如何获取窗体中组件的句柄

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取窗体中组件的句柄相关的知识,希望对你有一定的参考价值。

一般用FindWindow。。。

Delphi中获取其它进程的窗口句柄,在Delphi中获取其它进程的窗口句柄,绝大部分人首先想到的会使用:FindWindow或者用GetWindow来遍历查找,如:

Delphi/Pascal code?
handle := FindWindow(nil,PChar('窗口的标题'));

或者:

Delphi/Pascal code?

procedure TForm1.Button1Click(Sender: TObject);
var
  hCurrentWindow: HWnd;
  WndText:String;
begin
  hCurrentWindow := GetWindow(Handle, GW_HWNDFIRST);
  while hCurrentWindow <> 0 do
  begin
    WndText:=GetWndText(hCurrentWindow);
    if UpperCase(WndText)='窗口的标题' then begin
      ...
      ...
    end;
    hCurrentWindow:=GetWindow(hCurrentWindow, GW_HWNDNEXT);
  end;
end;

因为目前网络上绝大部分的代码都是介绍用这两种方法取得其它进程的窗口句柄。虽这两种方法都可以达到查找其它进程的窗口句柄的目的,但本人认为这两都方法存在较大的弊端。因为这两种方法都是根据其它进程的标题来查找的,如果其它进程的标题在运行时不断的发生变化,那么这两种方法就无法没办法用了。

介绍第三种通过进程的文件名来查找窗口句柄。首先通过进程快照得到要查找的进程ID(ProcessId),其次,再跟据ProcessId获取进程的窗口句柄。以下为本文章的代码:

Delphi/Pascal code?
uses TLHelp32;

procedure TForm1.Button1Click(Sender: TObject);
var
ProcessName : string; //进程名
FSnapshotHandle:THandle; //进程快照句柄
FProcessEntry32:TProcessEntry32; //进程入口的结构体信息
ContinueLoop:BOOL;
MyHwnd:THandle;
begin
FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); //创建一个进程快照
FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32); //得到系统中第一个进程
//循环例举
while ContinueLoop do
begin
ProcessName := FProcessEntry32.szExeFile;

if(ProcessName = '要找的应用程序名.exe') then begin
MyHwnd := GetHWndByPID(FProcessEntry32.th32ProcessID);
...

...
end;
ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);
end;
CloseHandle(FSnapshotHandle); // 释放快照句柄
end;

//跟据ProcessId获取进程的窗口句柄

function TForm1.GetHWndByPID(const hPID: THandle): THandle;
type
PEnumInfo = ^TEnumInfo;
TEnumInfo = record
ProcessID: DWORD;
HWND: THandle;
end;

function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
var
PID: DWORD;
begin
GetWindowThreadProcessID(Wnd, @PID);
Result := (PID <> EI.ProcessID) or
(not IsWindowVisible(WND)) or
(not IsWindowEnabled(WND));

if not Result then EI.HWND := WND;
end;

function FindMainWindow(PID: DWORD): DWORD;
var
EI: TEnumInfo;
begin
EI.ProcessID := PID;
EI.HWND := 0;
EnumWindows(@EnumWindowsProc, Integer(@EI));
Result := EI.HWND;
end;
begin
if hPID<>0 then
Result:=FindMainWindow(hPID)
else
Result:=0;
end;

我说的是组件的句柄,不是窗体的句柄

findwindowex();获取指定句柄窗口下的子控件,当然是有句柄的控件

窗体的句柄都知道,还能不知道里面组件的句柄?——windows标准组件

procedure TForm1.Button2Click(Sender: TObject);
var
canvas1: TCanvas;
begin
Canvas1 := TCanvas.Create;

//这是OK。这真要感谢baidu,google
canvas1.Handle := GetDc(panel1.Handle);

canvas1.TextOut(1,1,'hello');
canvas1.Free ;
Form1.Canvas.TextOut(10, 10, 'fff');
end;

有的组件是没有句柄的
ShowMessage(IntToStr(TWinControl(Form1.FindChildControl('Panel1')).Handle));
参考技术A // 取得控件的指针
CWnd *pWnd = GetDlgItem(ID_***);
// 取得控件的句柄
HWND hwnd = pWnd->GetSafeHwnd();
参考技术B CWnd *pWnd = GetDlgItem(ID_***); // 取得控件的指针 HWND hwnd = pWnd->GetSafeHwnd(); // 取得控件的句柄 参考技术C Could I have a menu, please?

delphi获取窗体的句柄

两个独立的问题。
1.我想用ShellExecute命令运行外部程序(带有窗体),同时想获得这个窗体的句柄。补充:在实际中我想多次打开同个外部程序,并想通过句柄区分它们
2.在外部程序运行到指定的时候,执行某一条命令。
补充:比如,外部程序完全打开需要一定的时间,我想等其完全打开后再执行某一条语句。
谢谢了

参考技术A 要获取窗体句柄,必须createprocess,WaitForSingleObject等待结束后通过findwindow查找得到,你可以根据标题或者窗体类获得 参考技术B 两个程序都是自己写的吗?是的话弄个mutex启动后设置? 参考技术C 你百度一下delphi createprocess吧,你说的问题都可以用它解决?追问

谢谢你,我找了,通过参数lpProcessInformation获得进程的句柄,再通过WaitForSingleObject设置等待的时间实现了第二个目的。 但是createprocess中的参数lpProcessInformation只有进程和当前线程的句柄,还是没有窗体的句柄,请问怎么获得窗体的句柄,麻烦说详细点。 而且我发现用createprocess同时打开两次某一个外部程序,参数lpProcessInformation的hProcess和hThread在两次中是相同的,起不到区分打开先后的作用。

以上是关于如何获取窗体中组件的句柄的主要内容,如果未能解决你的问题,请参考以下文章

已知窗体的句柄,如何显示出此窗体 C#.ne

EnumChildWindows 如何得到子窗体句柄的集合? 求高人指点

delphi 如何获取其它应用程序窗体中的所有控件句柄

vb 将一个程序通过句柄设为了另一个程序的子窗体后句柄发生改变 如何获取该程序在父窗体的新句柄?

VC++中怎样获取到一个窗体的句柄?

vb如何获取到窗口的句柄