Поделиться через


Обработка заставок

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.