WndProc 的简单映射到您特定的 Class WndProc - 第 1 部分






3.78/5 (13投票s)
将所有 WndProc 消息映射到您类的消息处理程序。最简单的方法。第 1 部分。
引言
这是我的第一篇文章,所以请原谅您可能发现的任何新手行为。
我一直在阅读许多关于从 WndProc
函数到您自己的消息处理程序的消息映射的文章,所有文章都需要一些复杂或只是愚蠢的东西。所以,我开始寻找一种以非常简单的方式并以尽可能少的代码来实现这一点的方法。我提出的方法让我非常满意,我希望它也能让您满意。
设置
首先,我们需要创建窗口。我不会深入研究完成此操作所需的所有代码,因为还有许多其他优秀的文章描述了每个步骤,并提供了比我更好的建议。
您需要做的只是在您的创建函数中放入一个简单的代码行,以允许整个过程工作。
if (hwnd == NULL) {
MessageBox("CreateWindowEx() Failed!", "Debug", NULL, MB_OK);
return false;
}
// Adds a pointer to your current class to the WndClassEx structure
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
ShowWindow(hwnd, SW_NORMAL);
UpdateWindow(hwnd);
这里重要的行是
SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong);
我们所做的只是传入我们刚刚创建的窗口的句柄(在本例中为 hwnd
),为其提供我们想要更改的参数的标志(在本例中为 GWLP_USERDATA
),最后是类的指针((LONG_PTR)this
- 由于函数原型,需要进行类型转换)。此函数将允许我们在稍后检索类的指针。
WndProc
现在我们已经保存了指针,我们可以恢复它并使用它来重新路由我们的消息。
LRESULT CALLBACK Win::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
// Recover the pointer to our class, don't forget to type cast it back
CWin* winptr = (CWin*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
// Check if the pointer is NULL and call the Default WndProc
if (winptr == NULL) {
return DefWindowProc(hwnd, message, wParam, lParam);
} else {
// Call the Message Handler for my class (MsgProc in my case)
return winptr->MsgProc(hwnd, message, wParam, lParam);
}
}
这看起来很多,但所有这些代码都很简单。首先,我们调用 GetWindowLongPtr(HWND hWnd, int nIndex)
来恢复我们类的指针。不要忘记,由于它存储为 long*
,我们必须将其类型转换回我们类的类型。现在,我们只需检查以确保指针不是 NULL
。如果是,则调用默认的 WndProc
。如果不是 NULL
,则从我们的类中调用我们的消息处理函数。您可以将您类中的函数设置为您想要的任何原型,并传递您想要的任何参数。只需记住具有 LRESULT
的返回类型并返回您函数的结果。例如,这是我的 MsgProc
函数。
virtual LRESULT MsgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case (WM_CLOSE):
DestroyWindow(hwnd);
return 1;
break;
case (WM_DESTROY):
if (!GetParent(hwnd)) {
PostQuitMessage(0);
}
return 1;
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
我将我的函数设置为 virtual
以允许我在我的类层次结构中继承它,但这不是必需的。我确实让默认情况返回默认的 WndProc
,这对于 WndProc
来说很常见。