MessageBox с таймером обратного отсчета
MessageBox с таймером обратного отсчета
Наверняка вы сталкивались с диалоговыми окнами и окнами сообщений, в которых какое-то действие может быть выполнено только после истечения некоторого времени или которые сами продолжат работу через какой-то интервал. Это, например, могут быть инсталляторы, дающие пользователю возможность передумать, но начинающие установку обновлений через несколько секунд, если подтверждения от пользователя не было получено. Или уведомление о завершении какой-либо операции, которое пользователь прочитает и закроет, если в данный момент он находится у монитора. То есть в таких ситуациях, когда и пользователя надо о чем-то поставить в известность, но при этом обязательной ответной реакции от него ждать не требуется, так как с большой вероятностью он сделает именно так же или у него вообще не будет других вариантов. Примерно такое же поведение используют триальные окна, когда кнопка "OK" блокируется и вам приходится какое-то время наблюдать предложение метнуться в кассу.
Диалоговые окна мы рассматривать не будем, так как там сразу же настраиваются функции обработки и все делается элементарно. А вот обычный MessageBox в качестве примера будет интересен. Первым делом надо получить хэндл окна MessageBox. Делается это следующим образом:
Code (Assembler) : Убрать нумерацию
- ; Получить хэндл текущего потока
- invoke GetCurrentThreadId
- ; Установить перехватчик событий
- invoke SetWindowsHookEx,WH_CBT,MBHookProc,NULL,eax
- mov [hMBHook],eax
- invoke MessageBox,HWND_DESKTOP,szMess,szTitle,MB_OK
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Перехватчик открытия MessageBox
- ;---------------------------------------------
- proc MBHookProc nCode:DWORD,wParam:DWORD,lParam:DWORD
- ; Сохранить все регистры
- pusha
- cmp [nCode],0
- jb @f
- cmp [nCode],HCBT_ACTIVATE
- jne @f
- ; Начальное значение таймера
- mov [dTimer],10
- ; Установить таймер окна MessageBox
- invoke SetTimer,[wParam],1,1000,TimerProc
- ; Сформировать начальную строку
- invoke wsprintf,buff,mask,[dTimer]
- add esp,12
- ; Установить текст на кнопку
- invoke GetDlgItem,[wParam],IDOK
- invoke SetWindowText,eax,buff
- ; Снять перехватчик
- invoke UnhookWindowsHookEx,[hMBHook]
- ; Восстановить регистры
- popa
- xor eax,eax
- ret
- @@:
- ; Восстановить регистры
- popa
- ; Передать управление следующему обработчику
- invoke CallNextHookEx,[hMBHook],[nCode],[wParam],[lParam]
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Функция таймера для MessageBox
- ;---------------------------------------------
- proc TimerProc hwnd:DWORD,uMsg:DWORD,idEvent:DWORD,dwTime:DWORD
- pusha
- ; Время вышло?
- cmp [dTimer],1
- ja @f
- ; Закрыть окно по истечении времени
- invoke DestroyWindow,[hwnd]
- jmp .loc_exit
- @@:
- ; Уменьшить таймер
- dec [dTimer]
- invoke wsprintf,buff,mask,[dTimer]
- add esp,12
- ; Установить текст на кнопку
- invoke GetDlgItem,[hwnd],2
- invoke SetWindowText,eax,buff
- .loc_exit:
- popa
- ret
- endp
Если же красота с тикающим таймером не требуется, а надо просто вывести сообщение, которое через заданный промежуток времени должно исчезнуть, то можно воспользоваться функцией MessageBoxTimeout. По какой-то причине она относится к недокументированным, хотя совершенно спокойно импортируется из user32.dll. Вызов аналогичен функции MessageBox, только добавляются два дополнительных параметра - идентификатор языка и таймаут в миллисекундах.
Code (Assembler) : Убрать нумерацию
- ; MessageBox закроется автоматически через 5 секунд
- invoke MessageBoxTimeout,HWND_DESKTOP,szMess,szTitle,MB_OK,0,5000
В приложении примеры программы с исходными текстами, первая открывает MessageBox, а через 10 секунд автоматически его закрывает, если не было реакции со стороны пользователя, вторая программа имитирует триальное окно, третья использует функцию MessageBoxTimeout для создания и автоматического закрытия окна сообщения.
Просмотров: 2068 | Комментариев: 6
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(01.02.2021 в 15:15):
А еще способ из статьи прекрасно работает с окнами сообщений, которые создает MessageBoxIndirect. MessageBoxTimeout не позволяет создавать сообщения с пользовательскими иконками в окне без дополнительных танцев с бубнами.
user
(01.02.2021 в 02:35):
Полезная статья.
Собирался как раз приторочить такую функцию к паре утилит,
но собирался делать это с помошью MessageBoxTimeout.
Теперь подумаю
Собирался как раз приторочить такую функцию к паре утилит,
но собирался делать это с помошью MessageBoxTimeout.
Теперь подумаю
ManHunter
(31.01.2021 в 14:14):
Дополнил статью описанием MessageBoxTimeout, в архив добавлен пример.
ManHunter
(31.01.2021 в 08:38):
MessageBoxTimeout решает задачу только с автозакрытием окна сообщения. А тут и красивый счетчик, и включение-отключение кнопок, если это все реализовывать, то получатся те же яйца, только чуть с боку.
Но пример с MessageBoxTimeout, пожалуй, добавлю. Лишним не будет.
Но пример с MessageBoxTimeout, пожалуй, добавлю. Лишним не будет.
brute
(31.01.2021 в 06:55):
DRON, пока читал заголовок, сам пытался вспомнить эту функцию, т.к. помню, что была. На счёт недокументированности - не замечал этого, кажется, она среди прочих в mdsn.
DRON
(31.01.2021 в 01:17):
Для таких целей существует недокументированный MessageBoxTimeout:
https://www.codeproject.com/Ar...xTimeout-API
Но он без обратного отсчёта, просто возвращает MB_TIMEDOUT через заданное время.
https://www.codeproject.com/Ar...xTimeout-API
Но он без обратного отсчёта, просто возвращает MB_TIMEDOUT через заданное время.
Добавить комментарий
Заполните форму для добавления комментария