Udostępnij przez


Obsługa wygaszaczy ekranu

Interfejs API Microsoft Win32 obsługuje specjalne aplikacje, zwane wygaszaczami ekranu. Wygaszacze ekranu zaczynają się, gdy mysz i klawiatura były bezczynne przez określony okres czasu. Są one używane z tych dwóch powodów:

  • Aby chronić ekran przed oparzeniem fosforu spowodowanym przez obrazy statyczne.
  • Aby ukryć poufne informacje pozostawione na ekranie.

Ten temat jest podzielony na następujące sekcje.

Informacje o wygaszaczych ekranu

Aplikacja klasyczna w Panelu sterowania systemu Windows umożliwia użytkownikom wybranie z listy wygaszaczy ekranu, określenie, ile czasu należy upłynąć przed uruchomieniem wygaszacza ekranu, skonfigurowaniem wygaszaczy ekranu i podglądem wygaszaczy ekranu. Wygaszacze ekranu są ładowane automatycznie po uruchomieniu systemu Windows lub aktywowaniu wygaszacza ekranu przez Panel sterowania.

Po wybraniu wygaszacza ekranu system Windows monitoruje naciśnięcia i ruch myszy, a następnie uruchamia wygaszacz ekranu po okresie braku aktywności. Jednak system Windows nie uruchamia wygaszacza ekranu, jeśli istnieją jakiekolwiek z następujących warunków:

  • Aktywna aplikacja nie jest aplikacją opartą na systemie Windows.
  • Istnieje okno trenowania komputerowego (CBT).
  • Aktywna aplikacja odbiera komunikat WM_SYSCOMMAND z parametrem wParam ustawionym na wartość SC_SCREENSAVE, ale nie przekazuje komunikatu do funkcji DefWindowProc.

kontekst zabezpieczeń wygaszacza ekranu

Kontekst zabezpieczeń wygaszacza ekranu zależy od tego, czy użytkownik jest zalogowany interaktywnie. Jeśli użytkownik jest zalogowany interaktywnie po wywołaniu wygaszacza ekranu, wygaszacz ekranu jest uruchamiany w kontekście zabezpieczeń użytkownika interaktywnego. Jeśli żaden użytkownik nie jest zalogowany, kontekst zabezpieczeń wygaszacza ekranu jest zależny od używanej wersji systemu Windows.

  • Windows XP i Windows 2000 — wygaszacz ekranu działa w kontekście Systemu lokalnego z ograniczonymi kontami.
  • Windows 2003 — wygaszacz ekranu jest uruchamiany w kontekście usługi lokalnej ze wszystkimi uprawnieniami usuniętymi i wyłączoną grupą administratorów.
  • Nie dotyczy systemu Windows NT4.

Kontekst zabezpieczeń określa poziom uprzywilejowanych operacji, które można wykonać z wygaszacza ekranu.

Windows Vista i nowsze: Jeśli ochrona hasłem jest włączona zgodnie z zasadami, wygaszacz ekranu jest uruchamiany niezależnie od tego, co aplikacja robi z powiadomieniem SC_SCREENSAVE.

Wygaszacze ekranu zawierają określone wyeksportowane funkcje, definicje zasobów i deklaracje zmiennych. Biblioteka wygaszacza ekranu zawiera funkcję main i inny kod uruchamiania wymagany dla wygaszacza ekranu. Po uruchomieniu wygaszacza ekranu kod startowy w bibliotece wygaszacza ekranu tworzy okno pełnoekranowe. Klasa okna dla tego okna jest zadeklarowana w następujący sposób:

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;

Aby utworzyć wygaszacz ekranu, większość deweloperów tworzy moduł kodu źródłowego zawierający trzy wymagane funkcje i łączy je z biblioteką wygaszacza ekranu. Moduł wygaszacza ekranu jest odpowiedzialny tylko za konfigurowanie się i dostarczanie efektów wizualnych.

Jedną z trzech wymaganych funkcji w module wygaszacza ekranu jest ScreenSaverProc. Ta funkcja przetwarza określone komunikaty i przekazuje wszystkie nieprzetworzone komunikaty z powrotem do biblioteki wygaszacza ekranu. Poniżej przedstawiono niektóre typowe komunikaty przetwarzane przez ScreenSaverProc.

