I have a Windows
class as follows:
struct PlatformState
{
HINSTANCE hInstance;
HWND WindowHandle;
};
class Win32Platform
{
public:
Win32Platform(const char* app_name, uint32 startX, uint32 startY, uint32 width, uint32 height);
~Win32Platform();
private:
PlatformState* PlatState;
const char* AppName;
uint32 StartPosX;
uint32 StartPosY;
uint32 Width;
uint32 Height;
LRESULT CALLBACK Win32ProcessMessage(HWND window_handle, uint32 msg, WPARAM w_param, LPARAM l_param);
};
When I am trying to create a constructor like this:
Win32Platform::Win32Platform(const char* app_name, uint32 startX, uint32 startY
, uint32 width, uint32 height)
: AppName(app_name), StartPosX(startX), StartPosY(startY), Width(width), Height(height)
{
PlatState = nullptr;
PlatState = (PlatformState *)malloc(sizeof(PlatformState));
PlatState->hInstance = GetModuleHandleA(0);
//Setup and Register Window Class
HICON icon = LoadIcon(PlatState->hInstance, IDI_APPLICATION);
WNDCLASSA WinClass;
WinClass.style = CS_DBLCLKS;
WinClass.lpfnWndProc = this->Win32ProcessMessage;
}
The driver code is basically:
Win32Platform window{"New", 100, 200, 1280, 720};
The get the error message
a pointer to a bound function may only be used to call the function
I need the function Win32ProcessMessage
as a member function because I need it to access certain class instance variables. I tried it with and without this
.
How can I fix this?
You can't use a non-static class method as a Win32 WndProc
callback, as the method has a hidden this
parameter which the API can't pass anything into.
To remove the this
parameter, you need to instead use a static class method, or a standalone function.
Then, you can use the lpParam
parameter of CreateWindow/Ex()
to pass your object's this
pointer into your callback. You can handle the WM_(NC)CREATE
message to receive the pointer, and then store it into the created HWND
via SetWindowLongPtr()
or SetProp()
. In subsequent messages, you can then retrieve the pointer from the HWND
to access the object as needed.
For example:
class Win32Platform
{
...
protected:
...
LRESULT ProcessMessage(uint32 msg, WPARAM w_param, LPARAM l_param);
...
private:
...
static LRESULT CALLBACK Win32ProcessMessage(HWND window_handle, uint32 msg, WPARAM w_param, LPARAM l_param);
...
};
WinClass.lpfnWndProc = &Win32Platform::Win32ProcessMessage;
...
CreateWindowEx(..., WinClass.lpszClassName, ..., this);
static LRESULT CALLBACK Win32Platform::Win32ProcessMessage(HWND window_handle, uint32 msg, WPARAM w_param, LPARAM l_param)
{
Win32Platform *plat;
if (msg == WM_NCCREATE) {
plat = (Win32Platform*) ((CREATESTRUCT*)l_Param)->lpCreateParams;
SetWindowLongPtr(window_handle, GWL_USERDATA, plat);
}
else {
plat = (Win32Platform*) GetWindowLongPtr(window_handle, GWL_USERDATA);
}
if (plat)
return plat->ProcessMessage(msg, w_param, l_Param);
return DefWindowProc(window_handle, msg, w_param, l_param);
}
LRESULT Win32Platform::ProcessMessage(uint32 msg, WPARAM w_param, LPARAM l_param)
{
...
}