I've been toying with template functions as a first step/ exploration/attempt to devise a c++ replacement for message macros from mainly windowsx.h. I've read some stuff on line - comparisons of different templatised techniques, functors etc and am using Stroustrup's C++ and Josuttis for reference.
In general: I have a base wnd class (C++) from which is derived various windows and controls, the hierarchy is something like BaseWnd::Wnd::MainWnd where MainWnd is a 'container' or frame for just about everything else. Currently I use a static wndproc which forwards messages to a virtual class wndproc which is overridden in descendant classes as required. I use msg macros in these virtual wndprocs as follows, eg:
where the HANDLE_MSG macro expands into the case statement and the call to the OnEraseBkGrd handler for WM_ERASEBKGND as defined in windowsx.h. I have included one msg only for simplicity.Code:LRESULT CALLBACK MainWnd::MsgProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch (uMsg) { HANDLE_MSG(hwnd,WM_ERASEBKGND,OnEraseBkGrd); } }
This is the template fn to 'replace' it:and the virtual wndproc becomes:Code:template <class T,class W> inline OnEraseHandler(T *ObjPtr,BOOL (W::*FnPtr)(HWND,HDC),HWND hwnd,WPARAM wParam,LPARAM lParam) { (ObjPtr->*FnPtr)(hwnd,reinterpret_cast<HDC>(wParam)); }Which works ok but is ugly.Code:LRESULT CALLBACK MainWnd::MsgProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch (uMsg) { case WM_ERASEBKGND: return OnEraseHandler(this,&MainWnd::OnEraseBkGrd,hwnd,wParam,lParam); } }
The problem: I want the template to function like the macro (I wouldn't mind if the syntax was equally simple too!) in that I can call any handler within the class hierarchy from it, eg:will call the required fn; if I try the same thing with the template fn ie:Code:HANDLE_MSG(hwnd,WM_ERASEBKGND,Wnd::OnEraseBkGrd);It fails (presumably because it's using this to determine the object. This fails too:Code:return OnEraseHandler(this,&Wnd::OnEraseBkGrd,hwnd,wParam,lParam);When I speak of failure what I mean is that the handler called is always the one currently in scope ie MainWnd::OnEraseBkGrd.Code:return OnEraseHandler<Wnd,Wnd>(this,&Wnd::OnEraseBkGrd,hwnd,wParam,lParam);
So, if anyone has been there and done that could you please give me some hint as to how I might coerce the template to call any handler in the class hierarchy I might explicitly choose or perhaps an explanation of why it's not possible to do so. Note that the handler functions (C++), in this case OnEraseBkgrd, are virtual.
Thanks in advance for your time and consideration.
edit: typos, formatting



LinkBack URL
About LinkBacks



[ templates<can suck sometimes>
]
Ok. Basically, a class simply "registers" a message it's interested in and at the same time, passes in the handler. The handler is cast to a pointer to the very lowest base-class type, and it and the message are added to a list that every object builds up. A sort of internalized message loop.