C++ Learning Community Forum
August 01, 2010, 02:27:05 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Hello. Smiley
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: How to make a callback class (non-MFC)  (Read 604 times)
FrozenKnight
ASM Freak
Global Moderator
Dr. of C++ology
*****
Posts: 546


Do it yourself it's the only way to learn.


View Profile
« on: August 06, 2009, 12:37:00 AM »

it took me a while to get this completely working but I eventually figured it out, this works with Visual C++ 2008 express I haven't tested it with other compilers.

First is the template I made to get this whole thing working.
Code
GeSHi (cpp):
template <class T, LRESULT (T::*Callback)(HWND,UINT,WPARAM,LPARAM)>
LRESULT CALLBACK ClassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
       T *wndClass = 0;
       switch (uMsg){
               case WM_NCCREATE:
                       wndClass = reinterpret_cast<T*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
                       SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(wndClass));
                       break;
               default:
                       wndClass = reinterpret_cast<T*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
       }
       return (wndClass->*Callback)(hWnd,uMsg,wParam,lParam);
}
Created by GeSHI 1.0.7.18
At first glance this may be a bit confusing, but trust me it isn't that hard to get working.
here is an example of how to use it.
Code
GeSHi (cpp):
wc.style                        = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;.
wc.lpfnWndProc                  = ClassWindowProc<MyClass,&MyClass::MyCallBack>; //MyClass is the name of your class, &MyClass::MyCallBack is the CallBack function in your class.
wc.cbClsExtra                   = 0;
wc.cbWndExtra                   = 0;
wc.hInstance                    = hInstance;
wc.hIcon                        = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor                      = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground                = NULL;
wc.lpszMenuName                 = NULL;
wc.lpszClassName                = "MyWin";
 
RegisterClass(&wc)
 
hWnd=CreateWindowEx(dwExStyle,
                       "MyWin",
                       title,
                       dwStyle |
                       WS_CLIPSIBLINGS |
                       WS_CLIPCHILDREN,
                       0, 0,
                       WindowRect.right-WindowRect.left,
                       WindowRect.bottom-WindowRect.top,
                       NULL,
                       NULL,
                       hInstance,
                       reinterpret_cast<LPVOID>(this)); //pass a this pointer to WM_CREATE and WM_NCCREATE
 
Created by GeSHI 1.0.7.18
I placed comments at the important sections in the code, you must create the window inside a function in your class for this to work correctly, . Some of you will notice that it is possible to do outside the class but i won't discuss how to do that here.

now for an explanation of how this works.
First is the template,
Code
GeSHi (cpp):
ClassWindowProc<MyClass,&MyClass::MyCallBack>
Created by GeSHI 1.0.7.18
The first parameter is your class name the second is the address of your classes callback function. (It is possible to have two windows going using one class, as long as they use different callbacks, if you do, do so with caution, it is possible to mess up the class address and crash the program)
the template uses the GWLP_USERDATA of the desired window to store a pointer to the class (which you pass from the last parameter of CreateWindow or CreateWindowEx also known as lpParam) this pointer is then used to rout all calls to the member function you specify.

You must also specify the template ClassWindowProc as your callback function in WNDCLASS.lpfnWndProc when you register the WNDCLASS structure. Hope this makes things easier for all of you who wanted to use classes for your windows.  Wink
« Last Edit: August 21, 2009, 02:10:02 AM by FrozenKnight » Logged


Imagine the impossible, then make it happen.
Joel
Coding from an Igloo
Jr. Nerd
***
Posts: 47


Linux coder


View Profile WWW
« Reply #1 on: August 08, 2009, 03:25:29 PM »

Good idea, I use friend functions in the WinProc just to avoid the unnecessary of the usage of "static member" for it.
Logged


* Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM
* Ubuntu 9.04; Kernel 2.6.28-15-generic.
* lighttpd, php5, perl, eruby, python.
* geany, HTML & CSS & JavaScript, mono, gtk+, QT4, wxWidgets, bash, gcj.
* Coming soon: Kubuntu 9.10 or Dragora 1.1
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!