First, let me say I'm new to using WinAPI, and I'm trying to learn the basics. That said, I'm trying to create a few objects to make my future work with WinAPI much easier. One of those is a Window Class...class. The other is, of course, a Window class.
I'm trying to make message processing into something simple, like myClassInst.addHandler(WM_PAINT, PaintFunction). For that, I figured I'd use a map that maps uints to function pointers. That seems fine.
But now, the messages aren't being processed. After some debugging, I found that whenever I try to use the map in any way inside my class's WndProc handler, it just silently fails. I get no compile errors, no runtime errors, no crashes; the function just immediately ends there until the next message comes in. I can't for the life of me figure out why. Maybe someone can help me?
Below is a snippet of my code, all in the private section of my WinClass class. The static dummyProc message-passer is the only way I found to allow a class-specific WndProc, so that's there. That's working, as the first part of my WndProc myHandler does, in fact, work, as evidenced by the debug message's output. It just stops the second I try and use the map, even just to get its size.
*Note: WindowFunction is a typedef to a pointer to a function taking an HWND parameter.
std::map<unsigned int, WindowFunction> messageMap;
static LRESULT CALLBACK dummyProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
WinClass* context=(WinClass*)GetWindowLong(hwnd, GWL_USERDATA);
return context->myHandler(hwnd, msg, wParam, lParam);
}
LRESULT CALLBACK myHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
std::cout<<"Message: "<<msg<<std::endl; // This gets output
std::cout<<" Contains "<<messageMap.size()<<" items"<<std::endl; // This does not
std::cout<<" And me!"<<std::endl; // Nothing works below the map usage.
for (std::map<unsigned int, WindowFunction>::iterator it=messageMap.begin(); it!=messageMap.end(); ++it) {
std::cout<<" Have: "<<it->first<<std::endl;
if (msg==it->first) {
(it->second)(hwnd);
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
EDIT So, after some further testing, I've discovered some more information. The context value is always 0, and while I don't understand how that would even allow the myHandler to get called, it is a problem. So I've changed my code to try and set the GWL_USERDATA from the WM_CREATE message...and what I've found is that my dummyProc is never getting the WM_CREATE message.
Below is the new dummyProc, complete with debugging output:
static LRESULT CALLBACK dummyProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
std::cout<<"Create would be "<<WM_CREATE<<std::endl;
std::cout<<"The message was "<<msg<<std::endl;
if (msg==WM_CREATE) {
SetLastError(0);
SetWindowLong(hwnd, GWL_USERDATA, lParam);
std::cout<<"ERROR: "<<GetLastError()<<std::endl;
}
long thelong=GetWindowLong(hwnd, GWL_USERDATA);
std::cout<<"Long: "<<thelong<<std::endl;
WinClass* context=(WinClass*)thelong;
std::cout<<"Context: "<<context<<std::endl;
return context->myHandler(hwnd, msg, wParam, lParam);
}
What it says is that WM_CREATE has a value of 1, but the messages come in starting from 36, then 129 and 130. What happened to my WM_CREATE message?
Here's the code that creates the window itself:
hand = CreateWindowEx(WS_EX_CLIENTEDGE,
myClass.myName,
title,
WS_OVERLAPPEDWINDOW,
x, y,
w, h,
parent,
NULL,
inst,
&myClass);
Most of those parameters are arguments passed to the Window class's constructor (where this code is). The myClass parameter is a WinClass instance. All WinClass instances set dummyProc as their WndProc handler. Testing shows that &myClass is indeed a valid non-NULL pointer when this is called.
So what's preventing the WM_CREATE message?