Hantera skärmsläckare
Microsoft Win32 API stöder särskilda program som kallas skärmsläckare. Skärmsläckare startar när musen och tangentbordet har varit inaktiva under en angiven tidsperiod. De används av följande två skäl:
- För att skydda en skärm mot fosforbränna som orsakas av statiska bilder.
- För att dölja känslig information som finns kvar på en skärm.
Det här avsnittet är indelat i följande avsnitt.
Om skärmsläckare
Med skrivbordsprogrammet på Windows-kontrollpanelen kan användarna välja från en lista över skärmsläckare, ange hur lång tid som ska gå innan skärmsläckaren startar, konfigurera skärmsläckare och förhandsgranska skärmsläckare. Skärmsläckare läses in automatiskt när Windows startar eller när en användare aktiverar skärmsläckaren via Kontrollpanelen.
När en skärmsläckare har valts övervakar Windows tangenttryckningar och musrörelser och startar sedan skärmsläckaren efter en period av inaktivitet. Windows startar dock inte skärmsläckaren om något av följande villkor finns:
- Det aktiva programmet är inte ett Windows-baserat program.
- Ett datorbaserat utbildningsfönster (CBT) finns.
- Det aktiva programmet tar emot WM_SYSCOMMAND-meddelandet med parametern wParam inställd på värdet SC_SCREENSAVE, men meddelandet skickas inte till funktionen DefWindowProc.
Säkerhetskontext för skärmsläckaren
Skärmsläckarens säkerhetskontext beror på om en användare är interaktivt inloggad. Om en användare är interaktivt inloggad när skärmsläckaren anropas körs skärmsläckaren i säkerhetskontexten för den interaktiva användaren. Om ingen användare är inloggad beror skärmsläckarens säkerhetskontext på vilken version av Windows som används.
- Windows XP och Windows 2000 – skärmsläckaren körs i samband med LocalSystem med konton som är begränsade.
- Windows 2003 – skärmsläckaren körs i kontexten LocalService med alla privilegier borttagna och administratörsgruppen inaktiverad.
- Gäller inte för Windows NT4.
Säkerhetskontexten avgör vilken nivå av privilegierade åtgärder som kan utföras från en skärmsläckare.
Windows Vista och senare: Om lösenordsskydd är aktiverat av principen startas skärmsläckaren oavsett vad ett program gör med SC_SCREENSAVE-meddelandet.
Skärmsläckare innehåller specifika exporterade funktioner, resursdefinitioner och variabeldeklarationer. Skärmsläckarbiblioteket innehåller den huvudfunktionen och annan startkod som krävs för en skärmsläckare. När en skärmsläckare startar skapar startkoden i skärmsläckarbiblioteket ett helskärmsfönster. Fönsterklassen för det här fönstret deklareras på följande sätt:
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;
För att skapa en skärmsläckare skapar de flesta utvecklare en källkodsmodul som innehåller tre nödvändiga funktioner och länkar dem till skärmsläckarbiblioteket. En skärmsläckarmodul ansvarar bara för att konfigurera sig själv och för att tillhandahålla visuella effekter.
En av de tre nödvändiga funktionerna i en skärmsläckarmodul är ScreenSaverProc. Den här funktionen bearbetar specifika meddelanden och skickar alla obearbetade meddelanden tillbaka till skärmsläckarbiblioteket. Följande är några av de vanliga meddelanden som bearbetas av ScreenSaverProc.
Meddelande | Betydelse |
---|---|
WM_CREATE | Hämta initieringsdata från Regedit.ini-filen. Ange en fönstertimer för skärmsläckarfönstret. Utför alla andra nödvändiga initieringar. |
WM_ERASEBKGND | Radera skärmsläckarfönstret och förbered dig för efterföljande ritningsåtgärder. |
WM_TIMER | Utför ritningsåtgärder. |
WM_DESTROY | Förstör de timers som skapades när programmet bearbetade WM_CREATE-meddelandet. Utför eventuell ytterligare nödvändig rensning. |
ScreenSaverProc skickar obearbetade meddelanden till skärmsläckarbiblioteket genom att anropa funktionen DefScreenSaverProc. I följande tabell beskrivs hur den här funktionen bearbetar olika meddelanden.
Meddelande | Åtgärd |
---|---|
WM_SETCURSOR | Ställ in markören på null-markören och ta bort den från skärmen. |
WM_PAINT | Måla skärmbakgrunden. |
WM_LBUTTONDOWN | Avsluta skärmsläckaren. |
WM_MBUTTONDOWN | Avsluta skärmsläckaren. |
WM_RBUTTONDOWN | Avsluta skärmsläckaren. |
WM_KEYDOWN | Avsluta skärmsläckaren. |
WM_MOUSEMOVE | Avsluta skärmsläckaren. |
WM_ACTIVATE | Avsluta skärmsläckaren om parametern wParam är inställd på FALSE. |
Den andra nödvändiga funktionen i en skärmsläckarmodul är ScreenSaverConfigureDialog. Den här funktionen visar en dialogruta som gör att användaren kan konfigurera skärmsläckaren (ett program måste tillhandahålla en motsvarande dialogrutemall). Windows visar konfigurationsdialogrutan när användaren väljer knappen Konfigurera i dialogrutan Skärmsläckare i Kontrollpanelen.
Den tredje nödvändiga funktionen i en skärmsläckarmodul är RegisterDialogClasses. Den här funktionen måste anropas av alla skärmsläckarprogram. Program som inte kräver särskilda fönster eller anpassade kontroller i konfigurationsdialogrutan kan dock bara returnera TRUE-. Program som kräver särskilda fönster eller anpassade kontroller bör använda den här funktionen för att registrera motsvarande fönsterklasser.
Förutom att skapa en modul som stöder de tre funktionerna som precis beskrivits bör en skärmsläckare ange en ikon. Den här ikonen visas bara när skärmsläckaren körs som ett fristående program. (För att kunna köras av Kontrollpanelen måste en skärmsläckare ha filnamnstillägget .scr. För att kunna köras som ett fristående program måste det ha filnamnstillägget .exe.) Ikonen måste identifieras i skärmsläckarens resursfil av konstanten ID_APP, som definieras i huvudfilen Scrnsave.h.
Ett sista krav är en beskrivningssträng för skärmsläckaren. Resursfilen för en skärmsläckare måste innehålla en sträng som kontrollpanelen visar som skärmsläckarnamn. Beskrivningssträngen måste vara den första strängen i resursfilens strängtabell (identifieras med ordningstalet 1). Beskrivningssträngen ignoreras dock av Kontrollpanelen om skärmsläckaren har ett långt filnamn. I sådana fall används filnamnet som beskrivningssträng.
Använda skärmsläckarfunktioner
I det här avsnittet används exempelkod som hämtats från ett skärmsläckarprogram för att illustrera följande uppgifter:
- Skapa en skärmsläckare
- Installera nya skärmsläckare
- Lägga till hjälp i Skärmsläckarens konfigurationsdialog
Skapa en skärmsläckare
Med intervall mellan 1 och 10 sekunder ommålar programmet i det här exemplet skärmen med en av fyra färger: vit, ljusgrå, mörkgrå och svart. Programmet målar skärmen varje gång det tar emot ett WM_TIMER meddelande. Användaren kan justera det intervall med vilket det här meddelandet skickas genom att välja programmets konfigurationsdialogruta och justera en enda vågrät rullningslist.
Skärmsläckarbibliotek
Funktionerna för statisk skärmsläckare finns i skärmsläckarbiblioteket. Det finns två versioner av biblioteket, Scrnsave.lib och Scrnsavw.lib. Du måste länka projektet till något av dessa. Scrnsave.lib används för skärmsläckare som använder ANSI-tecken, och Scrnsavw.lib används för skärmsläckare som använder Unicode-tecken. En skärmsläckare som är länkad till Scrnsavw.lib körs endast på Windows-plattformar som stöder Unicode, medan en skärmsläckare som är länkad med Scrnsave.lib körs på alla Windows-plattformar.
Stöd för konfigurationsdialogrutan
De flesta skärmsläckare innehåller en konfigurationsdialogruta där användaren kan ange anpassningsdata, till exempel unika färger, ritningshastigheter, linjetjocklek, teckensnitt och så vidare. För att stödja konfigurationsdialogrutan måste programmet tillhandahålla en dialogrutemall och måste även ha stöd för funktionen ScreenSaverConfigureDialog. Följande är dialogrutemallen för exempelprogrammet.
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
Du måste definiera den konstant som används för att identifiera dialogrutemallen med hjälp av decimalvärdet 2003, som i följande exempel:
#define DLG_SCRNSAVECONFIGURE 2003
I följande exempel visas funktionen ScreenSaverConfigureDialog som finns i exempelprogrammet.
#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;
}
Förutom att tillhandahålla dialogrutemallen och stödja funktionen ScreenSaverConfigureDialog måste ett program också ha stöd för funktionen RegisterDialogClasses. Den här funktionen registrerar alla icke-standardfönsterklasser som krävs av skärmsläckaren. Eftersom exempelprogrammet endast använde standardfönsterklasser i dialogrutan returnerar den här funktionen helt enkelt TRUE-, som i följande exempel:
BOOL WINAPI RegisterDialogClasses(hInst)
HANDLE hInst;
{
return TRUE;
}
Stöd för skärmsläckarfönsterproceduren
Varje skärmsläckare måste ha stöd för en fönsterprocedur med namnet ScreenSaverProc. Precis som de flesta fönsterprocedurer bearbetar ScreenSaverProc en uppsättning specifika meddelanden och skickar alla obearbetade meddelanden till en standardprocedur. Men i stället för att skicka dem till funktionen DefWindowProc skickar ScreenSaverProc obearbetade meddelanden till funktionen DefScreenSaverProc. En annan skillnad mellan ScreenSaverProc och en normal fönsterprocedur är att handtaget som skickas till ScreenSaverProc identifierar hela skrivbordet i stället för ett klientfönster. I följande exempel visas ScreenSaverProc proceduren för fönsterhantering för exemplet med skärmsläckare.
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);
}
Skapa en moduldefinitionsfil
Funktionerna ScreenSaverProc och ScreenSaverConfigureDialog måste exporteras i programmets moduldefinitionsfil. RegisterDialogClasses bör dock inte exporteras. I följande exempel visas moduldefinitionsfilen för exempelprogrammet.
NAME SSTEST.SCR
DESCRIPTION 'SCRNSAVE : Test'
STUB 'WINSTUB.EXE'
EXETYPE WINDOWS
CODE MOVEABLE
DATA MOVEABLE MULTIPLE
HEAPSIZE 1024
STACKSIZE 4096
EXPORTS
ScreenSaverProc
ScreenSaverConfigureDialog
Installera nya skärmsläckare
När du kompilerar listan över tillgängliga skärmsläckare söker Kontrollpanelen i Windows Startup-katalogen efter filer med tillägget .scr. Eftersom skärmsläckare är standard körbara Windows-filer med .exe tillägg måste du byta namn på dem så att de har .scr-tillägg och kopierar dem till rätt katalog.
Lägga till hjälp i dialogrutan för konfiguration av skärmsläckare
Konfigurationsdialogrutan för en skärmsläckare innehåller vanligtvis knappen Hjälp. Skärmsläckarprogram kan söka efter hjälpknappsidentifieraren och anropa funktionen WinHelp på samma sätt som Hjälp tillhandahålls i andra Windows-baserade program.