在以下致电中,WndProc
可以是returned as a handle:
FARPROC pfn = (FARPROC)GetWindowLongPtr(hWnd,
DWLP_DLGPROC); //same with GWLP_WNDPROC
有没有办法将它从用户模式代码转换为地址?
答案 0 :(得分:2)
你需要下一个代码:
PVOID pfn = (IsWindowUnicode(hwnd) ?
GetWindowLongPtrW : GetWindowLongPtrA)(hwnd, GWLP_WNDPROC);
因此您需要根据GetWindowLongPtrW
GetWindowLongPtrA
或IsWindowUnicode
注意:GetWindowLongPtrA(hwnd, GWLP_WNDPROC)
和GetWindowLongPtrW(hwnd, GWLP_WNDPROC)
- 总是返回不同的结果 - 窗口过程的一个地址和另一个 - 表示窗口过程地址的句柄:特殊内部值仅对{{1}有意义} - 用于确定哪个版本 A 或 W 检索窗口过程的地址 - 需要调用CallWindowProc
。这是没有证件的,但是合理的。如果子类程序具有与原始程序相同的ANSI或UNICODE本机,它可以直接调用原始程序。如果本机不同 - 需要对窗口消息进行转换(Unicode< - > ANSI)(例如IsWindowUnicode
,WM_GETTEXT
..)。
事实上WM_SETTEXT
必须返回与GetWindowLongPtr(hwnd, GWLP_WNDPROC)
但是SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)NewWindowProc)
设置了ansi窗口过程(在SetWindowLongPtrA
中得到了指向CHAR
字符串的指针)和WM_SETTEXT
设置了unicode窗口过程(表示指向了SetWindowLongPtrW
中的WCHAR
字符串。因此,如果当前窗口过程和WM_SETTEXT
的新设置具有相同的 A 或 W - 新过程可以直接调用old,不进行转换,并且绝对合理{ {1}}返回旧Windows程序的直接地址。如果本机不同 - (我们为A设置A代表W或W代表) - 新窗口程序不能直接调用旧代码。在此之前,需要翻译一些Windows消息(SetWindowLongPtr
,SetWindowLongPtr
等)。因为这和句柄在调用原始程序之前返回并且WM_GETTEXT
翻译了消息。
示例显示WM_SETTEXT
可以为同一窗口返回不同的值 - 基于当前窗口过程 - 是ansi还是Unicode:
CallWindowProc
并输出:
IsWindowUnicode
所以说文档:
窗口的字符集是通过使用来确定的 RegisterClass 功能。如果窗口类已注册 ANSI版本的 RegisterClass ( RegisterClassA ),字符集 窗口是ANSI。如果窗口类已注册 Unicode版本的 RegisterClass ( RegisterClassW ),字符集 窗口是Unicode。
不完全正确。它基于当前窗口过程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
答案 1 :(得分:1)
你的问题没有意义。如果您在自己的代码中有窗口过程 - 更准确地说是在其中一个应用程序模块中 - GetWindowLongPtr(hWnd, DWLP_DLGPROC);
将返回该地址。它只返回一个句柄,当没有明确的窗口过程时,它就是
...一个特殊的内部值,仅对CallWindowProc有意义。
这意味着消息由Windows内部代码直接处理,您甚至不应该猜测(*):它是Windows系统专用的。
(*)唯一的例外是如果您正在构建一个低级库,就像那些使用未记录的函数和结构的sysinternals那样。