在运行时更改HWND窗口过程
Changing HWND Window Procedure in runtime
我正在创建hwnd
及其各自的WndProc
LRESULT CALLBACK
的IDE中工作。我需要将WndProc
更改为自定义的。
我读到SetWindowLong
会做这项工作,但我找不到任何工作的例子。例如:
HWND hwnd; //My window
SetWindowLong(hwnd, GWL_WNDPROC, myNewWndProc);
SetWindowLong
的第三个参数是Long
,作为函数的名称。如何从WndProc
函数引用到Long
?
My WndProc
:
LRESULT CALLBACK WndProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
msg_dev(toString(uMsg));
switch(uMsg){
case WM_MOUSEMOVE:
SetCursor(LoadCursor(NULL, IDC_HAND));
break;
case WM_LBUTTONDOWN:
msg_dev("Button down!");
break;
default:
DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
};
您需要使用如下内容:
WNDPROC prevWndProc;
...
prevWndProc = (WNDPROC) SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)&myNewWndProc);
...
LRESULT CALLBACK myNewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
msg_dev(toString(uMsg));
switch(uMsg)
{
case WM_MOUSEMOVE:
SetCursor(LoadCursor(NULL, IDC_HAND));
break;
case WM_LBUTTONDOWN:
msg_dev("Button down!");
break;
}
return CallWindowProc(prevWndProc, hwnd, uMsg, wParam, lParam);
}
查看本文:
当你子类化一个窗口时,它是窗口的原始窗口过程当你想调用原始窗口过程时你必须调用的子类
话虽这么说,你应该使用SetWindowSubclass()
而不是SetWindowLongPtr()
。让它为你处理这件事。更多详细信息请参阅本文:
安全子类化例如:
#define MY_SUBCLASS_ID 1
SetWindowSubclass(hwnd, &mySubClassProc, MY_SUBCLASS_ID, 0);
...
LRESULT CALLBACK mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
msg_dev(toString(uMsg));
switch(uMsg)
{
case WM_MOUSEMOVE:
SetCursor(LoadCursor(NULL, IDC_HAND));
break;
case WM_LBUTTONDOWN:
msg_dev("Button down!");
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, &mySubClassProc, uIdSubclass);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
一个简单的强制转换就可以完成这项工作。
SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)&myNewWndProc);
否则将是不兼容的类型:LRESULT和LONG。
SetWindowLong()
的MSDN文档说明GWL_WNDPROC
为窗口过程设置一个新地址。
这意味着第三个形参应该是指向函数的指针。因此,您的SetWindowLong()
调用应该像这样:
SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR)&myNewWndProc);
还要注意注释部分,它声明:
应用程序必须通过调用CallWindowProc将任何未被新窗口过程处理的消息传递给前一个窗口过程。
你可以使用setWindowLong来解决你的问题。
setWindowLong(hwnd,GWL_WNDPROC,(LONG)newWindowProcedure);
但是,您将设置两次窗口过程。一次使用IDE默认设置,然后使用您的默认设置。当窗口被注册时,你需要做的是设置窗口过程。
#include <windows.h>
void registerWindow();
void createWindow();
void messageLoop();
int main()
{
registerWindow();
createWindow();
messageLoop();
}
LRESULT CALLBACK myWindowProcedure(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
return DefWindowProc(hwnd,msg,wparam,lparam);
}
void registerWindow()
{
/** This is the important part.
* Find this part in your code.
* Set WNDCLASS::lpfnWndProc to what ever
* window procedure you want.
**/
WNDCLASS wc = {};
wc.lpfnWndProc = myWindowProcedure;
wc.hInstance = hInstance;
wc.lpszClassName = "CLASS NAME";
RegisterClass(&wc);
// WARNING: Your app will crash at runtime if the
// windows procedure is "NOT PROPER"
}
void createWindow()
{
auto hwnd = CreateWindowEx(
0, // Optional window styles.
"CLASS NAME", // Window class
"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
HINSTANCE(), // Instance handle
NULL // Additional application data
);
ShowWindow(hwnd, nCmdShow
}
void messageLoop()
{
MSG msg;
while( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
您必须使用SetWindowLongPtr(它在32位上是一个宏,但在64位上是一个单独的函数)来确保与32位和64位系统的兼容性。
语法如下:
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)&myNewWndProc);
- 递归函数计算序列中的平方和(并输出过程)
- 如何在Qt窗口小部件中使用QStringView(或QStringRef)
- 问:如何使用C++中的按钮从窗口打开窗口
- SDL 窗口不会弹出
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- 如何在cpp文件之间切换窗口?在Qt中
- QuadTree只在窗口的右上角绘制
- 如何在窗口过程方法中检测击键?
- 如何拒绝一个叫做的过程以写入继承的控制台窗口
- 在窗口过程包装器中阅读访问违规
- 查询/查找启动过程窗口
- 背景过程没有窗口
- 窗口/对话框过程可以在名称空间中吗
- 在类中包装窗口过程
- 挂接WH_CALLWNDPROC后未获取窗口过程消息
- WNDPROC窗口回调过程中接收到的句柄与CreateWindow返回的句柄之间的差异
- 在运行时更改HWND窗口过程
- 消息处理程序未调用窗口过程
- 静态指针不会在子类化窗口过程中初始化?
- 我可以有主窗口过程作为一个lambda在WinMain