
Тюнингуем контрол msctls_trackbar32
За время существования этого сайта тут было доработано уже несколько различных стандартных элементов управления, настало время провести тюнинг контрола msctls_trackbar32. Создается он обычным образом, например, через прописывание в ресурсах. Обязательно надо добавить в импорт библиотеку comctl32.dll и вызвать функцию InitCommonControls. Ну а поскольку мы будем добавлять к контролу различные нестандартные функции, то и делать это будем в специально отведенной процедуре-обработчике. Для этого воспользуемся субклассированием. Действия стандартные, примеров субклассирования на этом сайте предостаточно.Code (Assembler) : Убрать нумерацию
- ; Настройки ползунка
- invoke GetDlgItem,[hwnddlg],IDC_PROGRESS
- mov [track],eax
- ; Установить наш собственный обработчик
- invoke SetWindowLong,[track],GWL_WNDPROC,TrackProc
- ; Сохранить хэндл предыдущего обработчика
- invoke SetWindowLong,[track],GWL_USERDATA,eax
Начинаем с избавления от рамки. Тут ничего нового, это уже было разобрано в одной из предыдущих статей. В случае с msctls_trackbar32 код в обработчике будет абсолютно такой же. Все необходимые значения констант и порядок установки обработчика можно посмотреть по приведенной ссылке.
Code (Assembler) : Убрать нумерацию
- ; Система хочет поменять состояние интерфейса
- cmp [uMsg],WM_UPDATEUISTATE
- je .wm_updateuistate
- ...
- ...
- .wm_updateuistate:
- ; Принудительно сбросить фокус
- mov [wParam],(UIS_SET shl 16 + UISF_HIDEFOCUS)
- jmp .process_ok
Code (Assembler) : Убрать нумерацию
- ; Вращение колесика мыши
- cmp [uMsg],WM_MOUSEWHEEL
- je .wm_mousewheel
- ...
- ...
- .wm_mousewheel:
- ; Инвертировать направление вращения колесика
- neg [wParam]
- jmp .process_ok

Добавляем "рулетку"
Для наглядности я сделал этот элемент видимым. В реальных проектах после позиционирования "рулетки" все риски на шкале можно убрать, а саму "рулетку" надо обязательно сделать невидимой. После всех выполненных манипуляций, при клике на контрол получаем координаты события при помощи функции GetMessagePos, затем при помощи функции ScreenToClient проецируем координаты клика на "рулетку". Остается, как я говорил выше, решить пропорцию и установить новую позицию бегунка в соответствии с местом клика. Важно проверять левую границу после пересчета координат, если она будет меньше начального значения, то надо принудительно приравнивать ее к этому значению.
Code (Assembler) : Убрать нумерацию
- ; Клик в области контрола
- cmp [uMsg],WM_LBUTTONDOWN
- je .wm_lbuttondown
- ...
- ...
- .wm_lbuttondown:
- ; Получить координаты события клика
- invoke GetMessagePos
- and eax,0FFFFh
- add eax,5
- mov [pt.x],eax
- ; Пересчитать координаты в пределах линейки
- invoke ScreenToClient,[ruler],pt
- ; Начальная координата не должна выходить за границу линейки
- mov eax,[pt.x]
- or eax,eax
- jns @f
- mov [pt.x],0
- @@:
- ; Получить размеры линейки
- invoke GetWindowRect,[ruler],coord
- ; Получить максимальное значение ползунка
- invoke SendMessage,[hBtn],TBM_GETRANGEMAX,NULL,NULL
- xor edx,edx
- mov ecx,[pt.x]
- imul ecx
- mov ecx,[coord.right]
- sub ecx,[coord.left]
- xor edx,edx
- idiv ecx
- mov ecx,[coord.right]
- sub ecx,[coord.left]
- shr ecx,1
- cmp ecx,edx
- jbe @f
- inc eax
- @@:
- ; Установить новую позицию в соответствии с кликом
- invoke SendMessage,[hBtn],TBM_SETPOS, TRUE, eax
- ; Отправить сообщение главному окну
- invoke SendMessage,[mainwnd],WM_HSCROLL,0,[hBtn]
- jmp .process_ok
Просмотров: 428 | Комментариев: 2
Метки: Assembler

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(16.03.2025 в 21:32):
Интересное наблюдение, надо будет при случае проверить на бесятке.

Алексей
(14.03.2025 в 22:04):
Попробовал убрать прямоугольник описанным способом в Win10 - не вышло. Стал разбираться. Записал в лог вообще все коды сообщений, поступающих в обработчик при манипуляциях над трекбаром. Выяснилось, что WM_UPDATEUISTATE ему вообще не поступает. Вместо этого ему поступает WM_SETFOCUS (0x0007). Соответственно, если его перехватить и просто заглушить, вернув системе 0, то все работает как надо. Возможно, кому-то эта информация будет полезной

Добавить комментарий
Заполните форму для добавления комментария
