Мини-практикум по C++Иван Гаврилюк Хранитель экрана, который мы сегодня вместе с вами сделаем, будет работать в фоновом режиме, при этом, естественно, он не должен мешать работе других приложений и потреблять минимум ресурсов. Технически хранитель экрана является обычным исполняемым файлом Windows (*.exe) полностью управляемым сообщениями ОС, но переименованным в *.scr. При разработке будет использоваться среда Microsoft Visual C++, так как автор статьи довольно долго с ней работает. Вместе с тем, для нашей задачи вполне можно было использовать любой другой компилятор, например, Borland C++ Builder или Watcom C++. Для уменьшения объема исполняемого файла в описанной программе не используется библиотека высокого уровня MFC или CLX(VCL), вся работа выполняется только средствами Win32 API. Также не используются объектно-ориентированные расширения языка. В результате размер программы удается уменьшить приблизительно до 35 Kб. Для создания хранителей экрана в комплект Visual C++ входит заголовочный файл scrnsave.h (D:\Program Files\ Microsoft Visual Studio\VC98 \Include\scrnsave.h), в котором находятся определения всех констант и функций, необходимых для работы screensaver'а в среде Windows 9x/NT, а также статическая библиотека scrnsave.lib. Точка входа в программу (функция WinMain) находится в самой scrnsave.lib, что очень сильно облегчает нам жизнь. Наш хранитель пишется ориентировочно для Windows NT (другого у меня нету), хотя должен работать на всех платформах. Различие состоит в том, что для Windows 9x приходится писать еще одну функцию, отвечающую за смену пароля. В NT и выше эту роль выполняет системный процесс Winlogon. Если ключ HKEY_CURRENT_USER\ Control Panel\Desktop\ ScreenSaverIsSecure в системном реестре Windows не равен нулю, то Winlogon будет запрашивать пароль перед выходом из скринсейвера. Хотя без этой функции можно и обойтись.
Для работы хранителя необходимо написать всего 3 функции (фактически только одну): 1. LRESULT WINAPI ScreenSaverProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); является «функцией окна» хранителя. Она получает все сообщения системы (аналог функции WinMain в чистом Windows-приложении). Первый параметр hWnd идентификатор окна нашего хранителя, message код сообщения, которое получил хранитель от системы, wParam и lParam параметры сообщения. В данной функции программист должен перехватить все интересующие его сообщения, а неперехваченные передать на обработку функции LRESULT WINAPI DefScreenSaverProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 2. BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); функция вызывается системой всякий раз, когда пользователь нажимает кнопку «настройка...» в окне настройки хранителей экрана (Пуск >Настройка >Панель управления >Экран >Заставка). 3. BOOL WINAPI RegisterDialogClasses (HANDLE hInst); вызывается системой для регистрации в ней дополнительных классов (мы ее не будем использовать). Итак, в новом ранее созданном окне пишем следующий код:
При нажатии кнопки Просмотр ничего не происходит так и должно быть, ведь функция ScreenSaverProc пуста. Наш хранитель запускается и тут же завершает свою работу. Давайте наполним эту функцию каким-нибудь полезным кодом. Впишем, например, в нее код, рисующий два вложенных квадрата, вращающихся в противоположные стороны. Для этого подключим еще один заголовочный файл math.h для работы с математикой: #include <math.h>. В начале файла после директив #include определим глобально число pi, а заодно 2*pi и pi/2, чтобы каждый раз их не вычислять: Функцию ScreenSaverProc наполним следующим содержанием: А теперь подробно что делает каждая строчка кода. В первых семи определяются переменные для дальнейшего использования. ps экземпляр структуры PAINTSTRUCT (рассмотрим далее), hDC идентификатор контекста дисплея, hPen1 кисть для рисования, uTimer идентификатор таймера (используется для анимации квадратов), x_max, y_max в этих переменных будет храниться разрешение экрана, step, angle приращение угла поворота и сам угол поворота квадрата, center_x, center_y координаты центра квадрата. Далее с помощью функции switch() организуется ветвление в зависимости от того, какое сообщение пришло от системы (message). WM_CREATE это сообщение приходит один раз при создании приложения. При помощи Win32-API функции GetSystemMetrix получаем разрешение экрана Вашего монитора и помещаем в переменные x_max и y_max. Находим координаты цента экрана обычным делением на 2 предыдущих параметров и помещаем в center_x и center_y. Устанавливаем при помощи функции SetTimer виртуальный таймер в систему. Здесь hWnd идентефикатор окна, которое будет получать сообщения от таймера. Второй параметр порядковый номер таймера в нашем приложении (можно установить несколько), третий время в миллисекундах, через которое приложение должно получать сообщения от таймера; устанавливаем на 10 миллисекунд. Четвертый функция таймера, она будет получать управление через количество миллисекунд, заданное в третьем параметре. Так как мы написали NULL, то таймер будет извещать окно приложения, посылая ему сообщение WM_TIMER. Осталось разобраться с функцией GetStockObject(). Она извлекает графический объект из стандартного репозитория Windows. В нашем случае мы достаем белую кисть (WHITE_PEN), которой будем рисовать в дальнейшем. WM_DESTROY приходит тоже один раз, при уничтожении окна нашего приложения. Здесь мы при помощи функции KillTimer() снимаем таймер с нашего окна. hWnd идентефикатор нашего окна, uTimer указатель на таймер, полученный функцией SetTimer. Наконец, функцией PostQuitMessage посылаем сообщение системе о выходе из приложения. Если этого не сделать, то окно будет уничтожено, но программа будет продолжать работать.
WM_PAINT это сообщение происходит при перерисовке окна. Первыми 4 строками мы опять же узнаем разрешение экрана и высчитываем центр. Далее вызываем функцию BeginPaint(). Она подготавливает определенное окно для рисования (hWnd), заполняет структуру типа PAINTSTRUCT (ps) информацией о рисовании и возвращает в hDC указатель на контекст устройства, в нашем случае дисплея. В условном операторе определяем, находимся ли мы в режиме просмотра, или окно развернуто на полный экран; это можно проверить при помощи флага fChildPreview (true просмотр). Если в режиме просмотра, то выводим текстовую строку «Мой хранитель :-)». Для этого сначала функцией SetBkColor() устанавливаем цвет фона для нашего контекста устройства (hDC), макрос RGB(r, g, b) преобразует интенсивность красного (r), зеленого (g) и желтого (b) цветов в тип COLORREF, переменную такого типа принимает в качестве второго параметра функция SetBkColor(). Аналогично функцией SetTextColor() устанавливаем цвет текста. Наконец, выводим строку szPreview при помощи TextOut() на дисплей. Она принимает в качестве параметров указатель контекста, координаты строки, саму строку и ее длину (вычисляем при помощи встроенной функции strlen()). У Вас должна получиться картинка, представленная на Рис. 3.
Теперь компилируйте проект (F7), переименовывайте ssaver.exe в ssaver.scr, пихайте в системную папку Windows и наслаждайтесь :-). Должно получиться что-то вроде представленного на Рис. 4. Готовый проект можно взять здесь: http://www.nap2k.narod.ru/ ssaver/sssource.exe (9.1 Кб), откомпилированный здесь: http://www.nap2k.narod.ru/ ssaver/ssaver.scr (36.8 Кб). Источник: http://www.mycomp.com.ua/
| |
Copyright © "Internet Zone", http://www.izcity.com/, info@izcity.com |