Я хотел бы знать, возможно ли указать WndProc для дочернего окна, созданного CreateWindowEx
,
Я уже создал класс окна, главное окно, процедуру окна и цикл сообщений. Код работает, и я решил оставить его для ясности моего вопроса.
Это мой Window Proc, пока:
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
// Creation of the Win32 Window
case WM_CREATE:
// Add an Edit Field
CreateWindowEx(
WS_EX_CLIENTEDGE,
"EDIT",
"",
WS_CHILD | WS_VISIBLE,
5, 5, 200, 24,
hwnd,
(HMENU)100,
g_Instance, // Comming from WinMain
NULL
);
return DefWindowProc(hwnd, uMsg, lParam, wParam);
case WM_KEYDOWN:
// Track key presses on the edit field
std::cout << "The key with the code " << wParam << " was pressed." << std::endl;
return 0;
case WM_PAINT:
// Some painting code...
return DefWindowProc(hwnd, uMsg, lParam, wParam);
default:
return DefWindowProc(hwnd, uMsg, lParam, wParam);
}
}
Я ожидал нажатия клавиш на дочернем поле редактирования, которое я создал, чтобы выдать сообщение WM_KEYDOWN, но они этого не делают! Ключи просто добавляются в поле редактирования в моем окне, но не вызывают сообщение WM_KEYDOWN.
Кажется, что созданное окно редактирования не использует мой WndProc. Как я могу это изменить?
Ваш WndProc
не получить WM_KEYDOWN
сообщения, потому что, если пользователь печатает внутри элемента управления редактирования, это означает, что он имеет фокус (не ваше окно), поэтому они отправляются в редактировать контроль оконный процесс, а не ваш. Тем не менее, Proc окна редактирования редактирования будет отправлять уведомления на ваш WndProc
(его родительское окно прок).
Так что, если вы хотите только реагировать на пользователя изменения содержание вашего дочернего элемента управления редактированием, вам не нужна другая оконная процедура. Ваш текущий WndProc
получит EN_CHANGE
код уведомления через WM_COMMAND
сообщение.
Увидеть https://msdn.microsoft.com/en-us/library/windows/desktop/bb761676(v=vs.85).aspx
Если вы действительно хотите поймать WM_KEYDOWN
сообщения, вы должны создать подкласс управления редактирования, как это:
OldWndProc = (WNDPROC)SetWindowLongPtr (hButton, GWLP_WNDPROC, (LONG_PTR)NewWndProc);
Вам также необходимо определить новую процедуру Windows ( NewWndProc
), что должно обрабатывать WM_KEYDOWN
сообщение (и любое другое сообщение, которое вы хотите обработать). Вам также нужно позвонить OldWndProc
как бы вы назвали DefWndProc
в стандарте WndProc
, если вы не хотите, чтобы элемент управления редактирования выполнял свою обычную обработку.
Для получения дополнительной информации о создании подклассов см. https://msdn.microsoft.com/en-us/library/windows/desktop/bb773183(v=vs.85).aspx
Отвечая на комментарий OP здесь.
Если ваше окно является диалоговым окном, вы должны быть уведомлены о вводе ключа, в вашем WndProc
:
case WM_COMMAND:
if(wParam=IDOFDEFBUTTON || IDOK) ...
Увидеть https://support2.microsoft.com/Default.aspx?scid=kb;en-us;Q102589
Если честно, я так и не удосужился понять, что такое диалоговое окно действительно является. Но если я правильно помню, вы можете получить свое окно для получения специальных уведомлений, вызвав IsDialogMessage в своем насосе сообщений:
if(!IsDialogMessage(hWnd,&msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
За интересную информацию о IsDialogMessage
, увидеть http://blogs.msdn.com/b/oldnewthing/archive/2012/04/16/10293933.aspx
Если это не дает достаточного контроля, вам, вероятно, придется разделить элемент управления на подклассы.
Ваш вызов CreateWindowsEx создает новое окно с классом «EDIT» wnd, имеющим собственную процедуру Window. Вам нужен новый WndProc и установить его во вновь созданное окно (чей дескриптор возвращается CreateWindowEx) через функцию SetClassLong