如何将返回的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
有意义的特殊内部值-用于确定哪个版本AW检索窗口过程的地址-需要调用
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
设置的新窗口过程具有相同的AW,则新过程可以直接调用旧窗口过程,而无需翻译,并且
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版本RegisterClassRegisterClassW) 窗口的名称是Unicode


不完全正确。它基于当前的窗口过程Ansi或Unicode。最初,这是基于注册类,但可以通过SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)NewWindowProc)来更改。

我不认为这个描述应该被理解为:“……所以你可以这样对待它”。它只是某种类型的值,只意味着要传递给(也不关心它是什么类型的)。为什么你需要知道?我闻到一个.exist
GetWindowLongPtrW
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
vs
SetWindowLongPtrW
?文件对此没有任何说明。总是需要想想你自己
IsWindowUnicode=1
IsWindowUnicode=0
IsWindowUnicode=1