Implementacja wygaszacza ekranu jest czynnością prostą. Trzeba jednak pamiętać o kilku ważnych zasadach by wygaszacz działał prawidłowo. Należy też tak go napisać, by obsługiwał okienko podglądu (właściwości ekranu). W artykule opiszę jak samemu w C# stworzyć własny wygaszacz i jako można go rozbudować.
Wygaszacz ekranu implementujemy jak zwykły plik exe. Jednak system Windows oczekuje by rozszerzenie pliku miało postać scr. Stąd, przed jego instalacją wystarczy więc zmienić rozszerzenie. Instalacja polega na wkopiowaniu wygaszacza (plik *.scr) do katalogu \windows\system32.
W zależności od parametrów uruchamiania naszego wygaszacza, przyjmuje on różne tryby pracy, i tak:
/s – normalne uruchomienie wygaszacza,
/c – konfiguracja wygaszacza
/p – okienko podglądu. W tym wypadku przezywane są dwa parametry, drugi to uchwyt do okienka podglądu.
Tworząc projekt w VS 2008 powstaje plik program.cs z metodą statyczną void Main(). Aby odczytać parametry przekazywane do aplikacji dokonam modyfikacji tej metody i odczytam argumenty w niej przekazane do tablicy args:
static void Main(string[] args)
Teraz, w zależności od przekazanych parametrów, metoda Main uruchamia formę z konfiguracją lub formę z wygaszaczem ekranu. Metoda MainForm jest przeciążona, inaczej wygląda jej wywołanie gdy prezentowane jest okienko podglądu. W wypadku opcji podglądu, przekazywany jest uchwyt do okna reprezentującego podgląd we właściwościach ekranu.
Wygaszacz – animacja
Wygaszacz pracując w normalnym trybie pracy ustawia pewne parametry początkowe dla formy, są to:
- WindowState – forma zmaksymalizowana,
- TopMost – forma zawsze na górze.
Metoda MainForm, dla normalnego trybu pracy ma postać:
public MainForm() { InitializeComponent(); this.WindowState = FormWindowState.Maximized; this.TopMost = true; timer1.Enabled = true; Cursor.Hide(); }
Okienko podglądu
Uruchamiając okienko podglądu wywoływana jest przeciążona metoda MainForm. Jak wspomniałem na wstępie, razem z parametrem /p przekazywany jest uchwyt do okienka podglądu. Argumentem przeciążonej metody jest właśnie uchwyt, jeszcze w formie stringa. Ale zaraz przekonwertujemy go na IntPtr i zapiszemy w zmiennej previewHwnd.

Następnie ustawiamy rodzica naszej formy na okienko podglądu wygaszacza. W tym wypadku wykorzystamy funkcję WinApi SetParent.
Kolejnym krokiem jest ustawienie MainForm jako formy child. Dzięki temu, przełączając wybór pomiędzy wygaszaczami nastąpi zakończenie pracy naszego wygaszacza. W tym wypadku posłużę się funkcją SetWindowLong praz GetWindowLong. Cały kod prezentuje się tak:
public MainForm(string hwnd)
{
InitializeComponent();
previewHwnd = new IntPtr(long.Parse(hwnd));
SetParent(this.Handle, previewHwnd);
SetWindowLong(this.Handle, -16,
new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000));
timer1.Enabled = true;
this.WindowState = FormWindowState.Maximized;
this.Width = 110;
this.Height = 60;
}
Funkcje WinApi
Funkcje WinApi zostały zaimportowane dyrektywą DllImport. Należy pamiętać, by DllImport zadziałał, do projektu należy dołączyć przestrzeń nazw:
using System.Runtime.InteropServices;
Wtedy piszemy (deklaracja odbywa się tu po definicji klasy):
[DllImport("user32.dll")] static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); [DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
Po zaimportowaniu funkcje są juz dostępne w naszej aplikacji.
Animacja
Cała animacja wygaszacza oparta jest o obiekt Timer. Co krok zegara następuje narysowanie okręgu o losowym rozmiarze, pozycji i kolorze.
Zwrócę uwagę na obiekt Graphics. Jest on tworzony z uchwytu MainForm:
Graphics.FromHwnd(this.Handle);
Przypomnę, że przeciążona metoda MainForm(string hwnd) ustawia rodzica formy na okno podglądu wygaszacza. Więc nie musimy tworzyć osobnej animacji wyświetlanej w podglądzie.
Wyłączenie wygaszacza
Wygaszacz wyłączany jest po wykryciu ruchu myszki (zdarzenie mousemove) lub naciśnięciu klawisza (keypress).
W przypadku poruszenia myszką sprawdzam, czy nastąpił ruch kursora (minimum 10 pixeli). Zdarzenie mouseMove jest czasami wywoływane chociaż nie nastąpił ruch kursora. Zdaje się, że wynika to z faktu, że Windows wysyła komunikat wm_MouseMove.
Konfiguracja
Okienko konfiguracji pozwala na ustawienie interwału czasowego, po którym prezentowane są koleje okręgi.

Forma konfiguracji zapisuje dane w rejestrze systemu. W tym celu utworzyłem klasę Rejestr, która odpowiedzialna jest za zapis i odczycz wartości kluczy. Klasa znajduje się w pliku Rejestr.cs i zapisuje dane w kluczu HKEY_LOCAL_MACHINE\SOFTWARE\Leniwce.com\ScreenSaver.
Podsumowanie
Efekt wizualny jest bardzo prosty. By wygaszacz nabrał rumieńców i był efektowny można wykorzystać DirectX lub OpenGL. O OpenGL zamieściłem post wcześniej: Animacje 3D (OpenGL).
Kod źródłowy wraz z binariami wygaszacza można pobrać z naszego serwisu (55 KB).
|
|