如何从WndProc内部获取窗口句柄?

扬基

也许是一个愚蠢的问题,但是...

我正在编写一个class应该注意将Window(FGuestHWnd从现在开始)保持在视觉上锚定到“宿主窗口”(FHostHWnd)的方法。

  • FGuestHWnd并且HostHWnd没有父母/所有者/孩子的关系。
  • FGuestHWnd 属于另一个进程-不在乎。
  • FHostHWnd是VCL的Window句柄TWinControl,因此它是我的进程内的子窗口。它可以位于“父级/子级”树中的任何级别。例如,假设它是一个TPanel

现在,我必须“ hook”FHostHWnd移动/调整大小并SetWindowPos(FGuestHWnd...在自定义计算后调用

调整大小很简单:我可以SetWindowLong(FHostHWnd, GWL_WNDPROC, ...)用来将FHostHWndWndProc重定向到我的自定义WindowPorcedure和trap WM_WINDOWPOSCHANGING当此消息FHostHWnd的祖先之一被调整大小时,该消息将自动发送到该消息,因为它FHostHWnd是与客户对齐的。

移动,如果我没有丢失任何东西,会有些棘手,因为如果我移动主窗体,FHostHWnd则不会真正移动它。相对于其父代,它保持相同的位置。因此,不会以任何方式通知祖先的移动。

我的解决方案是将“任何祖先”的WndProc“重定向”到自定义的“窗口过程”,并仅将WM_WINDOWPOSCHANGING捕获为“移动”消息。在这种情况下,我可以FHostHWnd通过自定义消息进行通知我班上的一些字段将跟踪Win Handles,原始WndProc地址和新WndProc地址的链。

这是一些代码来解释我的结构:

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, GWL_WNDPROC, LongInt(FNewHostAncestorWndProcList[0])) = 0) then
      RaiseLastOSError;
    ParentHWnd := GetParent(FHostHWnd);
  end;
end;

这是处理程序:

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;

我的问题是

最终调用时,如何从WindowProcedure内部获取窗口句柄CallWindowProc
(如果有Window Handle,也可以在中找到它FOldHostAncestorWndProcList,然后在中找到正确的Old-WndProc指针FHostAncestorHWndList),或者,如何获取CURRENT方法指针,以便可以在其中找到它并在中FNewHostAncestorWndProcList查找HWND FHostAncestorHWndList

还是您建议其他解决方案?

请注意,我想保留所有面向HWND的功能,而不是VCL / TWinControl意识的。
换句话说,我的应用程序仅应实例化TMyWindowHandler并将两个值HWND(主机和来宾)传递给它

戴维·赫弗南

我个人不会MakeObjectInstance在这里使用MakeObjectInstance如果您希望将实例绑定到单个窗口句柄,则很有用。的神奇之处MakeObjectInstance在于生成了一个thunk,可以将窗口过程调用转发给实例方法。并且这样做时,窗口句柄不会传递给实例方法,因为假设是实例已经知道其关联的窗口句柄。当然是TWinControl的主要用例MakeObjectInstance

现在,您将其绑定到多个窗口句柄。当实例方法执行时,您无法知道与该方法执行相关联的是多个窗口句柄中的哪个。那就是您问题的症结所在。

我的建议是放弃,MakeObjectInstance因为它不能满足您的需求。而是定义这种形式的普通窗口过程:

function WindowProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; 
  lParam: LPARAM): LRESULT; stdcall;

当您像这样实现窗口过程时,您确实会收到一个窗口句柄。

您可能需要保留TMyWindowHandler实例的全局列表,以便可以查找TMyWindowHandler与传递给窗口过程的窗口关联实例。或者,您可以用来SetProp将某些数据与窗口关联。

请注意,对窗口进行子分类的方式存在各种问题。SetWindowSubclass提供功能是为了避免这些问题。此处有更多详细信息:控件的子类化

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何获取VBA MsgBox的窗口句柄?

来自分类Dev

如何获取弹出窗口的句柄(WebdriverIO)

来自分类Dev

如何获取VBA MsgBox的窗口句柄?

