如何将返回的WndProc/DlgProc句柄转换为函数地址?
在以下调用中,如何将返回的WndProc/DlgProc句柄转换为函数地址?,c,winapi,C,Winapi,在以下调用中,WndProc可以是: 有没有办法将其从用户模式代码转换为地址?你的问题没有真正意义。如果您在自己的代码中有窗口过程,更确切地说是在一个应用程序模块中,GetWindowLongPtr(hWnd,DWLP\u DLGPROC)将返回该地址。它仅在不存在显式窗口过程时返回句柄,然后返回 。。。仅对CallWindowProc有意义的特殊内部值 这意味着这些消息是由Windows内部代码直接处理的,您甚至不应该猜测(*):它是Windows系统私有的 (*)唯一的例外是,如果您正在构
WndProc
可以是:
有没有办法将其从用户模式代码转换为地址?你的问题没有真正意义。如果您在自己的代码中有窗口过程,更确切地说是在一个应用程序模块中,
GetWindowLongPtr(hWnd,DWLP\u DLGPROC)
将返回该地址。它仅在不存在显式窗口过程时返回句柄,然后返回
。。。仅对CallWindowProc有意义的特殊内部值
这意味着这些消息是由Windows内部代码直接处理的,您甚至不应该猜测(*):它是Windows系统私有的
(*)唯一的例外是,如果您正在构建一个低级库,就像从sysinternals中构建的库一样,它使用了未记录的函数和结构。您需要下一个代码:
PVOID pfn = (IsWindowUnicode(hwnd) ?
GetWindowLongPtrW : GetWindowLongPtrA)(hwnd, GWLP_WNDPROC);
因此,您需要根据IsWindowUnicode
的结果调用GetWindowLongPtrW
或GetWindowLongPtrA
注:
GetWindowLongPtrA(hwnd,GWLP\u-WNDPROC)
和GetWindowLongPtrW(hwnd,GWLP\u-WNDPROC)
-始终返回不同的结果-窗口过程的一个地址和另一个-表示窗口过程地址的句柄:仅对CallWindowProc
有意义的特殊内部值-用于确定哪个版本A或W检索窗口过程的地址-需要调用IsWindowUnicode
。这是无证的,但也是合理的。如果子类化过程与原始过程具有相同的ANSI或UNICODE本机,则它可以直接调用原始过程。如果本机不同-需要窗口消息的翻译(Unicode ANSI)(例如WM_GETTEXT
,WM_SETTEXT
)
GetWindowLongPtr(hwnd,GWLP\u WNDPROC)
必须返回与SetWindowLongPtr(hwnd,GWLP\u WNDPROC,(LONG\u PTR)NewWindowProc)相同的值
但是SetWindowLongPtrA
设置ansi窗口过程(即在WM_SETTEXT
中获取指向CHAR
字符串的指针)和SetWindowLongPtrW
设置unicode窗口过程(即在WM_SETTEXT
中获取指向WCHAR
字符串的指针)。因此,如果当前窗口过程和由SetWindowLongPtr
设置的新窗口过程具有相同的A或W,则新过程可以直接调用旧窗口过程,而无需翻译,并且SetWindowLongPtr
返回旧窗口过程的直接地址是绝对合理的。如果本机不同-(我们为W设置了A或为A设置了W)-新窗口过程不能直接调用旧窗口。在此之前,需要翻译一些windows消息(WM_GETTEXT
,WM_SETTEXT
,等等)。因为这个和句柄返回并CallWindowProc
在调用原始过程之前翻译消息
示例显示,根据当前窗口过程,IsWindowUnicode
可以为同一窗口返回不同的值,是ansi还是Unicode:
if (HWND hwnd = CreateWindowExA(0, WC_STATICA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) {
DbgPrint("IsWindowUnicode=%x\n", IsWindowUnicode(hwnd));
LONG_PTR l = GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
SetWindowLongPtrA(hwnd, GWLP_WNDPROC, l);
DbgPrint("IsWindowUnicode=%x\n", IsWindowUnicode(hwnd));
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, l);
DbgPrint("IsWindowUnicode=%x\n", IsWindowUnicode(hwnd));
DestroyWindow(hwnd);
}
和输出:
IsWindowUnicode=1
IsWindowUnicode=0
IsWindowUnicode=1
那么,我们怎么说呢
窗口的字符集由
寄存器类函数。如果窗口类已注册到
ANSI版本的注册表类(RegisterClassA),是
窗户是ANSI的。如果窗口类已注册到
字符集的Unicode版本RegisterClass(RegisterClassW)
窗口的名称是Unicode
不完全正确。它基于当前的窗口过程Ansi或Unicode。最初,这是基于注册类,但可以通过SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)NewWindowProc)来更改。
我不认为这个描述应该被理解为:“……所以你可以这样对待它”。它只是某种类型的值,只意味着要传递给(也不关心它是什么类型的)。为什么你需要知道?我闻到一个.existGetWindowLongPtrW
和GetWindowLongPtrA
基于Unicode或ansi的窗口过程-一个版本返回句柄,另一个过程返回句柄address@zett42-我不知道行动需要什么,但是,如果我们编写Spy++之类的工具(通过给定的windows句柄)来显示有关窗口的用户信息,以及窗口过程地址,则需要这样做。对于调试和研究,此信息非常有用,所以(IsWindowUnicode(hwnd)?GetWindowLongPtrW:GetWindowLongPtrA)(hwnd,GWLP_WNDPROC)代码>给你们确切的函数地址。若我们写一些工具,比如Spy++并想要显示具体窗口的窗口过程地址,那个么这个问题就有意义了——我们不需要调用窗口过程,而是显示它address@RbMm:谢谢你的理解。这个网站上有很多热门人物,他们渴望在不理解问题的情况下发表毫无意义和精辟的评论。你下面的答案是正确的。而且我今天刚学到了一些东西。很酷的东西!不管怎样,我今天刚学到一些东西。这太疯狂了。我不知道有人可以通过调用SetWindowLongPtr
@c0000fd-yes在创建ANSI窗口类后将其更改为Unicode窗口类类型(反之亦然)。可以文件在这一点上是不完整的。但是,您可以简单地运行和测试我的代码snippet@c00000fd-有人将WM_SETTEXT
发送到窗口。window proc必须获得指向WCHAR
或CHAR
文本字符串的指针?这取决于windows ansi或unicode的格式。但如果我们用SetWindowLongPtrX(hwnd,GWLP\u WNDPROC,(LONG\u PTR)NewWindowProc)对window进行子类化
,那么新过程必须使用ansi或unicode字符串?这必须基于初始窗口创建或基于SetWindowLongPtrA
vsSetWindowLongPtrW
?文件对此没有任何说明。总是需要想想你自己
IsWindowUnicode=1
IsWindowUnicode=0
IsWindowUnicode=1