Ускорители клавиатуры Windows и дочерние окна - PullRequest
2 голосов
/ 26 декабря 2009

Я создал программу с графическим интерфейсом Windows, используя C и Windows API, и хочу, чтобы программа использовала ускорители клавиатуры. Я настроил некоторые ускорители, которые работают правильно, но когда фокус переходит к дочернему окну главного окна моей программы, например элементу управления списком или строке состояния, кажется, что клавиатурные ускорители переводятся в сообщения WM_COMMAND для дочерних окон, а не главного окна. Из-за этого моя обработка соответствующих сообщений WM_COMMAND в WndProc главного окна игнорируется, когда фокус находится на дочернем элементе управления.

Как мне решить эту проблему?

Ответы [ 2 ]

3 голосов
/ 26 декабря 2009

Я нашел ответ. Дочерние окна главного окна должны быть разделены на подклассы, чтобы сообщения WM_COMMAND, генерируемые ускорителями клавиатуры, могли быть перехвачены и переданы в родительское окно.

Это включает изменение оконной процедуры элемента управления на другую. Альтернативная процедура обрабатывает сообщения, которые должны быть перехвачены, отправляя их в родительское окно. Указатель на исходную оконную процедуру также должен храниться где-то, чтобы элемент управления мог функционировать правильно.

Процедуру окна можно изменить, используя SetWindowLongPtr с GWLP_WNDPROC.

Вот простой пример того, как сделать это путем сохранения указателя на исходную оконную процедуру в значении пользовательских данных элемента управления (GWLP_USERDATA):

Код для изменения процедуры окна и сохранения исходной процедуры в GWLP_USERDATA:

SetWindowLongPtr( hWnd, GWLP_USERDATA, ( LONG_PTR )SetWindowLongPtr( hWnd, GWLP_WNDPROC, ( LONG_PTR )WndProc ) );

Процедура перехватывающего окна:

static LRESULT CALLBACK WndProc( const HWND hWnd, const UINT message, const WPARAM wParam, const LPARAM lParam )
{
    switch( message )
    {
        case WM_COMMAND:
            SendMessage( GetParent( hWnd ), message, wParam, lParam );
            return 0;
        default:
        //Assume that GWLP_USERDATA has been set to the original window procedure.
            return CallWindowProc( ( WNDPROC )GetWindowLongPtr( hWnd, GWLP_USERDATA ), hWnd, message, wParam, lParam );
    }
}
0 голосов
/ 22 ноября 2013

Другой способ - избегать использования TranslateAccelerator для дочернего окна, пример кода:

if (mainWidget() && msg.hwnd == mainWidget()->hwnd()) {
            if (TranslateAccelerator(msg.hwnd, hMainAccelTable, &msg)) {
                continue;
            }
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);

если сообщение не относится к mainWidget, мы не переводим ускоритель для него, используя таблицу ускорителей основного виджета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...