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

如何获取窗体中组件的句柄,第1张

一般用FindWindow。。。

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

Delphi/Pascal code

handle := FindWindow(nil,PChar('窗口的标题'));

或者:

Delphi/Pascal code

procedure TForm1Button1Click(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 TForm1Button1Click(Sender: TObject);

var

ProcessName : string; //进程名

FSnapshotHandle:THandle; //进程快照句柄

FProcessEntry32:TProcessEntry32; //进程入口的结构体信息

ContinueLoop:BOOL;

MyHwnd:THandle;

begin

FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); //创建一个进程快照

FProcessEntry32dwSize:=Sizeof(FProcessEntry32);

ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32); //得到系统中第一个进程

//循环例举

while ContinueLoop do

begin

ProcessName := FProcessEntry32szExeFile;

if(ProcessName = '要找的应用程序名exe') then begin

MyHwnd := GetHWndByPID(FProcessEntry32th32ProcessID);

end;

ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);

end;

CloseHandle(FSnapshotHandle); // 释放快照句柄

end;

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

function TForm1GetHWndByPID(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 <> EIProcessID) or

(not IsWindowVisible(WND)) or

(not IsWindowEnabled(WND));

if not Result then EIHWND := WND;

end;

function FindMainWindow(PID: DWORD): DWORD;

var

EI: TEnumInfo;

begin

EIProcessID := PID;

EIHWND := 0;

EnumWindows(@EnumWindowsProc, Integer(@EI));

Result := EIHWND;

end;

begin

if hPID<>0 then

Result:=FindMainWindow(hPID)

else

Result:=0;

end;

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

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

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

procedure TForm1Button2Click(Sender: TObject);

var

canvas1: TCanvas;

begin

Canvas1 := TCanvasCreate;

//这是OK。这真要感谢baidu,google

canvas1Handle := GetDc(panel1Handle);

canvas1TextOut(1,1,'hello');

canvas1Free ;

Form1CanvasTextOut(10, 10, 'fff');

end;

有的组件是没有句柄的

ShowMessage(IntToStr(TWinControl(Form1FindChildControl('Panel1'))Handle));

这个可能是你想要的东东吧!

=========================

VB 遍历窗口所有子窗体句柄

Private Const GW_CHILD = 5

Private Const GW_HWNDFIRST = 0

Private Const GW_HWNDNEXT = 2

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long

Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long

Private Sub FillChild(hWndParent As Long)

Dim hWndChild As Long

Dim szCaption As String

Dim buffer As String

Dim i As Long

hWndChild = GetWindow(hWndParent, GW_CHILD)

If (hWndChild = 0) Then Exit Sub

hWndChild = GetWindow(hWndChild, GW_HWNDFIRST)

If hWndChild = 0 Then Exit Sub

While (hWndChild <> 0)

szCaption = String$(255, 0)

GetClassName hWndChild, szCaption, 250

szCaption = Left$(szCaption, InStr(szCaption, String$(1, 0)) - 1)

buffer = CStr(hWndChild) & "--" & szCaption

i = GetWindowTextLength(hWndChild)

szCaption = String$(255, 0)

GetWindowText hWndChild, szCaption, 250

szCaption = Left$(szCaption, i)

buffer = buffer & "--" & szCaption

List1AddItem buffer

FillChild hWndChild

hWndChild = GetWindow(hWndChild, GW_HWNDNEXT)

Wend

End Sub

Private Sub GetChildWindow(hwnd As Long)

Dim szCaption As String

Dim buffer As String

Dim i As Long

List1Clear

szCaption = String$(255, 0)

GetClassName hwnd, szCaption, 250

szCaption = Left$(szCaption, InStr(szCaption, String$(1, 0)) - 1)

buffer = CStr(hwnd)

buffer = buffer & "--" & szCaption

i = GetWindowTextLength(hwnd)

szCaption = String$(255, 0)

GetWindowText hwnd, szCaption, 250

szCaption = Left$(szCaption, i)

buffer = buffer & "--" & szCaption

List1AddItem buffer

FillChild hwnd

End Sub

调用方法

GetChildWindow hwnd'hwnd是指定的窗口句柄

结果以

窗体句柄--窗体类名称--窗体Text

