Обработка заставок
API Microsoft Win32 поддерживает специальные приложения, называемые заставки. Экранные заставки запускаются, когда мышь и клавиатура простаивают в течение указанного периода времени. Они используются по двум причинам:
- Для защиты экрана от выгорания фосфора, вызванного статическими изображениями.
- Чтобы скрыть конфиденциальную информацию, оставленную на экране.
Этот раздел состоит из следующих подразделов.
Сведения о заставки
Классическое приложение в Windows панель управления позволяет пользователям выбрать из списка заставок, указать, сколько времени должно пройти до запуска заставки, настроить заставки и предварительный просмотр заставок. Заставки загружаются автоматически при запуске Windows или при активации пользователем заставки с помощью панель управления.
После выбора заставки Windows отслеживает нажатия клавиш и движения мыши, а затем запускает заставку после периода бездействия. Тем не менее Windows не запускает заставку, если существует какое-либо из следующих условий:
- Активное приложение не является приложением на основе Windows.
- Имеется окно компьютерного обучения (CBT).
- Активное приложение получает сообщение WM_SYSCOMMAND с параметром wParam , равным значению SC_SCREENSAVE, но не передает его в функцию DefWindowProc .
Контекст безопасности заставки
Контекст безопасности заставки зависит от того, вошел ли пользователь в интерактивном режиме. Если пользователь входит в систему в интерактивном режиме при вызове заставки, заставка запускается в контексте безопасности интерактивного пользователя. Если пользователь не вошел в систему, контекст безопасности заставки зависит от используемой версии Windows.
- Windows XP и Windows 2000 — заставка с экрана выполняется в контексте LocalSystem с ограниченными учетными записями.
- Windows 2003 — заставка запускается в контексте LocalService с удаленными привилегиями и отключенной группой администраторов.
- Не применяется к Windows NT4.
Контекст безопасности определяет уровень привилегированных операций, которые можно выполнять с помощью заставки.
Windows Vista и более поздних версий: Если защита паролем включена политикой, заставка запускается независимо от того, что приложение делает с уведомлением SC_SCREENSAVE.
Заставки содержат определенные экспортированные функции, определения ресурсов и объявления переменных. Библиотека заставки содержит функцию main и другой код запуска, необходимый для заставки. При запуске заставки код запуска в библиотеке заставки создает полноэкранное окно. Класс window для этого окна объявляется следующим образом:
WNDCLASS cls;
cls.hCursor = NULL;
cls.hIcon = LoadIcon(hInst, MAKEINTATOM(ID_APP));
cls.lpszMenuName = NULL;
cls.lpszClassName = "WindowsScreenSaverClass";
cls.hbrBackground = GetStockObject(BLACK_BRUSH);
cls.hInstance = hInst;
cls.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS;
cls.lpfnWndProc = (WNDPROC) ScreenSaverProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;
Чтобы создать заставку, большинство разработчиков создают модуль исходного кода, содержащий три необходимые функции, и связывают их с библиотекой заставки. Модуль заставки отвечает только за настройку себя и предоставление визуальных эффектов.
Одной из трех обязательных функций в модуле заставки является ScreenSaverProc. Эта функция обрабатывает определенные сообщения и передает все необработанные сообщения обратно в библиотеку заставки. Ниже приведены некоторые из типичных сообщений, обрабатываемых ScreenSaverProc.
Сообщение | Значение |
---|---|
WM_CREATE | Получение всех данных инициализации из файла Regedit.ini. Задайте таймер окна для окна заставки. Выполните любую другую требуемую инициализацию. |
WM_ERASEBKGND | Очистите окно заставки и подготовьтесь к последующим операциям рисования. |
WM_TIMER | Выполнение операций рисования. |
WM_DESTROY | Уничтожьте таймеры, созданные при обработке приложением сообщения WM_CREATE . Выполните дополнительную необходимую очистку. |
ScreenSaverProc передает необработанные сообщения в библиотеку заставки, вызывая функцию DefScreenSaverProc . В следующей таблице описано, как эта функция обрабатывает различные сообщения.
Message | Действие |
---|---|
WM_SETCURSOR | Присвойте курсору значение NULL, удалив его с экрана. |
WM_PAINT | Закрашивать фон экрана. |
WM_LBUTTONDOWN | Завершите заставку. |
WM_MBUTTONDOWN | Завершите заставку. |
WM_RBUTTONDOWN | Завершите заставку. |
WM_KEYDOWN | Завершите заставку. |
WM_MOUSEMOVE | Завершите заставку. |
WM_ACTIVATE | Завершите работу заставки, если для параметра wParam задано значение FALSE. |
Вторая обязательная функция в модуле заставки — ScreenSaverConfigureDialog. Эта функция отображает диалоговое окно, позволяющее пользователю настроить заставку (приложение должно предоставить соответствующий шаблон диалогового окна). Windows отображает диалоговое окно конфигурации, когда пользователь нажимает кнопку "Настройка" в диалоговом окне "Заставка экрана" панель управления.
Третья обязательная функция в модуле заставки — RegisterDialogClasses. Эта функция должна вызываться всеми приложениями экранной заставки. Однако приложения, которым не требуются специальные окна или пользовательские элементы управления в диалоговом окне конфигурации, могут просто возвращать значение TRUE. Приложения, требующие специальных окон или пользовательских элементов управления, должны использовать эту функцию для регистрации соответствующих классов окон.
Помимо создания модуля, который поддерживает три только что описанные функции, заставка должна предоставить значок. Этот значок отображается только в том случае, если заставка выполняется как автономное приложение. (Для запуска панель управления заставка должна иметь расширение SCR. Для запуска в качестве автономного приложения она должна иметь расширение имени файла .exe.) Значок должен быть идентифицирован в файле ресурсов заставки константой ID_APP, которая определена в файле заголовка Scrnsave.h.
Последним требованием является строка описания заставки. Файл ресурсов для заставки должен содержать строку, которую панель управления отображает в качестве имени заставки. Строка описания должна быть первой строкой в таблице строк файла ресурсов (идентифицируемой порядковым значением 1). Однако строка описания игнорируется панель управления, если заставка имеет длинное имя файла. В этом случае имя файла будет использоваться в качестве строки описания.
Использование функций заставки
В этом разделе используется пример кода, взятого из приложения заставки для демонстрации следующих задач:
- Создание заставки
- Установка новых заставок
- Добавление справки в диалоговое окно "Настройка заставки"
Создание заставки
С интервалами от 1 до 10 секунд приложение в этом примере перерисовывает экран одним из четырех цветов: белым, светло-серым, темно-серым и черным. Приложение закрашивает экран каждый раз, когда получает WM_TIMER сообщение. Пользователь может настроить интервал отправки этого сообщения, выбрав диалоговое окно конфигурации приложения и настроив одну горизонтальную полосу прокрутки.
Библиотека заставки
Функции статической заставки экрана содержатся в библиотеке заставки. Доступны две версии библиотеки: Scrnsave.lib и Scrnsavw.lib. Необходимо связать проект с одним из них. Scrnsave.lib используется для заставок, использующих символы ANSI, а Scrnsavw.lib — для заставок, использующих символы Юникода. Заставка, связанная с Файлом Scrnsavw.lib, будет работать только на платформах Windows, поддерживающих Юникод, а заставка, связанная с Файлом Scrnsave.lib, будет работать на любой платформе Windows.
Поддержка диалогового окна конфигурации
Большинство экранных заставок предоставляют диалоговое окно конфигурации, с помощью чего пользователь может указать данные настройки, такие как уникальные цвета, скорость рисования, толщина линий, шрифты и т. д. Для поддержки диалогового окна конфигурации приложение должно предоставить шаблон диалогового окна, а также должно поддерживать функцию ScreenSaverConfigureDialog . Ниже приведен шаблон диалогового окна для примера приложения.
DLG_SCRNSAVECONFIGURE DIALOG 6, 18, 160, 63
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Sample Screen-Saver Setup"
FONT 8, "MS Shell Dlg"
BEGIN
GROUPBOX "Redraw Speed", 101, 0, 6, 98, 40
SCROLLBAR ID_SPEED, 5, 31, 89, 10
LTEXT "Fast", 103, 6, 21, 20, 8
LTEXT "Slow", 104, 75, 21, 20, 8
PUSHBUTTON "OK", ID_OK, 117, 10, 40, 14
PUSHBUTTON "Cancel", ID_CANCEL, 117, 32, 40, 14
END
Необходимо определить константу, используемую для идентификации шаблона диалогового окна, используя десятичное значение 2003, как показано в следующем примере:
#define DLG_SCRNSAVECONFIGURE 2003
В следующем примере показана функция ScreenSaverConfigureDialog , найденная в примере приложения.
#define MINVEL 1 // minimum redraw speed value
#define MAXVEL 10 // maximum redraw speed value
#define DEFVEL 5 // default redraw speed value
LONG lSpeed = DEFVEL; // redraw speed variable
extern HINSTANCE hMainInstance; // screen saver instance handle
CHAR szAppName[80]; // .ini section name
CHAR szTemp[20]; // temporary array of characters
CHAR szRedrawSpeed[ ] = "Redraw Speed"; // .ini speed entry
CHAR szIniFile[MAXFILELEN]; // .ini or registry file name
BOOL WINAPI ScreenSaverConfigureDialog(hDlg, message, wParam, lParam)
HWND hDlg;
UINT message;
DWORD wParam;
LONG lParam;
HRESULT hr;
{
static HWND hSpeed; // handle to speed scroll bar
static HWND hOK; // handle to OK push button
switch(message)
{
case WM_INITDIALOG:
// Retrieve the application name from the .rc file.
LoadString(hMainInstance, idsAppName, szAppName,
80 * sizeof(TCHAR));
// Retrieve the .ini (or registry) file name.
LoadString(hMainInstance, idsIniFile, szIniFile,
MAXFILELEN * sizeof(TCHAR));
// TODO: Add error checking to verify LoadString success
// for both calls.
// Retrieve any redraw speed data from the registry.
lSpeed = GetPrivateProfileInt(szAppName, szRedrawSpeed,
DEFVEL, szIniFile);
// If the initialization file does not contain an entry
// for this screen saver, use the default value.
if(lSpeed > MAXVEL || lSpeed < MINVEL)
lSpeed = DEFVEL;
// Initialize the redraw speed scroll bar control.
hSpeed = GetDlgItem(hDlg, ID_SPEED);
SetScrollRange(hSpeed, SB_CTL, MINVEL, MAXVEL, FALSE);
SetScrollPos(hSpeed, SB_CTL, lSpeed, TRUE);
// Retrieve a handle to the OK push button control.
hOK = GetDlgItem(hDlg, ID_OK);
return TRUE;
case WM_HSCROLL:
// Process scroll bar input, adjusting the lSpeed
// value as appropriate.
switch (LOWORD(wParam))
{
case SB_PAGEUP:
--lSpeed;
break;
case SB_LINEUP:
--lSpeed;
break;
case SB_PAGEDOWN:
++lSpeed;
break;
case SB_LINEDOWN:
++lSpeed;
break;
case SB_THUMBPOSITION:
lSpeed = HIWORD(wParam);
break;
case SB_BOTTOM:
lSpeed = MINVEL;
break;
case SB_TOP:
lSpeed = MAXVEL;
break;
case SB_THUMBTRACK:
case SB_ENDSCROLL:
return TRUE;
break;
}
if ((int) lSpeed <= MINVEL)
lSpeed = MINVEL;
if ((int) lSpeed >= MAXVEL)
lSpeed = MAXVEL;
SetScrollPos((HWND) lParam, SB_CTL, lSpeed, TRUE);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_OK:
// Write the current redraw speed variable to
// the .ini file.
hr = StringCchPrintf(szTemp, 20, "%ld", lSpeed);
if (SUCCEEDED(hr))
WritePrivateProfileString(szAppName, szRedrawSpeed,
szTemp, szIniFile);
case ID_CANCEL:
EndDialog(hDlg, LOWORD(wParam) == ID_OK);
return TRUE;
}
}
return FALSE;
}
Помимо предоставления шаблона диалогового окна и поддержки функции ScreenSaverConfigureDialog , приложение также должно поддерживать функцию RegisterDialogClasses . Эта функция регистрирует все нестандартные классы окон, необходимые для заставки. Так как в примере приложения в процедуре диалогового окна использовались только стандартные классы окон, эта функция просто возвращает значение TRUE, как показано в следующем примере:
BOOL WINAPI RegisterDialogClasses(hInst)
HANDLE hInst;
{
return TRUE;
}
Поддержка процедуры окна заставки
Каждая заставка должна поддерживать процедуру окна с именем ScreenSaverProc. Как и большинство оконных процедур, ScreenSaverProc обрабатывает набор определенных сообщений и передает все необработанные сообщения в процедуру по умолчанию. Однако вместо передачи их в функцию DefWindowProcScreenSaverProc передает необработанные сообщения в функцию DefScreenSaverProc . Еще одно различие между ScreenSaverProc и обычной процедурой окна заключается в том, что дескриптор, передаваемый в ScreenSaverProc , идентифицирует весь рабочий стол, а не клиентское окно. В следующем примере показана процедура окна ScreenSaverProc для примера заставки.
LONG WINAPI ScreenSaverProc(hwnd, message, wParam, lParam)
HWND hwnd;
UINT message;
DWORD wParam;
LONG lParam;
{
static HDC hdc; // device-context handle
static RECT rc; // RECT structure
static UINT uTimer; // timer identifier
switch(message)
{
case WM_CREATE:
// Retrieve the application name from the .rc file.
LoadString(hMainInstance, idsAppName, szAppName, 80 * sizeof(TCHAR));
// Retrieve the .ini (or registry) file name.
LoadString(hMainInstance, idsIniFile, szIniFile, MAXFILELEN * sizeof(TCHAR));
// TODO: Add error checking to verify LoadString success
// for both calls.
// Retrieve any redraw speed data from the registry.
lSpeed = GetPrivateProfileInt(szAppName, szRedrawSpeed,
DEFVEL, szIniFile);
// Set a timer for the screen saver window using the
// redraw rate stored in Regedit.ini.
uTimer = SetTimer(hwnd, 1, lSpeed * 1000, NULL);
break;
case WM_ERASEBKGND:
// The WM_ERASEBKGND message is issued before the
// WM_TIMER message, allowing the screen saver to
// paint the background as appropriate.
hdc = GetDC(hwnd);
GetClientRect (hwnd, &rc);
FillRect (hdc, &rc, GetStockObject(BLACK_BRUSH));
ReleaseDC(hwnd,hdc);
break;
case WM_TIMER:
// The WM_TIMER message is issued at (lSpeed * 1000)
// intervals, where lSpeed == .001 seconds. This
// code repaints the entire desktop with a white,
// light gray, dark gray, or black brush each
// time a WM_TIMER message is issued.
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rc);
if (i++ <= 4)
FillRect(hdc, &rc, GetStockObject(i));
else
(i = 0);
ReleaseDC(hwnd,hdc);
break;
case WM_DESTROY:
// When the WM_DESTROY message is issued, the screen saver
// must destroy any of the timers that were set at WM_CREATE
// time.
if (uTimer)
KillTimer(hwnd, uTimer);
break;
}
// DefScreenSaverProc processes any messages ignored by ScreenSaverProc.
return DefScreenSaverProc(hwnd, message, wParam, lParam);
}
Создание файла определения модуля
Функции ScreenSaverProc и ScreenSaverConfigureDialog должны быть экспортированы в файл определения модуля приложения; Однако не следует экспортировать RegisterDialogClasses . В следующем примере показан файл определения модуля для примера приложения.
NAME SSTEST.SCR
DESCRIPTION 'SCRNSAVE : Test'
STUB 'WINSTUB.EXE'
EXETYPE WINDOWS
CODE MOVEABLE
DATA MOVEABLE MULTIPLE
HEAPSIZE 1024
STACKSIZE 4096
EXPORTS
ScreenSaverProc
ScreenSaverConfigureDialog
Установка новых заставок
При компиляции списка доступных заставок панель управления выполняет поиск файлов с расширением SCR в каталоге автозагрузки Windows. Так как заставки — это стандартные исполняемые файлы Windows с расширениями .exe, их необходимо переименовать, чтобы у них были расширения SCR, и скопировать их в правильный каталог.
Добавление справки в диалоговое окно "Настройка заставки"
Диалоговое окно конфигурации для заставки обычно содержит кнопку Справка . Приложения-заставки могут проверка идентификатор кнопки "Справка" и вызывать функцию WinHelp так же, как в других приложениях windows.