Behandeln von Bildschirmschonern
Die Microsoft Win32-API unterstützt spezielle Anwendungen, die als Bildschirmschoner bezeichnet werden. Bildschirmschoner werden gestartet, wenn sich Maus und Tastatur für einen bestimmten Zeitraum im Leerlauf befinden. Sie werden aus den folgenden beiden Gründen verwendet:
- Zum Schutz eines Bildschirms vor einem durch statische Bilder verursachten Glühen.
- Um vertrauliche Informationen zu verbergen, die auf einem Bildschirm übrig bleiben.
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 bis zum Start des Bildschirmschoners verstreichen soll, bildschirmschoner konfigurieren und Bildschirmschoner in der Vorschau anzeigen. Bildschirmschoner werden automatisch geladen, wenn Windows gestartet wird oder wenn ein Benutzer den Bildschirmschoner über die Systemsteuerung.
Nachdem ein Bildschirmschoner ausgewählt wurde, Windows Tastatureingaben und Mausbewegungen und startet den Bildschirmschoner nach einer Bestimmten Zeit der Inaktivität. Allerdings wird Windows bildschirmschoner nicht gestartet, wenn eine der folgenden Bedingungen erfüllt ist:
- Die aktive Anwendung ist keine Windows-basierte Anwendung.
- Ein Fenster für computerbasiertes Training (CBT) ist vorhanden.
- Die aktive Anwendung empfängt die WM _ SYSCOMMAND-Nachricht mit dem wParam-Parameter, der auf den SC SCREENSAVE-Wert festgelegt ist, übergibt die Nachricht jedoch nicht an die _ DefWindowProc-Funktion.
Sicherheitskontext des Bildschirmschoners
Der Sicherheitskontext des Bildschirmschoners hängt davon ab, ob ein Benutzer interaktiv angemeldet ist. Wenn ein Benutzer interaktiv angemeldet wird, 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 Bildschirmschoners von der verwendeten Windows ab.
- Windows XP und Windows 2000 – Der Bildschirmschoner wird im Kontext von LocalSystem mit eingeschränkten Konten ausgeführt.
- Windows 2003 : Der Bildschirmschoner wird im Kontext von LocalService ausgeführt, und alle Berechtigungen wurden entfernt, und die Administratorengruppe wurde deaktiviert.
- 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 die Richtlinie aktiviert ist, wird der Bildschirmschoner unabhängig davon gestartet, was eine Anwendung mit der SC _ SCREENSAVE-Benachrichtigung macht.
Bildschirmschoner enthalten bestimmte exportierte Funktionen, Ressourcendefinitionen und Variablendeklarationen. Die Bildschirmschonerbibliothek enthält die Hauptfunktion 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;
Zum Erstellen eines Bildschirmschoners erstellen die meisten Entwickler ein Quellcodemodul, das drei erforderliche Funktionen enthält, und verknüpfen sie mit der Bildschirmschonerbibliothek. Ein Bildschirmschonermodul ist nur für die Konfiguration selbst und 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 finden Sie einige der typischen Nachrichten, die von ScreenSaverProc verarbeitet werden.
| Nachricht | Bedeutung |
|---|---|
| WM _ CREATE | Rufen Sie alle Initialisierungsdaten aus der Regedit.ini ab. Legen Sie einen Fensterzeiter für das Fenster des Bildschirmschoners fest. Führen Sie alle anderen erforderlichen Initialisierungen aus. |
| WM _ ERASEBKGND | Löschen Sie das Fenster des Bildschirmschoners, und bereiten Sie sich auf nachfolgende Zeichnungsvorgänge vor. |
| WM _ TIMER | Ausführen von Zeichnungsvorgängen. |
| 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 durch. |
ScreenSaverProc übergibt nicht verarbeitete Nachrichten durch Aufrufen der DefScreenSaverProc-Funktion an die Bildschirmschonerbibliothek. 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 | Paint des Bildschirmhintergrunds. |
| 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 wird das Konfigurationsdialogfeld angezeigt, wenn der Benutzer die Schaltfläche Setup im Dialogfeld Systemsteuerung Bildschirmschoner des Benutzers 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 benötigen, 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 oben beschriebenen Funktionen unterstützt, sollte ein Bildschirmschoner ein Symbol zur Verfügung stehen. 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 die Dateierweiterung .scr haben. Um als eigenständige Anwendung ausgeführt zu werden, muss er über die .exe-Dateierweiterung 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 Beschreibungszeichenfolge für den Bildschirmschoner. Die Ressourcendatei für einen Bildschirmschoner muss eine Zeichenfolge enthalten, Systemsteuerung als Name des Bildschirmschoners angezeigt wird. Die Beschreibungszeichenfolge muss die erste Zeichenfolge in der Zeichenfolgentabelle der Ressourcendatei sein (identifiziert mit dem Ordinalwert 1). Die Beschreibungszeichenfolge wird jedoch vom -Code ignoriert Systemsteuerung wenn der Bildschirmschoner über einen langen Dateinamen verfügt. 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 Bildschirmschoners
- Installieren neuer Bildschirmschoner
- Hinzufügen von Hilfe zum Dialogfeld "Bildschirmschonerkonfiguration"
Erstellen eines Bildschirmschoners
In Intervallen zwischen 1 und 10 Sekunden zeigt die Anwendung in diesem Beispiel den Bildschirm mit einer von vier Farben neu an: 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 und eine einzelne horizontale Scrollleiste anwählt.
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 Verknüpfungen verknüpfen. "Scrnsave.lib" wird für Bildschirmschoner verwendet, die ANSI-Zeichen verwenden, und "Scrnsavw.lib" für Bildschirmschoner, die Unicode-Zeichen verwenden. Ein mit "Scrnsavw.lib" verknüpfter Bildschirmschoner 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ützen des Konfigurationsdialogfelds
Die meisten Bildschirmschoner bieten ein Konfigurationsdialogfeld, in dem der Benutzer Anpassungsdaten wie eindeutige Farben, Zeichnungsgeschwindigkeiten, Linienstärke, Schriftarten und so weiter angeben kann. Um das Konfigurationsdialogfeld zu unterstützen, muss die Anwendung eine Dialogfeldvorlage bereitstellen und auch die ScreenSaverConfigureDialog-Funktion unterstützen. Im Folgenden finden Sie die Dialogfeldvorlage für die Beispielanwendung.
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:
#define DLG_SCRNSAVECONFIGURE 2003
Das folgende Beispiel zeigt die ScreenSaverConfigureDialog-Funktion 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 RegisterDialogClasses-Funktion unterstützen. Diese Funktion registriert alle nicht standardmäßigen Fensterklassen, die vom Bildschirmschoner benötigt werden. Da die Beispielanwendung in ihrer Dialogfeldprozedur nur Standardfensterklassen verwendet hat, gibt diese Funktion einfach TRUE zurück, wie im folgenden Beispiel:
BOOL WINAPI RegisterDialogClasses(hInst)
HANDLE hInst;
{
return TRUE;
}
Unterstützen der Bildschirmschonerfensterprozedur
Jeder Bildschirmschoner muss eine Fensterprozedur mit dem Namen ScreenSaverProc unterstützen. Wie die meisten Fensterprozeduren verarbeitet ScreenSaverProc einen Satz bestimmter Nachrichten und übergibt alle nicht verarbeiteten 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 ist, dass das an ScreenSaverProc übergebene Handle den gesamten Desktop anstelle eines Clientfensters 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 die 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 Es sich bei Bildschirmschonern Windows ausführbaren Dateien mit .exe-Erweiterungen handelt, müssen Sie sie umbenennen, damit sie über ERWEITERUNGEN VERFÜGEN, 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 Schaltfläche Hilfe. Bildschirmschoneranwendungen können auf den Bezeichner der Hilfeschaltfläche überprüfen und die WinHelp-Funktion auf die gleiche Weise aufrufen, wie Hilfe in anderen Windows-basierten Anwendungen bereitgestellt wird.