形式列在列表框List1中

 先找到窗口的句柄,再来查找按钮的句柄,如果按钮有文本内容,那就好办,如果没有,那建议你利用SPY++先来察看一下按钮的类型,以此类型为查找参数多次调用FindWindowEx来查找,直到找到的的句柄和Spy++相同,那么这个按钮就找到了。

按钮类名同样,但是你去遍历的时候它的次序始终是固定的。通过id不可靠,有些有id但是有些id是0。

clswindow类,里面有个函数etElementHwndByClassName,可以得到指定的次序按钮。加入你要处理的按钮是在第二个次序,类名为Button,那么就用:GetElementHwndByClassName("Button",2),即可,

具体代码:

Private Sub Command6_Click()

Dim w As New clsWindow

Dim i%

If wGetWindowHwndByTitleEx("自动化 *** 作框架") > 0 Then

i = i + 1

Do While wGetElementHwndByClassName("ThunderCommandButton", i) > 0'按次序遍历

MsgBox wGetElementHwndByClassName("ThunderCommandButton", i)'得到当前次序按钮的句柄

wSetElementTextByClassName "ThunderCommandButton", "次序" & i, i'设置按钮文本

i = i + 1

Loop

End If

End Sub

有一程序在xp下能正常运行,在win 7下运行后就跳出 程序已停止工作。

用vs2008调试发现是

map2DView = new Map2DView(this);

句代码出现 了异常异常信息如下:

{SystemReflectionTargetInvocationException: 无法获取“AxXnLegendView”控件的窗口句柄。不支持无窗口的 ActiveX 控件。 ---> SystemAccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。<br> 在 SystemWindowsFormsUnsafeNativeMethodsIOleObjectDoVerb(Int32 iVerb, IntPtr lpmsg, IOleClientSite pActiveSite, Int32 lindex, IntPtr hwndParent, COMRECT lprcPosRect)<br> 在 SystemWindowsFormsAxHostDoVerb(Int32 verb)<br> 在 SystemWindowsFormsAxHostInPlaceActivate()<br> --- 内部异常堆栈跟踪的结尾 ---<br> 在 SystemWindowsFormsAxHostInPlaceActivate()<br> 在 SystemWindowsFormsAxHostTransitionUpTo(Int32 state)<br> 在 SystemWindowsFormsAxHostCreateHandle()<br> 在 SystemWindowsFormsControlCreateControl(Boolean fIgnoreVisible)<br> 在 SystemWindowsFormsControlCreateControl(Boolean fIgnoreVisible)<br> 在 SystemWindowsFormsAxHostEndInit()<br> 在 CGUDFGISProUDPView2DMap2DViewInitializeComponent()<br> 在 CGUDFGISProUDPView2DMap2DViewctor(Form mainForm)<br> 在 GISMapMainFormInitMapRelative() 位置 E:\Demo\DataCenter\GISMap\MainFormcs:行号 99}

AxXnLegendView 类的结构如下:

public class AxXnLegendView : AxHost

{

private IXnLegendView ocx;

public AxXnLegendView();

protected override void AttachInterfaces();

public virtual int bindLegendFrame(XnLegendFrame frame);

public virtual void exposeLegendFrame(out XnLegendFrame pLegendFrame);

public virtual void innerInit();

public virtual void refreshLegendView();

}

我没用过大话西游,说一下我的想法

可能是主窗口是封装在一个Frame里了,你用SPY++获得那个框架的句柄(如果,果真是封装在了Frame的话),然后在SPY++中切换到标签选项卡(SPY++22),去掉"窗口可见"勾选,这样就剥离掉了Frame的封装,然后你就可以继续用SPY++获得其内部控件的句柄了

一般就是用这个方法了,QQ登陆框也是这样的,号码框和密码框还有软键盘都封在Frame里了,只要隐藏到那个Frame,里面的控件就无可遁形了

要获得窗体/控件的句柄 你先用SPY++获得它的类名,如任务栏类名为 "Shell_TrayWnd",然后用FindWindow即可获得其句柄,如任务栏句柄

hWnd=FindWindow("Shell_TrayWnd", vbNullString)

其他窗体也是一样,只要用SPY++选获得窗体(或父窗体)类名,便可以步步用FindWindow或FindWindowEx获得其句柄

以上就是关于如何获取窗体中组件的句柄全部的内容,包括:如何获取窗体中组件的句柄、vb 获取窗口上多个控件的句柄,如何知道哪个是自己想要的、vb怎么获取控件句柄和内容等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9620995.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存