Splash-окно при загрузке программы
При запуске некоторых приложений иногда требуется выполнить какие-нибудь ресурсоемкие или продолжительные по времени действия, например, загрузка дополнительных модулей, сбор информации о системе, распаковка файлов данных и т.п. Часто во время таких процессов открывается так называемое splash-окно (его также называют "сплэш-окно" или сокращенно "сплэш"), то есть модальное окно без заголовка, расположенное по центру экрана, обычно с логотипом и названием программы. Также в нем меняющейся строкой отображается текущее действие программы, и, иногда, полоса прогресса выполнения. Таким образом пользователя как бы уведомляют, что программа не зависла при запуске, а просто выполняет нужные ей действия и надо немного подождать. После появления главного окна программы сплэш закрывается. Попробуем сделать что-нибудь подобное на Ассемблере.Сперва нарисуем само окно. Оно должно быть без заголовка, модальное, можно разместить на нем картинку-логотип. Для большего эффекта добавим на это окно прогрессбар и текстовое поле для отображения состояния загрузки.
Code (Assembler) : Убрать нумерацию
- ; Стиль прогрессбара - непрерывный бегунок. В FASM значение не определено,
- ; сделаем это самостоятельно
- PBS_MARQUEE = 8
- dialog demonstration,' Splash Demo',0, 0, 150, 60,\
- WS_POPUP+DS_CENTER+DS_SYSMODAL+WS_BORDER, WS_EX_TOOLWINDOW,0,'Arial',10
- dialogitem 'STATIC',1, 1, 0, 0, 138, 38 ,WS_VISIBLE+SS_BITMAP
- dialogitem 'STATIC','Loading...',ID_TEXT, 0, 34, 150, 8 ,WS_VISIBLE+SS_CENTER
- dialogitem 'msctls_progress32', '', IDC_PROGRESS, 3, 47, 145, 10,\
- WS_VISIBLE+PBS_MARQUEE
- dialogitem 'BUTTON','',IDCANCEL, 0, 0, 0, 0, 0
- enddialog
Переходим к программированию. Чтобы открытое splash-окно не мешало выполнению основного приложения, его надо запускать в отдельном потоке в самом начале программы:
Code (Assembler) : Убрать нумерацию
- ; Запустить splash-окно отдельным потоком
- xor eax,eax
- push eax
- invoke CreateThread,NULL,NULL,SplashProc,NULL,NULL,esp
- pop eax
- ...
- ;---------------------------------------------
- ; Процедура открытия splash-окна отдельным потоком
- ;---------------------------------------------
- proc SplashProc hwnd:DWORD
- ; Показать сплэш-окно
- invoke DialogBoxParam,[hInstance],1,HWND_DESKTOP,DialogProc,0
- ret
- endp
Остался последний вопрос - как осуществить взаимодействие приложения со сплэш-окном, а именно передача строки текущего состояния, установка процента выполнения на прогрессбаре (если выбран такой вариант реализации) и как закрыть сплэш-окно из главного приложения. Для всего этого есть несколько способов, я сделал такой. В обработчике splash-окна устанавливается таймер, например, на интервал 10 миллисекунд. В памяти приложения устанавливаются глобальные переменные: текстовая строка сообщения с текущим состоянием, процент выполнения (если требуется) и флаг необходимости закрытия окна. Основное приложение выполняет свою загрузку, периодически записывая в строку текущее состояние и процент, а после загрузки взводит флаг необходимости закрытия сплэша. Обработчик сплэша по таймеру считывает строку состояния и процент выполнения, и на основании этих данных устанавливает соответствующие значения у себя. Если установлен флаг закрытия, то окно сплэша закрывается.
В приложении пример программы со сплэш-окном, в котором отображается прогрессбар и текущий статус выполнения. После открытия главного окна сплэш-окно закрывается.
Просмотров: 7115 | Комментариев: 10
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(04.04.2011 в 14:50):
Можно субклассировать и прогрессбар, была бы необходимость.
Isaev
(04.04.2011 в 14:49):
Приятное окошко! Поучительно.
В общем таскаться Splash-окну и не обязательно, но раз таскается, надо было сделать чтобы и за ProgressBar тоже цеплялось )
В общем таскаться Splash-окну и не обязательно, но раз таскается, надо было сделать чтобы и за ProgressBar тоже цеплялось )
ezfalc0n
(03.04.2011 в 21:42):
уточнение: посты ниже адресовал 64-ядерный процессор. "Сплэш-окно при загрузке программы" и что-то вроде "Защищенное сплэш-окно" разные темы. Могу представить, если б, Дима, тебе пришлось при написании статьи учитывать все "а вдруг" и "а если" - этоб по книге было на каждую тему. Колесо дали - а велосипед, уж извольте, сами =)
ezfalc0n
(03.04.2011 в 05:04):
Насчет взаимодействия можно конечно использовать обмен сообщениями WM_USER+message между процедурами. Или, если необходимо знать как дела у потока, можно обязать его обновлять глобальную переменную счетчик "ticker". На всякий случай, для cpp - переменную определять через volatile.
Дима, спасибо - понастальгировал
Дима, спасибо - понастальгировал
ezfalc0n
(03.04.2011 в 04:52):
Подобная картинка генерится на ходу, без особых затрат, через CreateFontEx, BitBlt и иже с ними. Можно еще анимацию в стиле plasma/flame и т.д. добавить. Также можно хранить ее в адаптированном RLE, места будет занимать немного.
ManHunter
(30.03.2011 в 20:50):
Ну в общем это и имелось в виду. И ладно на шару, хуже если на продажу :)
64-ядерный процессор
(30.03.2011 в 19:41):
ManHunter, на счёт "какой-нибудь мудила" - не знаю, а вот то что всякие ублюдки будут выставлять прогу на шару и при этом вставлять свой левый логотип - это точно.
ManHunter
(30.03.2011 в 18:06):
Можно и так. Но в этом случае придется добавлять обработчик ошибок, если вдруг картинка куда-то потерялась, и непонятно что рисовать в сплэше в случае такой ошибки. Плюс обязательно найдется какой-нибудь мудила, который заменит ее на свой логотип. Так что хранить в ресурсах удобнее, надежнее и проще всего.
zummenix
(30.03.2011 в 18:03):
Чтобы не держать бмпешку в ресурсах можно загружать ее функцией LoadImage и удалять при закрытии сплэш-окна.
1
(30.03.2011 в 14:22):
Спасибо, занятно.
Добавить комментарий
Заполните форму для добавления комментария