来自分类Dev

定义重写的WndProc方法后,“错误创建窗口句柄”

来自分类Dev

如何在Windows 10的窗口中获取TextBox控件的句柄

来自分类Dev

如何从Chrome扩展程序获取窗口句柄(int)?

来自分类Dev

Matlab图形窗口-获取句柄

来自分类Dev

在PyGI中获取窗口句柄

来自分类Dev

硒中的获取窗口句柄

来自分类Dev

通过句柄或pid获取子窗口的窗口

来自分类Dev

获取光标下方窗口的窗口句柄

来自分类Dev

如何获取显示隐藏的系统任务栏图标的窗口的隐藏窗口句柄

来自分类Dev

当我们只知道窗口的句柄时如何获取窗口的图像

来自分类Dev

WinAPI-获取窗口句柄的所有控件句柄

来自分类Dev

获取最小化窗口的句柄?

来自分类Dev

尝试获取进程的窗口句柄的异常消息

来自分类Dev

Python Selenium获取当前窗口句柄

来自分类Dev

Xlib,C ++-获取窗口句柄(SendEvent,...)

来自分类Dev

Xlib,C ++-获取窗口句柄(SendEvent,...)

来自分类Dev

如何在Powershell中通过进程获取所有窗口句柄?

来自分类Dev

Tesseract OCR:如何在不先保存文件的情况下直接从窗口句柄获取文本

来自分类Dev

从窗口句柄首次打开时,如何获取Windows应用程序的原始大小?

来自分类Dev

如何获取进程的文件句柄?

来自分类Dev

如何从函数内部访问MATLAB GUI句柄

来自分类Dev

无法获取Windows Internet Explorer主窗口的句柄

来自分类Dev

获取没有名称的窗口的句柄

来自分类Dev

获取SDL 2应用程序的窗口句柄

来自分类Dev

如何使用JAVA获取sessionStorage的句柄

来自分类Dev

等待任务时如何获取它的句柄

Related 相关文章

  1. 1

    如何获取VBA MsgBox的窗口句柄?

  2. 2

    如何获取弹出窗口的句柄(WebdriverIO)

  3. 3

    如何获取VBA MsgBox的窗口句柄?

  4. 4

    定义重写的WndProc方法后,“错误创建窗口句柄”

  5. 5

    如何在Windows 10的窗口中获取TextBox控件的句柄

  6. 6

    如何从Chrome扩展程序获取窗口句柄(int)?

  7. 7

    Matlab图形窗口-获取句柄

  8. 8

    在PyGI中获取窗口句柄

  9. 9

    硒中的获取窗口句柄

  10. 10

    通过句柄或pid获取子窗口的窗口

  11. 11

    获取光标下方窗口的窗口句柄

  12. 12

    如何获取显示隐藏的系统任务栏图标的窗口的隐藏窗口句柄

  13. 13

    当我们只知道窗口的句柄时如何获取窗口的图像

  14. 14

    WinAPI-获取窗口句柄的所有控件句柄

  15. 15

    获取最小化窗口的句柄?

  16. 16

    尝试获取进程的窗口句柄的异常消息

  17. 17

    Python Selenium获取当前窗口句柄

  18. 18

    Xlib,C ++-获取窗口句柄(SendEvent,...)

  19. 19

    Xlib,C ++-获取窗口句柄(SendEvent,...)

  20. 20

    如何在Powershell中通过进程获取所有窗口句柄?

  21. 21

    Tesseract OCR:如何在不先保存文件的情况下直接从窗口句柄获取文本

  22. 22

    从窗口句柄首次打开时,如何获取Windows应用程序的原始大小?

  23. 23

    如何获取进程的文件句柄?

  24. 24

    如何从函数内部访问MATLAB GUI句柄

  25. 25

    无法获取Windows Internet Explorer主窗口的句柄

  26. 26

    获取没有名称的窗口的句柄

  27. 27

    获取SDL 2应用程序的窗口句柄

  28. 28

    如何使用JAVA获取sessionStorage的句柄

  29. 29

    等待任务时如何获取它的句柄

热门标签

归档