Во-первых, позвольте мне сказать, что я новичок в использовании WinAPI и пытаюсь изучить основы. Тем не менее, я пытаюсь создать несколько объектов, чтобы сделать мою будущую работу с WinAPI намного проще. Одним из них является класс окна... класс. Другой, конечно же, класс Window.
Я пытаюсь упростить обработку сообщений, например myClassInst.addHandler(WM_PAINT, PaintFunction). Для этого я решил использовать карту, которая сопоставляет uints с указателями функций. Это кажется прекрасным.
Но сейчас сообщения не обрабатываются. После некоторой отладки я обнаружил, что всякий раз, когда я пытаюсь каким-либо образом использовать карту внутри обработчика WndProc моего класса, она просто молча терпит неудачу. Я не получаю ни ошибок компиляции, ни ошибок времени выполнения, ни сбоев; функция просто немедленно заканчивается там, пока не придет следующее сообщение. Я не могу понять, почему. Может быть, кто-нибудь может мне помочь?
Ниже приведен фрагмент моего кода, все в приватном разделе моего класса WinClass. Статический dummyProc message-passer — это единственный способ, который я нашел для разрешения специфичного для класса WndProc, так что это там. Это работает, так как первая часть моего WndProc myHandler действительно работает, о чем свидетельствует вывод отладочного сообщения. Он просто останавливается, как только я пытаюсь использовать карту, даже просто для получения ее размера.
*Примечание: WindowFunction — это определение типа указателя на функцию, принимающую параметр HWND.
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);
}
ИЗМЕНИТЬ Итак, после дальнейшего тестирования я обнаружил дополнительную информацию. Значение контекста всегда равно 0, и хотя я не понимаю, как это вообще позволяет вызывать myHandler, это проблема. Итак, я изменил свой код, чтобы попытаться установить GWL_USERDATA из сообщения WM_CREATE... и обнаружил, что мой dummyProc никогда не получает сообщение WM_CREATE.
Ниже представлен новый dummyProc с выводом отладочной информации:
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);
}
Он говорит, что WM_CREATE имеет значение 1, но сообщения приходят, начиная с 36, затем со 129 и 130. Что случилось с моим сообщением WM_CREATE?
Вот код, который создает само окно:
рука = CreateWindowEx(WS_EX_CLIENTEDGE, myClass.myName, title, WS_OVERLAPPEDWINDOW, x, y, w, h, parent, NULL, inst, &myClass);
Большинство этих параметров являются аргументами, передаваемыми конструктору класса Window (где находится этот код). Параметр myClass является экземпляром WinClass. Все экземпляры WinClass устанавливают dummyProc в качестве своего обработчика WndProc. Тестирование показывает, что &myClass действительно является допустимым указателем, отличным от NULL, когда это вызывается.
Так что же мешает сообщению WM_CREATE?
context
имеет правильное значение? - person Ben Voigt   schedule 03.03.2014this
, потому что это неvirtual
. И верхняя половина функции (часть, которая работает) еще не использовала указательthis
. - person Ben Voigt   schedule 03.03.2014WM_CREATE
отправляется, но далеко не первым. В своем ответе я упомянулWM_NCCREATE
, что обычно довольно рано, хотя все же не первое. Попробуйте прочитать весь мой ответ, а также сообщение в блоге Раймонда Чена, на которое я ссылаюсь. - person Ben Voigt   schedule 03.03.2014RegisterClass
? - person Ben Voigt   schedule 03.03.2014WM_CREATE
... Может быть, вы хотите, чтобыif (!thelong) return DefWindowProc(hwnd, msg, wParam, lParam);
получил обработку по умолчанию для всех этих ранних сообщений? - person Ben Voigt   schedule 03.03.2014RegisterClass
. Но независимо от того, какие аргументы передаются конструктору WinClass, он всегда использует dummyProc в качестве своего обработчика в своем члене WNDCLASSEX при регистрации. Это то, что я имел в виду. - person Daniel Burnett   schedule 03.03.2014myClass
внутриWindow
?&myClass
делает двойной указатель? Позже вы будете обращаться с ним как с одним указателем. Предполагать, что это твоя проблема. - person Ben Voigt   schedule 03.03.2014