Tutorial ten napisałem na prośbę użytkownika
pionner, który chciał się dowiedzieć, jak uzyskać efekt Aero Glass w oknie aplikacji, jaki zastosowałem w programie
YouTube Downloader.
Mogłem mu odpisać na prywatną wiadomość, ale pomyślałem, że może ktoś jeszcze będzie chciał skorzystać z moich wskazówek, dlatego założyłem ten temat.
Rozszerzenie efektu Aero Glass w oknie aplikacji 1. Przygotowanie oknaNiestety, .net w Windows Form nie oferuje żadnych funkcji, które pozwoliłyby natychmiast uzyskać taki efekt, dlatego musimy samodzielnie zaimportować funkcje systemowe. Warto do tego celu utworzyć oddzielną klasę, żeby zachować porządek.
Na początku tworzymy projekt z szablonu
Windows Form Application. Dzięki temu od razu dostajemy okienko, na którym możemy zastosować efekt Aero Glass. Dodajmy klasę
WinApi, która posłuży nam do zaimportowania funkcji systemowych:
class WinApi
{
[DllImport("dwmapi.dll")]
internal static extern void DwmExtendFrameIntoClientArea(System.IntPtr hWnd, ref MARGINS pMargins);
[DllImport("dwmapi.dll")]
internal static extern void DwmIsCompositionEnabled(ref bool isEnabled);
[DllImport("user32.dll")]
public static extern bool ReleaseCapture();
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
internal struct MARGINS
{
public int Left, Right, Top, Bottom;
}
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
}
Wykorzystujemy w niej funkcję
DllImport, a więc musimy zadeklarować na początku przestrzeń nazw
System.Runtime.InteropServices, w której znajduje się ta funkcja:
using System.Runtime.InteropServices;
Zaimportowaliśmy następujące funkcje:
- DwmExtendFrameIntoClientArea - rozszerza efekt Aero Glass na okno programu
- DwmIsCompositionEnabled - sprawdza, czy kompozycja Aero jest włączona
- ReleaseCapture - dzięki niej będziemy mogli przesuwać okno klikając myszką w obszarze, gdzie jest efekt Aero Glass
- SendMessage - wysyła komunikat do okna, co jest podstawą funkcjonowania GUI w systmach Windows
A ktaże strukturę:
- MARGINS - potrzebna do ustalenia granic efektu Aero Glass
I stałe:
- WM_NCLBUTTONDOWN - numer komunikatu odpowiedzialnego za wciśnięcie klawisza myszki
- HT_CAPTION - numer parametru oznaczającego pasek tytułowy okna (czyli miejsce, które umożliwia nam przesuwanie okna)
Przejdźmy teraz do clasy
Form1 reprezentującej nasze okno. Dodamy w niej funkcję, która uruchomi efekt Aero Glass w naszym oknie. Nazwijmy ją
SetGlass:
private void SetGlass()
{
WinApi.MARGINS margins;
margins.Top = Padding.Top;
margins.Bottom = Padding.Bottom;
margins.Left = Padding.Left;
margins.Right = Padding.Right;
WinApi.DwmExtendFrameIntoClientArea(this.Handle, ref margins);
}
Wywołajmy ją w konstruktorze okna tuż po załadowaniu wszystkich kontrolek:
public Form1()
{
InitializeComponent();
SetGlass();
}
Na początku tworzymy obiekt struktury
MARGINS. Następnie ustalamy jej wartości. We wszystkich tutorialach, jakie widziałem, wartości te podawało się wprost przez liczbę. Uważam, że w ten sposób łatwo o pomyłkę, dlatego zalecam, aby w wartości marginesów wpisać po prostu wartości dopełnienia okna, czyli
Padding. Korzyści z takiego sposobu wyjdą nam w kolejnych krokach. W ostatniej linijce uruchamiamy funkcję
DwmExtendFrameIntoClientArea, która włącza nam Aero Glass w naszym oknie! Kod okna jest już gotowy, więc przejdźmy do projektowania.
2. ProjektowanieJesli uruchomimy program, to właściwie nie zauważymy żandych zmian. W sumie to dobrze, bo to oznacza, że nie popełniliśmy błędu i program wciąż się uruchamia.
Ustaliliśmy, że granice efektu Aero Glass zależą od parametru
Padding. Więc zmieńmy go. Ustalmy np.
Padding.Top na 32, a
Padding.Bottom na 64:
Jeśli teraz uruchomimy program, możemy poczuć się trochę zawiedzeni, ponieważ zamiast przezroczystego szkła zaobaczymy zwykłą biel. Dzieje się tak dlatego, że kolorem efektu Aero Glass jest czerń. Jedyne, co musimy zrobić, to zmienić kolor tła okna (
BackColor) na
Black:
Teraz oknieko będzie już miało efekt Aero Glass. Tyle, że tym razem wszędzie mamy czarne tło! Na szczęście szybko temu zaradzimy, przez zadokowanie panelu. W oknie
Toolbox znajdujemy
Panel i wstawiamy go w centrum okna. Następnie zmieniamy jego kolor tła (
BackColor) na
Control oraz ustawiamy dokowanie (
Dock) na
Fill. W końcu nasze okno wygląda jak należy:
Jak widać, dokowanie nie sprawia, że panel wypełnia całe okno, ale idealnie mieści się w granicach efektu Aero Glass. To dzięki temu, że granice efektu uzależniliśmy od parametru
Padding.
3. Chwytanie okna za obszar z efektem Aero GlassTam gdzie jest Aero Glass, tam po wcisnięciu lewego przycisku myszy powinniśmy mieć możliwość przesuwania okna. Jak się jednak okazuje, w naszym oknie to nie działa. Dlatego musimy jeszcze raz wrócić do kodu okna w klasie
Form1 i przeładować funkcję odpowiadającą za wciśnięcie przycisku myszy w obszarze naszego okna. W funkcji tej nakażemy systemowi, aby przesuwał okno, gdy klikniemy w obszarze Aero Glass. Do klasy
Form1 dodajmy następujący kod:
protected override void OnMouseDown(MouseEventArgs e)
{
WinApi.ReleaseCapture();
WinApi.SendMessage(this.Handle, WinApi.WM_NCLBUTTONDOWN, WinApi.HT_CAPTION, 0);
base.OnMouseDown(e);
}
Od tej pory możemy przesuwać okno chwytając je za dowolny obszar z efektem Aero Glass.
4. Rysowanie na Aero GlassEfekt Aero Glass wygląda wspaniale, ale w tym obszarze wcale nie musi być tak pusto. Przeładowując metodę
OnPaint możemy bez problemu na nim rysować. Teoretycznie w tym obszarze możemy też wstawiać kontrolki systemowe, czyli przyciski, etykiety, pola tekstowe, ale niestety ich tekst jest źle wyświetlany. Jeszcze nie znalazłem dobrego sposobu w C# na poprawienie tego błędu. Ale możemy wstawić np. przycisk, który zamiast tekstu ma jakiś obrazek. Bez problemu też działają nasze własne kontrolki, jeśli takie stworzymy. Oto przykład takiego fikuśnego okienka:
Zastosowałem w nim takie kontrolki:
- Button - czyli te dwa przyciski
- PictureBox - ten obrazek
- UpDownButton - moja własna kontrolka, choć wzorowana na systemowej
Projekt ten możona pobrać tutaj:
GlassTutorial.zipOsobiście mam swoje własne sposoby na rysowanie ładnie wygładzonego tekstu na szkle oraz wyświetlanie tekstu z jasną poświatą, jak w tytule okna, ale nie będę tego teraz tutaj wyjaśniał, bo znów musiałbym się rozpisać.
Być może kiedyś założę na to oddzielny temat.