Use the object method as a WinApi WndProc callback

I am trying to create a small class displaying a console window in a parent window. (you can imagine that chat or debug information is displayed there)
Now, since different instances have different private variables (such as an array of messages or a parent window), I need to use the non-static method as a callback for Windows events.
I was thinking of ways when I passed the actual instance of the class to a static callback function and then called the proper method on it, but in winAPI everything is done using TranslateMessage and DispatchMessage , which prevents me from using my arguments. I found the code here: The class method as a winAPI callback , but I do not understand this, and I think that this is not quite what I need. If so, please give me a further explanation of the code provided.
Error:

error : argument of type 'LRESULT ( WindowConsole:: (HWND__, UINT, WPARAM, LPARAM)' does not match 'LRESULT ( * ) (HWND__, UINT, WPARAM, LPARAM)'

I do not know what this star means in brackets, but this is what does not correspond.
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; } 
+6
source share
3 answers

The usual thing is something in this order:

 #include <windows.h> class BaseWindow { static LRESULT CALLBACK internal_WndProc(HWND hWnd, int msg, WORD wParam, LONG lParam) { BaseWindow *c = (BaseWindow *)GetWindowLong(hWnd,GWLP_USERDATA); if (c == NULL) return DefWindowProc(hWnd, msg, wParam, lParam); return c->WindowProc(hWnd, msg, wParam, lParam); } public: virtual int WindowProc(HWND hWnd, int msg, WPARAM wParam, LPARAM lParam) = 0; BaseWindow(HINSTANCE instance) { WNDCLASS window_class = {0}; HWND window; HMENU my_menu; window_class.lpfnWndProc = (WNDPROC)internal_WndProc; /* fill in window_class here */ RegisterClass(&window_class); window = CreateWindow( "My Application", "Stupidity", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, my_menu, instance, NULL); // save the address of the class as the Window USERDATA. SetWindowLong(window, GWLP_USERDATA, (long)this); } }; 

In doing so, you get a class from BaseWindow. In a derived class, you provide a "WindowProc" that overrides (pure virtual) in BaseWindow. The trick here is quite simple: since you cannot pass the parameter directly, you store the class address in the GWLP_USERDATA window, then in the proc window (try) to extract it and use the proc window to call the virtual class of the derived class.

Note that this is a sketch, not a completed work (so to speak). Although it should compile as is, the result will not actually work unless you fill in quite a few pieces that are not here (for example, other fields of the WNDCLASS structure are only one of the most obvious).

+9
source

Another question related to you concerns only partially.

The WindowProc method must be static. Then immediately after calling CreateWindowEx, SetWindowLongPtr is called with GWLP_USERDATA as the second parameter and this one as the third. This binds HWND to an instance of the class. Then, in the static WindowProc method, call GetWindowLongPtr (again with GWLP_USERDATA) to get the WindowConsole instance that received the user interface event.

All of this is described in detail here:

http://msdn.microsoft.com/en-us/library/windows/desktop/ff381400(v=vs.85).aspx

+4
source

I am using a simple solution. Winproc is a template function. The message receiver is inside setwindowptr.

If the recipient has a function with the message name, for example, onpaint, then wm_paint is included in the message switch.

http://www.thradams.com/codeblog/wndproc.htm

+1
source

All Articles