Любопытная проблема отсутствующего сообщения WM_NCLBUTTONUP, когда окно не развернуто - PullRequest
5 голосов
/ 06 февраля 2009

У меня есть окно, в котором я обрабатываю сообщения WM_NCLBUTTONUP, чтобы обрабатывать щелчки на пользовательских кнопках в строке заголовка. Это прекрасно работает, когда окно развернуто, но когда это не так, сообщение WM_NCLBUTTONUP никогда не приходит! Я получаю сообщение WM_NCLBUTTONDOWN, хотя. Как ни странно, WM_NCLBUTTONUP появляется, если я щелкаю справа от строки меню, но в любом месте строки заголовка / рамки окна сообщение никогда не приходит.

Через некоторое время отладки я обнаружил, что если я установил точку останова на CMainFrame :: OnNcLButtonDown (), щелкнул панель заголовка, но удерживал кнопку мыши нажатой, оставил отладчик в функции, нажмите F5, чтобы продолжить отладку , затем отпустите кнопку мыши - волшебным образом отправляется WM_NCLBUTTONUP !!

Мой вопрос двоякий: (1) что, черт возьми, происходит? (2) как мне обойти эту «проблему».

Я также отмечаю, что в Интернете есть несколько других людей, имеющих такую ​​же проблему (быстрый Google обнаруживает множество других людей с той же проблемой, но без решения).

Редактировать
Спасибо за первые два ответа, я попытался вызвать ReleaseCapture в NCLButtonDown, но это не имеет никакого эффекта (фактически, он возвращает NULL, указывая, что захват не на месте). Я могу только предположить, что функциональность базового класса (def window proc) может устанавливать захват. Я буду расследовать в понедельник ...

Ответы [ 4 ]

4 голосов
/ 05 мая 2009

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

Решение состоит в том, чтобы переопределить WM_NCHITTEST:

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
    switch (nMsg)
    {
        ...
        case WM_NCHITTEST:
            Point p(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam);
            ScreenToClient(p);
            if (myButtonRect.Contains(p))
            {
                return HTBORDER;
            }
            break;
    }
    return DefWindowProc(hWnd, nMsg, wParam, lParam);
}

Таким образом, по сути, вы сообщаете Windows, что область, занимаемая вашей кнопкой, не является частью заголовка окна, а является неконкретной частью не клиентской области (HTBORDER).

Сноска. Если вы вызвали SetCapture () и еще не вызвали ReleaseCapture (), когда ожидаете, что придет сообщение WM_NCLBUTTONDOWN, оно не будет получено даже с указанным выше изменением. Это может раздражать, так как захват мыши во время взаимодействия с такими пользовательскими кнопками является нормальным, так что вы можете отменить щелчок / выделение, если мышь покидает окно. Однако в качестве альтернативы использованию захвата вы можете рассмотреть SetTimer () / KillTimer () с коротким (например, 100 мс) интервалом, который не приведет к исчезновению сообщений WM_NCLBUTTONUP.

2 голосов
/ 06 февраля 2009

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

Я бы посоветовал вам запустить Spy ++ в этом окне, и это дети, и попытаться выяснить, кто получает сообщение «вверх»

Что касается того, как это исправить - не могу помочь вам, не посмотрев на реальный код. Вы должны выяснить, кто является виновником, и посмотреть на их код.

1 голос
/ 18 января 2015

включает ReleaseCapture () в WM_NCLBUTTONDOWN {кодовый блок}

1 голос
/ 06 февраля 2009

Чтобы добавить к ответу Франциска Пенова , щелчок по строке заголовка интерпретируется как начало перетаскивания, чтобы изменить положение окна. Окно захватывает мышь, поэтому оно может выполнять перетаскивание. Поскольку развернутое окно не может быть перетащено, захват пропускается и сообщение отправляется нормально.

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