TA STRONA UŻYWA COOKIE. Dowiedz się więcej o celu ich używania. Korzystając ze strony wyrażasz zgodę na używanie cookie, zgodnie z aktualnymi ustawieniami przeglądarki.

Od dnia 25.05.2018 r. na terenie Unii Europejskiej wchodzi w życie Rozporządzenie Parlamentu Europejskiego w sprawie ochrony danych osobowych. Prosimy o zapoznanie się z polityką prywatności oraz regulaminem serwisu [X]
Windows 7 Forum

Rozszerzenie efektu Aero Glass w oknie aplikacji (C# tutorial)

Offline Luke

  • ****
  • 423
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 okna
Niestety, .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. Projektowanie
Jesli 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. :P 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 Glass
Tam 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 Glass
Efekt 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.zip

Osobiś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ć. :P Być może kiedyś założę na to oddzielny temat.
« Ostatnia zmiana: 22 Maj 2010, 09:06:24 wysłana przez Luke »

Odp: Rozszerzenie efektu Aero Glass w oknie aplikacji (C# tutorial)
« Odpowiedź #1 dnia: 03 Styczeń 2011, 09:05:33 »
Jeśli chodzi o tekst na przyciskach i w labelach problem można rozwiązać za pomocą Application.SetCompatibleTextRenderingDefault(true);(należy zmienić z false na true w linijce w main).
« Ostatnia zmiana: 03 Styczeń 2011, 09:07:53 wysłana przez Johniak »

Offline Luke

  • ****
  • 423
Odp: Rozszerzenie efektu Aero Glass w oknie aplikacji (C# tutorial)
« Odpowiedź #2 dnia: 03 Styczeń 2011, 13:40:44 »
To jednak nie rozwiązuje problemu, a tylko go omija, bo powoduje jedynie usunięcie wygładzenia tekstu. ;) Z tego co się orientuję, to w WPF tekst na szkle działa dobrze, ale nie sprawdzałem tego.