Behandeln von Bildschirmschonern
Die Microsoft Win32-API unterstützt spezielle Anwendungen, die als Bildschirmschoner bezeichnet werden. Bildschirmschoner werden gestartet, wenn Maus und Tastatur für einen bestimmten Zeitraum im Leerlauf waren. Sie werden aus folgenden beiden Gründen verwendet:
- Zum Schutz eines Bildschirms vor Phosphorverbrennung durch statische Bilder.
- Zum Verbergen vertraulicher Informationen, die auf einem Bildschirm verbleiben.
Dieses Thema ist in die folgenden Abschnitte unterteilt.
Informationen zu Bildschirmschonern
Mit der Desktopanwendung im Windows-Systemsteuerung können Benutzer aus einer Liste von Bildschirmschonern auswählen, angeben, wie viel Zeit verstreichen soll, bevor der Bildschirmschoner gestartet wird, Bildschirmschoner konfigurieren und Bildschirmschoner in der Vorschau anzeigen. Bildschirmschoner werden automatisch geladen, wenn Windows gestartet wird oder wenn ein Benutzer den Bildschirmschoner über den Systemsteuerung aktiviert.
Sobald ein Bildschirmschoner ausgewählt ist, überwacht Windows Tastaturanschläge und Mausbewegungen und startet dann den Bildschirmschoner nach einer Zeit der Inaktivität. Windows startet den Bildschirmschoner jedoch nicht, wenn eine der folgenden Bedingungen vorhanden ist:
- Die aktive Anwendung ist keine Windows-basierte Anwendung.
- Ein CBT-Fenster (Computer-Based Training) ist vorhanden.
- Die aktive Anwendung empfängt die WM_SYSCOMMAND-Nachricht , wobei der wParam-Parameter auf den SC_SCREENSAVE-Wert festgelegt ist, aber sie übergibt die Nachricht nicht an die DefWindowProc-Funktion .
Sicherheitskontext des Bildschirmschoner
Der Sicherheitskontext des Bildschirmschoner hängt davon ab, ob ein Benutzer interaktiv angemeldet ist. Wenn ein Benutzer interaktiv angemeldet ist, wenn der Bildschirmschoner aufgerufen wird, wird der Bildschirmschoner im Sicherheitskontext des interaktiven Benutzers ausgeführt. Wenn kein Benutzer angemeldet ist, hängt der Sicherheitskontext des Bildschirmschoner von der verwendeten Windows-Version ab.
- Windows XP und Windows 2000 : Bildschirmschoner wird im Kontext von LocalSystem mit eingeschränkten Konten ausgeführt.
- Windows 2003 – Bildschirmschoner wird im Kontext von LocalService ausgeführt, wobei alle Berechtigungen entfernt und die Administratorgruppe deaktiviert ist.
- Gilt nicht für Windows NT4.
Der Sicherheitskontext bestimmt die Ebene der privilegierten Vorgänge, die über einen Bildschirmschoner ausgeführt werden können.
Windows Vista und höher: Wenn der Kennwortschutz durch eine Richtlinie aktiviert ist, wird der Bildschirmschoner unabhängig davon gestartet, was eine Anwendung mit der SC_SCREENSAVE Benachrichtigung ausführt.
Bildschirmschoner enthalten bestimmte exportierte Funktionen, Ressourcendefinitionen und Variablendeklarationen. Die Bildschirmschonerbibliothek enthält die Standard-Funktion und anderen Startcode, der für einen Bildschirmschoner erforderlich ist. Wenn ein Bildschirmschoner gestartet wird, erstellt der Startcode in der Bildschirmschonerbibliothek ein Vollbildfenster. Die Fensterklasse für dieses Fenster wird wie folgt deklariert:
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;
Um einen Bildschirmschoner zu erstellen, erstellen die meisten Entwickler ein Quellcodemodul mit drei erforderlichen Funktionen und verknüpfen sie mit der Bildschirmschonerbibliothek. Ein Bildschirmschonermodul ist nur für die Konfiguration selbst und für die Bereitstellung visueller Effekte verantwortlich.
Eine der drei erforderlichen Funktionen in einem Bildschirmschonermodul ist ScreenSaverProc. Diese Funktion verarbeitet bestimmte Nachrichten und übergibt alle nicht verarbeiteten Nachrichten zurück an die Bildschirmschonerbibliothek. Im Folgenden sind einige der typischen Nachrichten aufgeführt, die von ScreenSaverProc verarbeitet werden.
Nachricht | Bedeutung |
---|---|
WM_CREATE | Rufen Sie alle Initialisierungsdaten aus der Regedit.ini-Datei ab. Legen Sie einen Fenstertimer für das Bildschirmschonerfenster fest. Führen Sie alle anderen erforderlichen Initialisierungen aus. |
WM_ERASEBKGND | Löschen Sie das Bildschirmschonerfenster, und bereiten Sie sich auf nachfolgende Zeichnungsvorgänge vor. |
WM_TIMER | Führen Sie Zeichnungsvorgänge aus. |
WM_DESTROY | Zerstören Sie die Timer, die erstellt wurden, als die Anwendung die WM_CREATE Nachricht verarbeitet hat. Führen Sie alle zusätzlichen erforderlichen Bereinigungen aus. |
ScreenSaverProc übergibt nicht verarbeitete Nachrichten an die Bildschirmschonerbibliothek, indem die DefScreenSaverProc-Funktion aufgerufen wird . In der folgenden Tabelle wird beschrieben, wie diese Funktion verschiedene Nachrichten verarbeitet.
`Message` | Aktion |
---|---|
WM_SETCURSOR | Legen Sie den Cursor auf den NULL-Cursor fest, und entfernen Sie ihn vom Bildschirm. |
WM_PAINT | Zeichnen Sie den Bildschirmhintergrund. |
WM_LBUTTONDOWN | Beenden Sie den Bildschirmschoner. |
WM_MBUTTONDOWN | Beenden Sie den Bildschirmschoner. |
WM_RBUTTONDOWN | Beenden Sie den Bildschirmschoner. |
WM_KEYDOWN | Beenden Sie den Bildschirmschoner. |
WM_MOUSEMOVE | Beenden Sie den Bildschirmschoner. |
WM_ACTIVATE | Beenden Sie den Bildschirmschoner, wenn der wParam-Parameter auf FALSE festgelegt ist. |
Die zweite erforderliche Funktion in einem Bildschirmschonermodul ist ScreenSaverConfigureDialog. Diese Funktion zeigt ein Dialogfeld an, in dem der Benutzer den Bildschirmschoner konfigurieren kann (eine Anwendung muss eine entsprechende Dialogfeldvorlage bereitstellen). Windows zeigt das Konfigurationsdialogfeld an, wenn der Benutzer im Dialogfeld Bildschirmschoner des Systemsteuerung die Schaltfläche Setup auswählt.
Die dritte erforderliche Funktion in einem Bildschirmschonermodul ist RegisterDialogClasses. Diese Funktion muss von allen Bildschirmschoneranwendungen aufgerufen werden. Anwendungen, die keine speziellen Fenster oder benutzerdefinierten Steuerelemente im Konfigurationsdialogfeld erfordern, können jedoch einfach TRUE zurückgeben. Anwendungen, die spezielle Fenster oder benutzerdefinierte Steuerelemente erfordern, sollten diese Funktion verwenden, um die entsprechenden Fensterklassen zu registrieren.
Zusätzlich zum Erstellen eines Moduls, das die drei soeben beschriebenen Funktionen unterstützt, sollte ein Bildschirmschoner ein Symbol bereitstellen. Dieses Symbol ist nur sichtbar, wenn der Bildschirmschoner als eigenständige Anwendung ausgeführt wird. (Um vom Systemsteuerung ausgeführt zu werden, muss ein Bildschirmschoner über die Dateinamenerweiterung .scr verfügen. Damit er als eigenständige Anwendung ausgeführt werden kann, muss er über die .exe Dateinamenerweiterung verfügen.) Das Symbol muss in der Ressourcendatei des Bildschirmschoners durch die Konstante ID_APP identifiziert werden, die in der Headerdatei "Scrnsave.h" definiert ist.
Eine letzte Anforderung ist eine Bildschirmschonerbeschreibungszeichenfolge. Die Ressourcendatei für einen Bildschirmschoner muss eine Zeichenfolge enthalten, die vom Systemsteuerung als Bildschirmschonername angezeigt wird. Die Beschreibungszeichenfolge muss die erste Zeichenfolge in der Zeichenfolgentabelle der Ressourcendatei sein (identifiziert mit dem Ordnungswert 1). Die Beschreibungszeichenfolge wird jedoch vom Systemsteuerung ignoriert, wenn der Bildschirmschoner einen langen Dateinamen hat. In diesem Fall wird der Dateiname als Beschreibungszeichenfolge verwendet.
Verwenden der Bildschirmschonerfunktionen
In diesem Abschnitt wird beispielcode aus einer Bildschirmschoneranwendung verwendet, um die folgenden Aufgaben zu veranschaulichen:
- Erstellen eines Bildschirmschoner
- Installieren neuer Bildschirmschoner
- Hinzufügen von Hilfe zum Dialogfeld "Bildschirmschonerkonfiguration"
Erstellen eines Bildschirmschoner
In Intervallen von 1 bis 10 Sekunden streicht die Anwendung in diesem Beispiel den Bildschirm mit einer von vier Farben neu: Weiß, Hellgrau, Dunkelgrau und Schwarz. Die Anwendung zeichnet den Bildschirm jedes Mal, wenn sie eine WM_TIMER Nachricht empfängt. Der Benutzer kann das Intervall anpassen, in dem diese Nachricht gesendet wird, indem er das Konfigurationsdialogfeld der Anwendung auswählt und eine einzelne horizontale Bildlaufleiste anpasst.
Bildschirmschonerbibliothek
Die statischen Bildschirmschonerfunktionen sind in der Bildschirmschonerbibliothek enthalten. Es sind zwei Versionen der Bibliothek verfügbar: Scrnsave.lib und Scrnsavw.lib. Sie müssen Ihr Projekt mit einer dieser Elemente verknüpfen. Scrnsave.lib wird für Bildschirmschoner verwendet, die ANSI-Zeichen verwenden, und Scrnsavw.lib wird für Bildschirmschoner verwendet, die Unicode-Zeichen verwenden. Ein Bildschirmschoner, der mit Scrnsavw.lib verknüpft ist, wird nur auf Windows-Plattformen ausgeführt, die Unicode unterstützen, während ein mit Scrnsave.lib verknüpfter Bildschirmschoner auf jeder Windows-Plattform ausgeführt wird.
Unterstützung des Konfigurationsdialogfelds
Die meisten Bildschirmschoner bieten ein Konfigurationsdialogfeld, mit dem der Benutzer Anpassungsdaten wie eindeutige Farben, Zeichnungsgeschwindigkeiten, Linienstärken, Schriftarten usw. angeben kann. Um das Konfigurationsdialogfeld zu unterstützen, muss die Anwendung eine Dialogfeldvorlage bereitstellen und auch die ScreenSaverConfigureDialog-Funktion unterstützen. Im Folgenden ist die Dialogfeldvorlage für die Beispielanwendung aufgeführt.
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
Sie müssen die Konstante definieren, die zum Identifizieren der Dialogfeldvorlage verwendet wird, indem Sie den Dezimalwert 2003 verwenden, wie im folgenden Beispiel gezeigt:
#define DLG_SCRNSAVECONFIGURE 2003
Das folgende Beispiel zeigt die Funktion ScreenSaverConfigureDialog in der Beispielanwendung.
#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;
}
Neben der Bereitstellung der Dialogfeldvorlage und der Unterstützung der ScreenSaverConfigureDialog-Funktion muss eine Anwendung auch die Funktion RegisterDialogClasses unterstützen. Diese Funktion registriert alle nicht standardmäßigen Fensterklassen, die für den Bildschirmschoner erforderlich sind. Da die Beispielanwendung in ihrer Dialogfeldprozedur nur Standardfensterklassen verwendet hat, gibt diese Funktion einfach TRUE zurück, wie im folgenden Beispiel gezeigt:
BOOL WINAPI RegisterDialogClasses(hInst)
HANDLE hInst;
{
return TRUE;
}
Unterstützung der Bildschirmschonerfensterprozedur
Jeder Bildschirmschoner muss eine Fensterprozedur namens ScreenSaverProc unterstützen. Wie die meisten Fensterprozeduren verarbeitet ScreenSaverProc einen Satz bestimmter Nachrichten und übergibt alle unverarbeiteten Nachrichten an eine Standardprozedur. Anstatt sie jedoch an die DefWindowProc-Funktion zu übergeben, übergibt ScreenSaverProc nicht verarbeitete Nachrichten an die DefScreenSaverProc-Funktion . Ein weiterer Unterschied zwischen ScreenSaverProc und einer normalen Fensterprozedur besteht darin, dass das an ScreenSaverProc übergebene Handle den gesamten Desktop und nicht ein Clientfenster identifiziert. Das folgende Beispiel zeigt die ScreenSaverProc-Fensterprozedur für den Beispielbildschirmschoner.
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);
}
Erstellen einer Moduldefinitionsdatei
Die Funktionen ScreenSaverProc und ScreenSaverConfigureDialog müssen in der Moduldefinitionsdatei der Anwendung exportiert werden. RegisterDialogClasses sollte jedoch nicht exportiert werden. Das folgende Beispiel zeigt die Moduldefinitionsdatei für die Beispielanwendung.
NAME SSTEST.SCR
DESCRIPTION 'SCRNSAVE : Test'
STUB 'WINSTUB.EXE'
EXETYPE WINDOWS
CODE MOVEABLE
DATA MOVEABLE MULTIPLE
HEAPSIZE 1024
STACKSIZE 4096
EXPORTS
ScreenSaverProc
ScreenSaverConfigureDialog
Installieren neuer Bildschirmschoner
Beim Kompilieren der Liste der verfügbaren Bildschirmschoner durchsucht der Systemsteuerung das Windows-Startverzeichnis nach Dateien mit der Erweiterung .scr. Da Bildschirmschoner standardmäßig ausführbare Windows-Dateien mit .exe Erweiterungen sind, müssen Sie sie umbenennen, damit sie .scr-Erweiterungen haben und sie in das richtige Verzeichnis kopieren.
Hinzufügen von Hilfe zum Dialogfeld "Bildschirmschonerkonfiguration"
Das Konfigurationsdialogfeld für einen Bildschirmschoner enthält in der Regel eine Hilfeschaltfläche . Bildschirmschoneranwendungen können auf den Bezeichner der Schaltfläche Hilfe überprüfen und die WinHelp-Funktion auf die gleiche Weise aufrufen, wie Hilfe in anderen Windows-basierten Anwendungen bereitgestellt wird.