我正在尝试创建一个包含WndProc的类,但是我收到了一个错误:
Error 2 error C2440: '=' : cannot convert from 'LRESULT (__stdcall Client::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
我在网上搜索它,看到你需要让WndProc保持静态,但是,它编译并且一切都很好,但是如果我想改变一些东西,它不会让我:
Error 3 error C2352: 'Client::CreateMen' : illegal call of non-static member function
(CreateMen是创建菜单的类中的一个函数,使用HMENU等)。
这是我的职称:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
我该怎么办?我真的很困惑......
谢谢!
答案 0 :(得分:16)
非静态类方法具有隐藏的this
参数。这就是阻止该方法用作WndProc(或任何其他API回调)的原因。您必须将类方法声明为static
才能删除该this
参数。但正如您已经注意到的那样,您无法从静态方法访问非静态成员。您需要一个指向该对象的指针才能访问它们。
在WndProc回调的特定情况下,您可以将对象指针存储在HWND本身中(使用SetWindowLong/Ptr(GWL_USERDATA)
或SetProp()
),然后您的静态方法可以从{检索该对象指针{1}}参数(使用hWnd
或GetWindowLong/Ptr(GWL_USERDATA)
)并根据需要使用该对象指针访问非静态成员。例如:
GetProp()
private:
HWND m_Wnd;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK Client::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Client *pThis;
if (msg == WM_NCCREATE)
{
pThis = static_cast<Client*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
SetLastError(0);
if (!SetWindowLongPtr(hwnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(pThis)))
{
if (GetLastError() != 0)
return FALSE;
}
}
else
{
pThis = reinterpret_cast<Client*>(GetWindowLongPtr(hwnd, GWL_USERDATA));
}
if (pThis)
{
// use pThis->member as needed...
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
答案 1 :(得分:2)
不幸的是,您不能将类函数用作wndproc,因为编译器试图告诉您调用约定有所不同,即使这两个函数具有相同的签名,类函数也希望将该指针传递给它。在64位版本中,它将期望它在RCX / ECX注册表中,而在32位版本中,它将期望该指针是在堆栈上推送的最后一个参数。调用WndProc时,窗口代码不会这样做,基本上将它转换为垃圾指针上的函数调用。
>做的是制作一个执行以下操作的静态方法:
LRESULT Client::CreateMen(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
// The OS makes sure GWLP_USERDATA is always 0 before being initialized by the application
Client* client = (Client*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(msg == WM_INIT)
{
client = new Client();
SetWindowLongPtr(hwnd, GWLP_USERDATA, client);
}
if(msg == WM_DESTROY)
{
client = (Client*)GetWindowLongPtr(hwnd, GWLP_USERDATA, client);
SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
delete client;
client = NULL;
}
if(client)
{
// Do stuff with the client instance
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
我没有对此进行过测试,因此可能会有一些错误,但如果您遇到任何问题请告诉我,如果需要,我会对其进行改进。