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 aBOOL
instead of anLRESULT
. If an actualLRESULT
value needs to be returned to the system,WinProc()
will need to useSetWindowLong(DWL_MSGRESULT)
for that purpose.WinProcWraper()
is expecting to receive aWM_NCCREATE
message to deliver it aMyClass*
pointer, which it will then assign to theHWND
. But, since you are usingCreateDialog()
,WinProcWraper()
will not receive anyWM_(NC)CREATE
messages, it will receive aWM_INITDIALOG
message 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_INITDIALOG
may 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...
}