windows – 如何从WndProc内部获取窗口句柄?
也许是一个愚蠢的问题,但……
我正在编写一个类,应该注意保持一个Window(FGuestHWnd,从现在开始)视觉锚定到“主机窗口”(FHostHWnd). > FGuestHWnd和HostHWnd没有父/所有者/子关系. 现在我必须“挂钩”FHostHWnd的移动/调整大小并调用SetWindowPos(FGuestHWnd …在我的自定义计算之后. 调整大小非常简单:我可以使用SetWindowLong(FHostHWnd,GWL_WNDPROC,…)将FHostHWnd的WndProc“重定向”到我的自定义WindowPorcedure并捕获WM_WINDOWPOSCHANGING.当其中一个祖先调整大小时,此消息会自动发送到FHostHWnd,因为FHostHWnd是客户端对齐的. 移动,如果我没有遗漏某些东西,有点棘手,因为如果我移动主要形式FHostHWnd并没有真正感动.它保持相对于其父级的相同位置.因此,它不会以任何方式通知祖先的运动. 我的解决方案是将任何ANCESTOR的WndProc“重定向”到自定义窗口过程,并仅为“移动”消息捕获WM_WINDOWPOSCHANGING. 这里有一些代码来解释我的结构: TMyWindowHandler = class(TObject) private FHostAncestorHWndList: TList; FHostHWnd: HWND; FGuestHWnd: HWND; FOldHostAncestorWndProcList: TList; FNewHostAncestorWndProcList: TList; //... procedure HookHostAncestorWindows; procedure UnhookHostAncestorWindows; procedure HostAncestorWndProc(var Msg: TMessage); end; procedure TMyWindowHandler.HookHostAncestorWindows; var ParentHWnd: HWND; begin ParentHWnd := GetParent(FHostHWnd); while (ParentHWnd > 0) do begin FHostAncestorHWndList.Insert(0,Pointer(ParentHWnd)); FOldHostAncestorWndProcList.Insert(0,TFarProc(GetWindowLong(ParentHWnd,GWL_WNDPROC))); FNewHostAncestorWndProcList.Insert(0,MakeObjectInstance(HostAncestorWndProc)); Assert(FOldHostAncestorWndProcList.Count = FHostAncestorHWndList.Count); Assert(FNewHostAncestorWndProcList.Count = FHostAncestorHWndList.Count); if (SetWindowLong(ParentHWnd,LongInt(FNewHostAncestorWndProcList[0])) = 0) then RaiseLastOSError; ParentHWnd := GetParent(FHostHWnd); end; end; 这是The Handler: procedure TMyWindowHandler.HostAncestorWndProc(var Msg: TMessage); var pNew: PWindowPos; begin case Msg.Msg of WM_DESTROY: begin UnHookHostAncestorWindows; end; WM_WINDOWPOSCHANGING: begin pNew := PWindowPos(Msg.LParam); // Only if the window moved! if ((pNew.flags and SWP_NOMOVE) = 0) then begin // // Do whatever // end; end; end; Msg.Result := CallWindowProc(???,???,Msg.Msg,Msg.WParam,Msg.LParam ); end; 我的问题是: 当我最终调用CallWindowProc时,如何从WindowProcedure中获取Window Handle? 或者您是否建议其他解决方案? 请注意,我希望保持一切以HWND为导向,而不是VCL / TWinControl. 解决方法
我个人不会在这里使用MakeObjectInstance.如果您希望将实例绑定到单个窗口句柄,则MakeObjectInstance非常有用. MakeObjectInstance的神奇之处在于生成一个thunk,它将窗口过程调用转发给实例方法.在这样做时,窗口句柄不会传递给实例方法,因为假设实例已经知道其关联的窗口句柄.对于TWinControl来说,情况确实如此,这是MakeObjectInstance的主要用例.
现在,您将它绑定到多个窗口句柄.当实例方法执行时,您无法知道许多窗口句柄中的哪一个与此方法执行相关联.这是你问题的关键所在. 我的建议是放弃MakeObjectInstance,因为它无法满足您的需求.而是,定义此窗体的纯窗口过程: function WindowProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; 当你实现这样的窗口过程时,你会收到一个窗口句柄,如你所愿. 您可能需要保留TMyWindowHandler实例的全局列表,以便您可以查找与传递给窗口过程的窗口关联的TMyWindowHandler实例.或者,您可以使用 请注意,您对窗口进行子类化的方式存在各种问题.提供SetWindowSubclass函数是为了避免这些问题.更多细节:Subclassing Controls. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows – 如何检测COM对象实现的所有接口?
- windows-phone-7 – 如何同时为两个轴(X,Y)翻译动画?
- windows-installer – 任何人都有MSIINV.EXE的副本?
- WP7 - Runing App under the Locked Screen详述
- xaml – TextBlock中的多种颜色
- windows – rDesktop的最佳小型Linux发行版
- 如何使用Windows Server Task Scheduler在文件夹上的任何更
- windows 2008r2+php5.6.28环境搭建详细过程
- WPF.抓住最后一个窗口点击任意位置
- 如何在Windows应用程序中对加扰的数据包进行逆向工程?