如何将信息传递到使用Winapi创建的窗口Proc

发布于 2025-01-19 13:49:56 字数 793 浏览 0 评论 0原文

我需要创建一个用于处理消息的窗口(WM_HOTKEY),因此我在以下方面的水平较低,并使用setWindowlong将实例信息传递到WindowProc中。

fWindow:=CreateWindowEx(WS_EX_TOOLWINDOW,MsgWndClass.lpszClassName,'',WS_POPUP,0,0,0,0,0,0,HInstance,nil);
SetWindowLong(fWindow,GWL_USERDATA,NativeInt(Self));


class function TMessageWindow.WindowProc(hWnd: HWND; uMsg: Integer; wParam: WPARAM; lParam: LPARAM): Integer;
begin
  var I:=GetWindowLong(hWnd,GWL_USERDATA);
  if I=0 then
    Exit(DefWindowProc(hWnd,uMsg,wParam,lParam));

  Result:=TMessageWindow(I).HandleMessage(uMsg,wParam,lParam);
end;

当我尝试从tmessagewindow创建一个带有handlemessage的继承类时,我的问题就会出现。 我发现,尽管在继承的类中,处理函数被超越,但tmessagewindow(i)的类型正在调用基本方法。

在寻找此示例的示例之后,我找不到任何使用setWindowlong函数将信息传递给WindowProc的示例,因此现在我认为必须有更好的方法。

I needed to create a window for handling messages (WM_HOTKEY) so I went about going low level with the following and using SetWindowLong to pass the instance information for use in the windowproc.

fWindow:=CreateWindowEx(WS_EX_TOOLWINDOW,MsgWndClass.lpszClassName,'',WS_POPUP,0,0,0,0,0,0,HInstance,nil);
SetWindowLong(fWindow,GWL_USERDATA,NativeInt(Self));

and the windowproc is

class function TMessageWindow.WindowProc(hWnd: HWND; uMsg: Integer; wParam: WPARAM; lParam: LPARAM): Integer;
begin
  var I:=GetWindowLong(hWnd,GWL_USERDATA);
  if I=0 then
    Exit(DefWindowProc(hWnd,uMsg,wParam,lParam));

  Result:=TMessageWindow(I).HandleMessage(uMsg,wParam,lParam);
end;

My issues arise when I tried to create an inherited class from TMessageWindow with HandleMessage being virtual.
I found that although the HandleMessage function was overriden in the inherited class, the typecast of TMessageWindow(I) was calling the base method.

After searching around looking for an example of this I could not find any examples of people using the SetWindowLong function to pass information to the windowproc so am now thinking there must be a better way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小ぇ时光︴ 2025-01-26 13:49:56

首先,请确保您的方法也标记为static以删除隐藏的self参数,并使用stdcall < /code>调用约定,如果您还没有这样做,例如:

class function WindowProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; static;

之后,如果您要编译64位,则代码需要使用(get | set)windowlongptr()而不是:

private
  fWindow: HWND;
fWindow := ...;
SetWindowLongPtr(fWindow, GWLP_USERDATA, LONG_PTR(Self));
class function TMessageWindow.WindowProc(hWnd: HWND; uMsg: Integer; wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
begin
  var I := GetWindowLongPtr(hWnd, GWLP_USERDATA);
  if I <> 0 then
    Result := TMessageWindow(I).HandleMessage(uMsg, wParam, lParam)
  else
    Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
end;

另外,请使用 相反,例如:

private
  fWindow: HWND;
  class function SubclassWindowProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM; uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall; static;
uses
  ..., Commctrl;

fWindow := ...;
SetWindowSubclass(fWindow, @TMessageWindow.SubclassWindowProc, 1, DWORD_PTR(Self));
class function TMessageWindow.SubclassWindowProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM; uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall;
begin
  if uMsg = WM_NCDESTROY then
    RemoveWindowSubclass(hWnd, @TMessageWindow.SubclassWindowProc, uIdSubclass);
  Result := TMessageWindow(dwRefData).HandleMessage(uMsg, wParam, lParam);
  // have HandleMessage() call DefSubclassProc() for any unhandled messages...
end;

说,使用虚拟消息过程创建消息窗口的一种更简单的方法是使用rtl的 allocateHwnd() 函数,例如:

private
  fWindow: HWND;
  procedure HandleMessage(var Message: TMessage); virtual;
// to create the window:
fWindow := AllocateHWnd(HandleMessage);
// to destroy the window:
DeallocateHWnd(fWindow);
procedure TMessageWindow.HandleMessage(var Message: TMessage);
begin
  with Message do
    Result := DefWindowProc(fWindow, Msg, WParam, LParam);
end;

First off, make sure your class method is also marked as static to remove the hidden Self parameter, and is using the stdcall calling convention, if you haven't already done so, eg:

class function WindowProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; static;

After that, if you are compiling for 64bit, your code needs to use (Get|Set)WindowLongPtr() instead, eg:

private
  fWindow: HWND;
fWindow := ...;
SetWindowLongPtr(fWindow, GWLP_USERDATA, LONG_PTR(Self));
class function TMessageWindow.WindowProc(hWnd: HWND; uMsg: Integer; wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
begin
  var I := GetWindowLongPtr(hWnd, GWLP_USERDATA);
  if I <> 0 then
    Result := TMessageWindow(I).HandleMessage(uMsg, wParam, lParam)
  else
    Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
end;

Alternatively, use SetWindowSubclass() instead, eg:

private
  fWindow: HWND;
  class function SubclassWindowProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM; uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall; static;
uses
  ..., Commctrl;

fWindow := ...;
SetWindowSubclass(fWindow, @TMessageWindow.SubclassWindowProc, 1, DWORD_PTR(Self));
class function TMessageWindow.SubclassWindowProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM; uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall;
begin
  if uMsg = WM_NCDESTROY then
    RemoveWindowSubclass(hWnd, @TMessageWindow.SubclassWindowProc, uIdSubclass);
  Result := TMessageWindow(dwRefData).HandleMessage(uMsg, wParam, lParam);
  // have HandleMessage() call DefSubclassProc() for any unhandled messages...
end;

That being said, an easier way to create a message window with a virtual message procedure is to use the RTL's AllocateHWnd() function instead, eg:

private
  fWindow: HWND;
  procedure HandleMessage(var Message: TMessage); virtual;
// to create the window:
fWindow := AllocateHWnd(HandleMessage);
// to destroy the window:
DeallocateHWnd(fWindow);
procedure TMessageWindow.HandleMessage(var Message: TMessage);
begin
  with Message do
    Result := DefWindowProc(fWindow, Msg, WParam, LParam);
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文