Как сделать ProgressBar с надписью
Не перестаю удивляться, почему разработчики Microsoft с самого начала не реализовали "из коробки" очевиднейшие решения. Например, есть хороший и удобный элемент диалоговых окон - Progress Bar. Легко реализовать, удобно управлять, но по какой-то причине нет никаких инструментов, чтобы системными средствами наложить на индикатор прогресса какую-нибудь надпись типа "42% завершено". Градиентный ProgressBar мы уже делали, настала очередь реализовать ProgressBar с надписью.ProgressBar с надписью
Использовать стандартный элемент msctls_progress32 не будем, вместо него возьмем элемент EDIT или STATIC, как и в предыдущем примере. Полоса индикатора и надпись реализуется путем рисования прямо на канве элемента диалогового окна, которое выделено под индикатор.
Основная загвоздка заключается в том, что при отрисовке текста поверх индикатора прогресса, надо учитывать разницу в цвете фона и полосы выполненной части. Посмотрите на скриншоте, чтобы стало понятно, о чем идет речь. В некоторых случаях при определенной комбинации цветов можно использовать единый цвет, но это не самое хорошее решение. Так что сделаем все правильно.
Взаимодействие основного потока приложения и кастомного индикатора реализуется через субклассирование. Установка обработчика ничем не отличается от десятка других примеров, которые мы ранее разбирали.
Code (Assembler) : Убрать нумерацию
- ; Субклассирование ProgressBar
- invoke GetDlgItem,[hwnddlg],ID_PROGRESS
- mov ebx,eax
- ; Установить наш собственный обработчик
- invoke SetWindowLong,ebx,GWL_WNDPROC,ProgressWindowProc
- ; Сохранить хэндл предыдущего обработчика
- mov [OldProc],eax
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------
- ; Субклассированный обработчик
- ;------------------------------------------------
- proc ProgressWindowProc hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
- locals
- text dd ?
- ps PAINTSTRUCT
- hDC dd ?
- rcClient RECT
- endl
- cmp [uMsg],WM_PAINT
- je .wm_paint
- .char_ok:
- ; Передать управление предыдущему обработчику
- invoke CallWindowProc,[OldProc],[hEdit],[uMsg],\
- [wParam],[lParam]
- ret
- .wm_paint:
- mov ebx,[hEdit]
- ; Размеры окна
- lea edi,[rcClient]
- invoke GetClientRect,ebx,edi
- ; Получить текст из свойств
- invoke GetProp,ebx,szProp
- mov [text],eax
- ; Начать рисование
- lea eax,[ps]
- invoke BeginPaint,ebx,eax
- mov [hDC],eax
- ; Шрифт
- invoke SelectObject,[hDC],[hFont]
- invoke SetBkMode,[hDC],TRANSPARENT
- ; Отрисовать общий фон
- invoke GetSysColorBrush,COLOR_WINDOW
- invoke FillRect,[hDC],edi,eax
- ; Текст для отрисовки есть?
- cmp [text],0
- je @f
- invoke GetSysColor,COLOR_WINDOWTEXT
- invoke SetTextColor,[hDC],eax
- invoke DrawText,[hDC],buff,-1,edi,\
- DT_NOPREFIX+DT_SINGLELINE+DT_VCENTER+DT_CENTER
- @@:
- ; Вычислить размеры области для заливки
- invoke GetProp,ebx,szPerc
- mov ecx,eax
- mov eax,[edi+RECT.right]
- sub eax,[edi+RECT.left]
- xor edx,edx
- mul ecx
- mov ecx,100
- div ecx
- ; Позиция выполненного прогресса
- add eax,[edi+RECT.left]
- ; Наложить выполненный прогресс
- invoke CreateRectRgn,[edi+RECT.left],[edi+RECT.top],\
- eax,[edi+RECT.bottom]
- invoke SelectClipRgn,[hDC],eax
- invoke GetSysColorBrush,COLOR_HIGHLIGHT
- invoke FillRect,[hDC],edi,eax
- ; Текст для отрисовки есть?
- cmp [text],0
- je @f
- invoke GetSysColor,COLOR_HIGHLIGHTTEXT
- invoke SetTextColor,[hDC],eax
- invoke DrawText,[hDC],buff,-1,edi,\
- DT_NOPREFIX+DT_SINGLELINE+DT_VCENTER+DT_CENTER
- @@:
- lea eax,[ps]
- invoke EndPaint,[hDC],eax
- invoke ReleaseDC,ebx,[hDC]
- xor eax,eax
- ret
- endp
- szProp db 'text',0
- szPerc db 'percent',0
Code (Assembler) : Убрать нумерацию
- ; Шрифт текста
- invoke CreateFont,32,12,0,0,FW_BOLD,FALSE,FALSE,FALSE,\
- ANSI_CHARSET,OUT_RASTER_PRECIS,\
- CLIP_DEFAULT_PRECIS,PROOF_QUALITY,\
- FIXED_PITCH+FF_DONTCARE,szFont
- mov [hFont],eax
- ; Хэндл ProgressBar
- invoke GetDlgItem,[hwnddlg],ID_PROGRESS
- mov ebx,eax
- ; Сформировать строку для отрисовки
- invoke wsprintf,buff,szText,[percent]
- add esp,12
- ; Назначить строку свойством ProgressBar
- invoke SetProp,ebx,szProp,buff
- ; Назначить значение процента свойством ProgressBar
- invoke SetProp,ebx,szPerc,[percent]
- ; Перерисовать содержимое окна
- invoke InvalidateRect,ebx,0,FALSE
В приложении пример программы с исходным текстом, которая выводит на форму кастомизированный индикатор прогресса с наложением текста.
Просмотров: 1187 | Комментариев: 1
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Сергей Озеров
(16.05.2022 в 11:57):
Утащил себе,буду изучать
Добавить комментарий
Заполните форму для добавления комментария