Průhledné okno s Aero Glass efektem v C# .NET WPF - Část 1
Tentokrát to bude trochu "vyšší dívčí", pokusíme se "nahackovat" do systémových prostředků operačního systému Windows 10. Všichni jistě dobře znáte Aero Glass design oken, které představil Microsoft s příchodem Windows Vista, aby jej zařízl s novými Windows 8/10. Podporu oficiálně odstranil jak z vývojářských nástrojů (myslím, že od verze .NET Framework 3.5 nelze volat DWM pro WinForms, které rozmazané pozadí formuláře běžně užívaly). Nicméně ze mě neznámých důvodů stále existuje nezdokumentované API, které toto umožňuje pod Windows 10. My se k němu dnes dostaneme a uděláme si hezký průhledný formulář s efektem rozmazání, který můžeme využít tak jako například já v mé aplikaci: Počasí na desktopu – volně šiřitelná verze zde:

Co budeme potřebovat
- Visual Studio 2017 či 2019 (v této verzi budu vytvářet průvodce, změny oproti verzi 2017 by měly být jen kosmetické)
- Znalost jazyka C# a Visual Studia
- Pokročilejší orientaci v OOP
- Windows 10
Co se dnes naučíme
- Práci s knihovnami a prostředky operačního systému
- Nastavení formuláře WPF
- Práce s API operačního systému
- Práce s
Brush
barvami, míchání a převod barev
Založení nového projektu
Vytvořme nový projekt typu Aplikace WPF (.NET Framework). V případě UWP tento postup bohužel nebude fungovat, vzhledem k představenému "Fluent design" u Windows 10 jsou průhledné formuláře řízeny striktně OS. Při ztrátě aktivity okna (když klikneme např. na plochu mimo formulář) se rozmazání vždy vypne a přepne se do neprůhledné barvy, což není vždy to, co potřebujeme.

