This question already has an answer here:
I'm trying to make a little class that displays console window in parent window. (you can imagine chat or debug info being displayed there)
Now, since diferent instanes do have different private variables (such as message array or parent window), I need to use non-static method as callback for the Windows events.
I have thought of ways, where I'd pass the actual class instance to static callback function and then called the proper method on it, but in winAPI, everything is done using TranslateMessage
and DispatchMessage
giving me no chance to use arguments of my own.
I found some code here: Class method as winAPI callback, but I don't understand it, and I think it is not exactly what I need. If it is, then please give me further explanation of code provided.
Error I get:
error: argument of type 'LRESULT (
WindowConsole::
)(HWND__, UINT, WPARAM, LPARAM)' does not match 'LRESULT (*
)(HWND__, UINT, WPARAM, LPARAM)'
I don't know what that star in brackets means, but this is what does not match.
And the code:
class WindowConsole {
char messages[255][255];
HWND mainWindow;
public:
int width;
int height;
inline HWND create(HWND parent);
inline bool update();
inline LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
};
HWND WindowConsole::create(HWND parent) {
HINSTANCE inst = GetModuleHandle (0);
WNDCLASSEX wincl;
/* The Window structure */
wincl.hInstance = inst;
wincl.lpszClassName = "ConsoleClass";
wincl.lpfnWndProc = this->WndProc; /* This function is called by windows */
/* more WNDCLASSEX crap...*/
mainWindow = CreateWindow (
/*PARAMS*/
);
ShowWindow(mainWindow,1);
return mainWindow;
}
bool WindowConsole::update() {
return true;
}
LRESULT CALLBACK WindowConsole::WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) /* handle the messages */
{
/*EVENT crap*/
}
return 0;
}
I use a simple solution. The winproc is a template function. The message receiver is inside setwindowptr.
If the receiver has a function with the message name , for instance, onpaint , then the wm_paint is included at message switch.
http://www.thradams.com/codeblog/wndproc.htm
The usual is something on this order:
With this, you derive a class from BaseWindow. In your derived class, you provide a "WindowProc" that overrides the (pure virtual) one in BaseWindow. The trick here is fairly simple: since you can't pass a parameter directly, you store the address of the class in the window's GWLP_USERDATA, then in the window proc (try to) retrieve that and use it to call the derived class' virtual window proc.
As an aside, note that this is a sketch, not a finished work (so to speak). Though it should compile as-is, the result won't actually work unless you fill in a fair number of pieces that aren't here (e.g., the other fields of the WNDCLASS structure being only one of the most obvious).
The other question you linked to only applies partially.
The WindowProc method does need to be static. Then right after the call to CreateWindowEx call SetWindowLongPtr with GWLP_USERDATA as the second parameter and this as the third one. That associates the HWND with the class instance. Then in the static WindowProc method call GetWindowLongPtr (again with GWLP_USERDATA) to get the WindowConsole instance that received the UI event.
That's all explained in detail here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff381400(v=vs.85).aspx