How do I turn my message procedure into a member function of a class?

Started by
10 comments, last by Red Ant 22 years, 4 months ago
Hi there, As of now my Win32 application isn''t very OOP yet. I wanna change that but I can''t seem to figure out what I have to do to actually make my message procedure into a member function. Can somebody maybe give me a pointer to a tutorial or something? Thanks in advance.
Advertisement
make it static
The problem you have if you make it static is that you only have one window procedure for many window instantiations. However, you must give a global or static method to the WNDCLASS argument. So what you do is make a static window procedure that acts as a message router. This static procedure maps the message to the appropriate C++ window object.

static int WndProcRouter(HWND hwnd, ...etc)

Now the problem is that in the static wndproc you don''t have the C++ object that the message was directed to. BUT we do have the HWND. We need a method that given the HWND as an argument returns us the corresponding C++ window object. We want something like:

Window* win = GetWindowObject(hwnd);

Then we can write:

win->msgProc(...);

There are several ways to associate a c++ window object with a HWND. We can keep a static data structure that stores the HWND and a ptr to its corresponding C++ object. Then procide an interface that searches the data structure for a particular HWND and returns the Window object.

During creation:

dataStructure.AddWindow(_hwnd, this);

then:

Window* GetWindowObject(HWND hwnd)
{
Window* win = dataStructure.get(hwnd);

win->msgProc(...);
}





ECKILLER
ECKILLER
Thanks for your help. However, if I make my WndProc static then how can I call any other methods (which are non-static) from within the window procedure?
quote:Original post by Red Ant
Thanks for your help. However, if I make my WndProc static then how can I call any other methods (which are non-static) from within the window procedure?

Read the post before yours... carefully.
Sorry, I must have read that post for the 20th time now but I still don''t know how to do it. Help me!
ECKILLER suggest associating window handles with object pointers in some way (say, through a static table). A message router defined as
LRESULT WINAPI WndProcRouter(HWND hwnd, ...); 

is then specified as the window procedure for every window of the class (or even of the entire application). This handler will then call a function of the form
window * GetWindow(HWND hwnd); 

provided by yourself (where window is the name of your class that encapsulates windows), which (the function) looks up the object pointer in the table described above.

The message router will now call the WindowProc function of the returned object:
window *win = NULL;win = GetWindow(hwnd);if(!win)  throw "failed to obtain window object";win->WindowProc(hwnd, umsg,...); 

A very elegant solution he has detailed more than once on these fora. Any further questions, why not email him?
The best way to do this is to allocate extra storage in the window class, 4 bytes, to store the "this" pointer... pass this along when you do OpenWindowEx().

Then, have a standard procedure as your default message handler for your window class that retrieves this "this" pointer, and calls your own message procedure member function.

quote:Original post by Anonymous Poster
The best way to do this is to allocate extra storage in the window class, 4 bytes, to store the "this" pointer... pass this along when you do OpenWindowEx().

Then, have a standard procedure as your default message handler for your window class that retrieves this "this" pointer, and calls your own message procedure member function.

Exactly. I was trying to find the specifics on doing so. I know that the extra data is requested/reserved via cbClsExtra and/or cbWndExtra, but I don''t know where to place the pointer itself. If you would post some specifics, I''d be much obliged.
Found it. Use cbWndExtra to specify how much extra memory, in bytes, is required per window (in this case 4 bytes to store the this pointer). Then use SetWindowLong() and GetWindowLong() to commit/retrieve the data.

Cool.

This topic is closed to new replies.

Advertisement