Почему SC_HSCROLL и SC_VSCROLL кажутся переключенными в WM_SYSCOMMAND?

Я знаю, что это очень старая вещь, но я ломаю над ней голову. Кто-нибудь знает, почему это происходит?

Скажем, когда уведомление о щелчке мыши на полосе прокрутки распространяется через WM_NCHITTEST -> WM_NCLBUTTONDOWN -> WM_SYSCOMMAND -> WM_HSCROLL или WM_VSCROLL, все параметры в этой цепочке, кажется, следуют документации, кроме SC_HSCROLL и SC_VSCROLL для WM_SYSCOMMAND. Итак, если я сделаю:

//From within WndProc
if(message == WM_SYSCOMMAND)
{
    UINT uiCmd = wParam & 0xFFF0;
    if(uiCmd == SC_HSCROLL)
    {
        TRACE(L"Horiz scroll\n");
    }
    else if(uiCmd == SC_VSCROLL)
    {
        TRACE(L"Vertical scroll\n");
    }
}

Кажется, я получаю вертикальное уведомление для горизонтального и наоборот.

Вот доказательство от Spy++. Если я нажму эту стрелку вниз:

введите здесь описание изображения

это уведомления, которые получает окно:

введите здесь описание изображения

Все правильно, кроме SC_HSCROLL. ВТФ?


person c00000fd    schedule 05.04.2019    source источник
comment
Что это за контроль? Это обычный Win32 ListBox, ListView или что-то нестандартное. Можете ли вы опубликовать MVCE (минимальный, полный, проверяемый пример).   -  person selbie    schedule 05.04.2019
comment
Кроме того, что вы действительно пытаетесь сделать? Как видите, сообщение WM_VSCROLL приходит после SYSCOMMAND.   -  person selbie    schedule 05.04.2019
comment
@selbie/: Это richedit   -  person c00000fd    schedule 05.04.2019


Ответы (1)


если искать __int64 OnDwpNcLButtonDown(CThhemeWnd*, THEME_MSG*) под отладчиком виден следующий код:

введите здесь описание изображения

wParam = HTVSCROLL != HitTest ? SC_VSCROLL : SC_HSCROLL;
SendMessage(*, WM_SYSCOMMAND, (wParam | HitTest), *)

WM_SYSCOMMAND с SC_VSCROLL или SC_HSCROLL отправлены с этой точки, но очевидный код содержит логическую ошибку - SC_VSCROLL и SC_HSCROLL перепутаны.

правильный код должен быть

wParam = HTVSCROLL == HitTest ? SC_VSCROLL : SC_HSCROLL;

также

В сообщениях WM_SYSCOMMAND четыре младших бита параметра wParam используются внутри системы. Чтобы получить правильный результат при проверке значения wParam, приложение должно объединить значение 0xFFF0 со значением wParam с помощью побитового оператора AND.

здесь видно, что вместо четырех младших бит мы попали в тестовый код из WM_NCLBUTTONDOWN сообщение из WM_NCHITTEST< /a> возврат сообщения

0xf087 - это SC_HSCROLL | HTVSCROLL, когда в hscroll мы получили 0xf076, что равно SC_VSCROLL | HTHSCROLL

это просто ошибка Windows в uxtheme.OnDwpNcLButtonDown

person RbMm    schedule 05.04.2019