Komunikat Znaczenie
WM_CREATE Pobierz wszystkie dane inicjowania z pliku Regedit.ini. Ustaw czasomierz okna dla okna wygaszacza ekranu. Wykonaj inne wymagane inicjowanie.
WM_ERASEBKGND Wymaż okno wygaszacza ekranu i przygotuj się do kolejnych operacji rysowania.
WM_TIMER Wykonywanie operacji rysowania.
WM_DESTROY Zniszczyć czasomierze utworzone, gdy aplikacja przetworzyła komunikat WM_CREATE. Wykonaj dodatkowe wymagane czyszczenie.

 

ScreenSaverProc przekazuje nieprzetworzone komunikaty do biblioteki wygaszacza ekranu przez wywołanie funkcji DefScreenSaverProc. W poniższej tabeli opisano sposób przetwarzania różnych komunikatów przez tę funkcję.

Komunikat Akcja
WM_SETCURSOR Ustaw kursor na kursor o wartości null, usuwając go z ekranu.
WM_PAINT Maluj tło ekranu.
WM_LBUTTONDOWN Zakończ wygaszacz ekranu.
WM_MBUTTONDOWN Zakończ wygaszacz ekranu.
WM_RBUTTONDOWN Zakończ wygaszacz ekranu.
WM_KEYDOWN Zakończ wygaszacz ekranu.
WM_MOUSEMOVE Zakończ wygaszacz ekranu.
WM_ACTIVATE Jeśli parametr wParam jest ustawiony na FALSE, zakończ wygaszacz ekranu.

 

Druga wymagana funkcja w module wygaszacza ekranu to ScreenSaverConfigureDialog. Ta funkcja wyświetla okno dialogowe, które umożliwia użytkownikowi skonfigurowanie wygaszacza ekranu (aplikacja musi podać odpowiedni szablon okna dialogowego). System Windows wyświetla okno dialogowe konfiguracji, gdy użytkownik wybierze przycisk Setup w oknie dialogowym Wygaszacza ekranu w Panelu sterowania.

Trzecia wymagana funkcja w module wygaszacza ekranu to RegisterDialogClasses. Ta funkcja musi być wywoływana przez wszystkie aplikacje wygaszacza ekranu. Jednak aplikacje, które nie wymagają specjalnych okien ani kontrolek niestandardowych w oknie dialogowym konfiguracji, mogą po prostu zwrócić true. Aplikacje wymagające specjalnych okien lub kontrolek niestandardowych powinny używać tej funkcji do rejestrowania odpowiednich klas okien.

Oprócz utworzenia modułu obsługującego trzy opisane funkcje wygaszacz ekranu powinien podać ikonę. Ta ikona jest widoczna tylko wtedy, gdy wygaszacz ekranu jest uruchamiany jako autonomiczna aplikacja. (Aby można było uruchomić przez Panel sterowania, wygaszacz ekranu musi mieć rozszerzenie nazwy pliku scr; aby można było uruchomić jako autonomiczną aplikację, musi mieć rozszerzenie nazwy pliku .exe). Ikona musi zostać zidentyfikowana w pliku zasobów wygaszacza ekranu przez stałą ID_APP, która jest zdefiniowana w pliku nagłówka Scrnsave.h.

Jednym z ostatecznych wymagań jest ciąg opisu wygaszacza ekranu. Plik zasobów wygaszacza ekranu musi zawierać ciąg wyświetlany przez Panel sterowania jako nazwę wygaszacza ekranu. Ciąg opisu musi być pierwszym ciągiem w tabeli ciągów pliku zasobu (identyfikowanym z wartością porządkową 1). Jednak ciąg opisu jest ignorowany przez Panel sterowania, jeśli wygaszacz ekranu ma długą nazwę pliku. W takim przypadku nazwa pliku będzie używana jako ciąg opisu.

Korzystanie z funkcji wygaszacza ekranu

W tej sekcji użyto przykładowego kodu pobranego z aplikacji wygaszacza ekranu, aby zilustrować następujące zadania:

Tworzenie wygaszacza ekranu

W przedziałach od 1 do 10 sekund aplikacja w tym przykładzie przemalowuje ekran na jeden z czterech kolorów: biały, jasnoszary, ciemnoszary i czarny. Aplikacja maluje ekran za każdym razem, gdy otrzymuje komunikat WM_TIMER. Użytkownik może dostosować interwał wysyłania tego komunikatu, wybierając okno dialogowe konfiguracji aplikacji i dostosowując pojedynczy poziomy pasek przewijania.

Biblioteka wygaszacza ekranu

