Почему SC_HSCROLL и SC_VSCROLL, похоже, переключены в WM_SYSCOMMAND?

#c #winapi #scrollbar #spy #common-controls

#c #winapi #полоса прокрутки #spy #общие элементы управления

Вопрос:

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

Скажем, когда уведомление о щелчке мыши на полосе прокрутки передается через 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 amp; 0xFFF0;
    if(uiCmd == SC_HSCROLL)
    {
        TRACE(L"Horiz scrolln");
    }
    else if(uiCmd == SC_VSCROLL)
    {
        TRACE(L"Vertical scrolln");
    }
}
  

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

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

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

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

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

Все правильно, за исключением SC_HSCROLL . WTF?

Комментарии:

1. Что это за элемент управления? Это обычный список Win32, ListView или что-то пользовательское. Можете ли вы опубликовать MVCE (минимальный, полный, проверяемый пример).

2. Кроме того, что вы действительно пытаетесь сделать? Как вы можете видеть, сообщение WM_VSCROLL приходит после SYSCOMMAND.

3. @selbie /: Это richedit

Ответ №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 возврата сообщения

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

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

Комментарии:

1. Интересно. И это было там с тех пор, idk, Windows XP или около того, и никто этого не заметил? В любом случае, спасибо за подтверждение. Я думал, что мне «мерещится» 🙂 Хотя, если ошибка в uxtheme.dll , означает ли это, что если процесс не тематический, то SC_VSCROLL и SC_HSCROLL будет отправлен правильно?

2. @c00000fd — просто посмотрите на этот ox xp — та же ошибка .

3. @c00000fd — если процесс не тематический — даже не проверяйте .. просто нужна обработка WM_VSCROLL и WM_HSCROLL я думаю.