Design aplikace
Zde si vystačíme jen s oknem s upravenými parametry, jedním prvkem
<Slider>
a pěti prvky <TextBlock>
pro
jednoduché nastavení a zobrazení kódu užité barvy na formuláři.
Nastavení formuláře Window
Je nicméně potřeba dodržet několik pravidel a doporučení:
- Je třeba nastavit parametr
AllowsTransparency="True"
, neboli povolit průhlednost formuláře. Díky tomu můžeme volně nastavovat průhlednost pomocíBrush
barvy nebo hodnotyOpacity
. - S prvním nastavením se váže podmínka kompilátoru, která neumožňuje,
aby bylo možné při
AllowsTransparency="True"
mít styl zobrazeného okna jakýkoliv jiný nežWindowStyle="None"
. Ten je tedy nutné nastavit, pokud to neprovede Visual Studio automaticky za nás (to je velmi pravděpodobné).WindowStyle
říká OS, jaké ovládací prvky budou na oknu vykreslené. V našem případě to logicky nebudou žádné, krom absence klasické lišty s názvem aplikace a obligátních třech tlačítek v pravém rohu narazíme na jiné problémy s tím spojené:- Pokud si budete chtít takovýto formulář někam posunout, tak neuspějete, protože jej není za co "chytit". Níže ukáži jak toto omezení elegantně a jedním řádkem kódu v Code behind obejít.
- To samé platí pro změnu rozměru stávajícího okna, na což ale již
bylo pamatováno, a vyřešíme to rovnou v XAML parametrem
ResizeMode="CanResizeWithGrip"
. Tímto parametrem se v pravém dolním rohu formuláře vykreslí tři čárky, za které klikem myši chytíme a formuláři můžeme libovolně upravovat rozměry. Decentní, rychlé a elegantní.
- Dále můžeme nastavit
BorderThickness="2"
aBorderBrush="Black"
, což zobrazí oknu okraje široké 2px v černé barvě. Jde ale čistě o estetický detail tak, aby se okraj okna jasně oddělil od pozadí formuláře. - Pro rychlé otestování, zda máme správně zapnutou transparency,
můžeme nastavit rovnou barvu
Background="#7FFFFFFF"
. To znamená bílou barvu s 50 % průhledností.
Další prvky na formuláři
Na formulář postupně vložíme:
<Grid>
- rozdělený přibližně na třetiny<Slider>
– s rozsahem0
-255
, který nesmí být překročen.<ViewBox>
– roztáhne obsaženýTextBlock
tak aby byl stále ve stejným poměru ku velikosti formuláře<TextBlock>
– obyčejnýTextBlock
, který bude vypisovat aktuální barvu v HTML kódu
Kód XAML bude následující:
<Window x:Name="Okno" x:Class="BluredFormNETF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:BluredFormNETF" mc:Ignorable="d" MouseLeftButtonDown="Window_MouseLeftButtonDown" Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded" AllowsTransparency="True" WindowStyle="None" ResizeMode="CanResizeWithGrip" BorderThickness="2" BorderBrush="Black" Background="#7FFFFFFF"> <Grid > <Grid.RowDefinitions> <RowDefinition Height="1*"/> <RowDefinition Height="1*"/> <RowDefinition Height="1*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="1*"/> </Grid.ColumnDefinitions> <Slider Grid.Row="0" Grid.Column="0" ValueChanged="Slider_ValueChanged" Maximum="255" SmallChange="1" TickFrequency="10" TickPlacement="BottomRight" Background="#7F2F1E47" Value="125" Grid.ColumnSpan="3" Grid.RowSpan="3"/> <Grid Grid.Row="1" Grid.Column="1"> <Grid.RowDefinitions> <RowDefinition Height="1*"/> <RowDefinition Height="0.4*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.4*"/> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="1*"/> </Grid.ColumnDefinitions> <Viewbox Stretch="Uniform" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="5" VerticalAlignment="Bottom"> <TextBlock Name="barva" Text="{Binding Value, ElementName=SliderValueText}" Foreground="White" FontFamily="Consolas"/> </Viewbox> <Viewbox Stretch="Uniform" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top"> <TextBlock Text="ALPHA" Foreground="White"/> </Viewbox> <Viewbox Stretch="Uniform" Grid.Row="1" Grid.Column="2" VerticalAlignment="Top"> <TextBlock Text=" RED " Foreground="Red"/> </Viewbox> <Viewbox Stretch="Uniform" Grid.Row="1" Grid.Column="3" VerticalAlignment="Top"> <TextBlock Text="GREEN" Foreground="Green"/> </Viewbox> <Viewbox Stretch="Uniform" Grid.Row="1" Grid.Column="4" VerticalAlignment="Top"> <TextBlock Text=" BLUE " Foreground="Blue" /> </Viewbox> </Grid> </Grid> </Window>
Výsledek by měl vypadat nějak takto:

Brush – Jak funguje jednoduché mixování barev
Než se vrhneme na Code behind a to na co netrpělivě čekáte, tak si v
rychlosti povíme něco o třídě Brush
. Přesněji jak pracuje s
barvami a jak jednoduše toho využít pro náš projekt. Ve WPF i UWP se již
nepoužívá původní jednoduchá třída Colors
, která prakticky
umožňovala pouze omezenou práci s moderními efekty a proto byla nahrazena
podstatně modernější a flexibilnější třídou Brushes
. Ta se
používá kdekoliv, kde je třeba říci kompilátoru jakou má mít něco
barvu. Netřeba panikařit, z Colors
si tato třída ponechala
jednoduché názvosloví nejpoužívanějších barev, a doplnila je o další
efekty jako přechody apod.
Nás pro naši aplikaci bude zajímat jen jak si obyčejně namíchat vlastní barvu pomocí základních barev RGB s doplňkovou hodnotou ALPHA kanálu - neboli hodnotou průhlednosti. To budeme potřebovat pro nastavení průhlednosti okna dále v kódu.
Využijeme možnosti jednoduše konvertovat z hexadecimálního zápisu HTML, který je upraven o Alpha kanál ve formátu tak, jak je naznačeno v tabulce níže:

Rozsah barevné hloubky je zapsán hexadecimálně a je tedy v rozsahu
0
-255
pro každý barevný kanál. V příkladu je 50%
hodnota pro všechny kanály, což dělá přibližně číslo 127
(7F
).
Toto vše jednoduše zastřešuje
System.Windows.Media.BrushConverter
:
var converter = new System.Windows.Media.BrushConverter();
Více ale už v Code behind v druhém díle.