Funkcje wygaszacza ekranu statycznego znajdują się w bibliotece wygaszacza ekranu. Dostępne są dwie wersje biblioteki: Scrnsave.lib i Scrnsavw.lib. Musisz połączyć projekt z jednym z tych elementów. Narzędzie Scrnsave.lib jest używane w przypadku wygaszaczy ekranu korzystających z znaków ANSI, a plik Scrnsavw.lib jest używany w przypadku wygaszaczy ekranu korzystających z znaków Unicode. Wygaszacz ekranu połączony z plikiem Scrnsavw.lib będzie uruchamiany tylko na platformach systemu Windows obsługujących kod Unicode, podczas gdy wygaszacz ekranu połączony z scrnsave.lib będzie uruchamiany na dowolnej platformie systemu Windows.

Obsługa okna dialogowego konfiguracji

Większość wygaszaczy ekranu udostępnia okno dialogowe konfiguracji, aby umożliwić użytkownikowi określenie danych dostosowywania, takich jak unikatowe kolory, szybkość rysowania, grubość linii, czcionki itd. Aby obsługiwać okno dialogowe konfiguracji, aplikacja musi podać szablon okna dialogowego i musi również obsługiwać funkcję ScreenSaverConfigureDialog. Poniżej znajduje się szablon okna dialogowego dla przykładowej aplikacji.

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

Należy zdefiniować stałą używaną do identyfikowania szablonu okna dialogowego przy użyciu wartości dziesiętnej 2003, jak w poniższym przykładzie:

#define  DLG_SCRNSAVECONFIGURE 2003

W poniższym przykładzie przedstawiono funkcję ScreenSaverConfigureDialog znalezioną w przykładowej aplikacji.

#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; 
}

Oprócz udostępniania szablonu okna dialogowego i obsługi funkcji ScreenSaverConfigureDialog aplikacja musi również obsługiwać funkcję RegisterDialogClasses. Ta funkcja rejestruje wszystkie niestandardowe klasy okien wymagane przez wygaszacz ekranu. Ponieważ przykładowa aplikacja używała tylko standardowych klas okien w swojej procedurze okna dialogowego, ta funkcja po prostu zwraca true, jak w poniższym przykładzie:

BOOL WINAPI RegisterDialogClasses(hInst) 
HANDLE  hInst; 
{ 
    return TRUE; 
}

Obsługa procedury okna wygaszacza ekranu

Każdy wygaszacz ekranu musi obsługiwać procedurę okna o nazwie ScreenSaverProc. Podobnie jak większość procedur okien, ScreenSaverProc przetwarza zestaw określonych komunikatów i przekazuje wszystkie nieprzetworzone komunikaty do procedury domyślnej. Jednak zamiast przekazywać je do funkcji DefWindowProc, ScreenSaverProc przekazuje nieprzetworzone komunikaty do funkcji DefScreenSaverProc. Inną różnicą między ScreenSaverProc a normalną procedurą okna jest to, że dojście przekazane do ScreenSaverProc identyfikuje cały pulpit, a nie okno klienta. W poniższym przykładzie przedstawiono procedurę okna ScreenSaverProc dla przykładowego wygaszacza ekranu.

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); 
}

Tworzenie pliku definicji modułu

Funkcje ScreenSaverProc i ScreenSaverConfigureDialog muszą zostać wyeksportowane w pliku definicji modułu aplikacji; RegisterDialogClasses nie należy jednak eksportować. W poniższym przykładzie przedstawiono plik definicji modułu dla przykładowej aplikacji.

NAME    SSTEST.SCR 

DESCRIPTION 'SCRNSAVE : Test' 
 
STUB    'WINSTUB.EXE' 
EXETYPE WINDOWS 
 
CODE    MOVEABLE 
DATA    MOVEABLE MULTIPLE 
 
HEAPSIZE  1024 
STACKSIZE 4096 
 
EXPORTS 
        ScreenSaverProc 
        ScreenSaverConfigureDialog

Instalowanie nowych wygaszaczy ekranu

Podczas kompilowania listy dostępnych wygaszaczy ekranu Panel sterowania wyszukuje katalog startowy systemu Windows dla plików z rozszerzeniem scr. Ponieważ wygaszacze ekranu to standardowe pliki wykonywalne systemu Windows z rozszerzeniami .exe, należy je zmienić, aby miały rozszerzenia scr i skopiować je do odpowiedniego katalogu.

Dodawanie pomocy do okna dialogowego konfiguracji wygaszacza ekranu

Okno dialogowe konfiguracji wygaszacza ekranu zwykle zawiera przycisk Pomoc. Aplikacje wygaszacza ekranu mogą sprawdzać identyfikator przycisku Pomoc i wywoływać funkcję WinHelp w taki sam sposób, jak w innych aplikacjach opartych na systemie Windows.