Based on this port, I'm trying to create a simple Win32 application, in which the window procedure/callback function of a dialog window is a member function of a class. My code looks like this:
H file:
class MyClass
{
public:
HINSTANCE hInstance;
HWND hWnd;
int APIENTRY WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
static LRESULT CALLBACK WinProcWraper(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
ATOM MyClassRegisterClass(HINSTANCE hInstance);
};
CPP file:
LRESULT CALLBACK MyClass::WinProcWraper(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
if (WM_NCCREATE == message)
{
SetWindowLong (hWnd, GWL_USERDATA, (long)((CREATESTRUCT*) lParam)->lpCreateParams);
return TRUE;
}
return ((MyClass*) GetWindowLong (hWnd, GWL_USERDATA))->WinProc (hWnd, message, wParam, lParam);
}
int APIENTRY MyClass::WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
MyClass.hInstance=hInstance;
MyClass.MyClassRegisterClass(hInstance);
//MY PROBLEM IS HERE: cannot convert parameter 4 to int
HWND hWnd = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_MAIN_DIALOG), 0, (DLGPROC)MyClass::WinProc);
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsWindow(hWnd) || !IsDialogMessage(hWnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK MyClass::WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
(...)
}
When calling CreateDialog(), I get the following error:
cannot convert from 'long (__stdcall MyClass::*)(struct HWND__ *,unsigned int,unsigned int,long)'
to 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)'
How can I make the correct type conversion in this case?
CodePudding user response:
Lets start with the error message. You are trying to use a non-static class method, WinProc(), as your CreateDialog() callback. That will not work. You went to the trouble of implementing a static class method, WinProcWraper(), which calls WinProc(), but you are not actually using it. You need to use WinProcWraper() as the actual window procedure for CreateDialog().
Also, there is no need to type-cast WinProcWraper when passing it to CreateDialog(), if its signature is correct to begin with (which yours is not).
After fixing that, you still have other problems:
the other code you are modeling after was designed for a window procedure for
CreateWindow/Ex(), but you are usingCreateDialog()instead, which has different requirements.Since you are using
CreateDialog()instead ofCreateWindow/Ex(),WinProcWraper()andWinProc()need to return aBOOLinstead of anLRESULT. If an actualLRESULTvalue needs to be returned to the system,WinProc()will need to useSetWindowLong(DWL_MSGRESULT)for that purpose.WinProcWraper()is expecting to receive aWM_NCCREATEmessage to deliver it aMyClass*pointer, which it will then assign to theHWND. But, since you are usingCreateDialog(),WinProcWraper()will not receive anyWM_(NC)CREATEmessages, it will receive aWM_INITDIALOGmessage instead. And even then,CreateDialog()does not allow you to pass any user-defined value to the window procedure, so you can't pass in theMyClass*pointer thatWinProcWraper()requires. You need to useCreateDialogParam()instead for that.WM_INITDIALOGmay not be the first message a window receives, just the first message that can give you access to theMyClass*pointer that you pass toCreateDialogParam().WinProcWraper()needs to handle the possibility that it can receive messages before it has received access to theMyClass*pointer.You are using
SetWindowLong(). Your code will not work if it is ever compiled for 64bit. UseSetWindowLongPtr()instead, even for 32bit code.
With that said, try this:
class MyClass
{
public:
HINSTANCE hInstance;
HWND hWnd;
int APIENTRY WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
BOOL CALLBACK WinProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
ATOM MyClassRegisterClass(HINSTANCE hInstance);
private:
static BOOL CALLBACK WinProcWraper(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
BOOL CALLBACK MyClass::WinProcWraper(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MyClass *cls;
if (WM_INITDIALOG == uMsg)
{
cls = reinterpret_cast<MyClass*>(lParam);
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(cls));
}
else
cls = reinterpret_cast<MyClass*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
if (cls)
return cls->WinProc(uMsg, wParam, lParam);
return FALSE;
}
int APIENTRY MyClass::WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
MyClass.hInstance = hInstance;
MyClass.MyClassRegisterClass(hInstance);
HWND hWnd = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, MyClass::WinProcWraper, reinterpret_cast<LPARAM>(this));
if (!hWnd)
return -1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsWindow(hWnd) || !IsDialogMessage(hWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
BOOL CALLBACK MyClass::WinProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
...
if (needed)
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, ...);
return ...; // TRUE or FALSE as needed...
}
