Vi piace quell’effetto di vetro semitrasparente che contraddistingue l’interfaccia Aero di Windows Vista e di Windows 7? Con WPF è possibile utilizzarla nelle proprie applicazioni, per offrire una tocco in più che spesso fa innamorare i nostri utenti… è necessario tirare fuori alcune API, ma non c’è nulla di veramente complicato. In effetti ci sono solamente due limiti all’utilizzo di questa funzionalità:
- la “glass area” si estende sempre dai bordi della finestra verso l’interno della stessa;
- non è possibile creare zone vetrificate isolate (a macchia di leopardo, tanto per intenderci) nella client area della finestra;
Vediamo per prima cosa le API da importare, che provengono dalla dll DwmApi.dll (non presente in Windows XP!)
1: [StructLayout(LayoutKind.Sequential)]
2: public struct Margins
3: {
4: public int cxLeftWidth;
5: public int cxRightWidth;
6: public int cyTopHeight;
7: public int cyBottomHeight;
8: }
9:
10: [DllImport("DwmApi.dll")]
11: private static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref Margins margins);
La chiamata alla DwmExtendFrameIntoClientArea consente di estendere i “bordi” della finestra all’interno della finestra stessa. I valori –1 dei margini hanno il particolare significato di estendere l’effetto vetro all’interno di tutta la client area della window.
Sempre nella classe Glassificator, ho creato due metodi:
- il primo necessario per impostare correttamente i margini basandosi sui Dpi correnti del sistema;
- il secondo è un helper che consente con una singola chiamata di impostare l’effetto vetro desiderato su una finestra;
1: private static Margins GetDpiMargins(IntPtr hwnd, int left, int right, int top, int bottom)
2: {
3: System.Drawing.Graphics g = System.Drawing.Graphics.FromHwnd(hwnd);
4: float _dpiX = g.DpiX;
5: float _dpiY = g.DpiY;
6:
7: Margins _margins = new Margins();
8: _margins.cxLeftWidth=Convert.ToInt32(left * (_dpiX / 96));
9: _margins.cxRightWidth=Convert.ToInt32(right * (_dpiX / 96));
10: _margins.cyTopHeight=Convert.ToInt32(top * (_dpiX / 96));
11: _margins.cyBottomHeight=Convert.ToInt32(bottom * (_dpiX / 96));
12:
13: return _margins;
14: }
15:
16: public static void Glassify(Window win, int left, int right, int top, int bottom)
17: {
18: //Se siamo su Vista o Windows 7, allora possiamo procedere
19: if (Environment.OSVersion.Version.Major > 5)
20: {
21: WindowInteropHelper _helper = new WindowInteropHelper(win);
22: HwndSource _hSource = (HwndSource)HwndSource.FromHwnd(_helper.Handle);
23:
24: _hSource.CompositionTarget.BackgroundColor = Colors.Transparent;
25: win.Background = Brushes.Transparent;
26:
27: Margins _margins = GetDpiMargins(_helper.Handle, left, right, top, bottom);
28: int _retVal = DwmExtendFrameIntoClientArea(_helper.Handle, ref _margins);
29: if (_retVal < 0)
30: throw new NotSupportedException("Glassification not supported.");
31: }
32: }
notare che è stata controllata la versione del sistema operativo in uso, in quanto se fossimo su Windows XP, questo effetto non sarebbe disponibile. Come utilizzare queste funzioni da una finestra? Molto semplice: creiamo una banale window senza preoccuparci del particolare effetto:
1: <Window x:Class="GlassyWindow.Window1"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: Title="Glass Window" Loaded="Window_Loaded" Width="300" Height="300">
5: <Grid>
6: <Button Content="Hello from the glass world!" Margin="50,100,50,100"/>
7: </Grid>
8: </Window>
Nell’evento Loaded, interveniamo per modificare il comportamento della client area con una chiamata al metodo statico Glassify della classe Glassificator:
1: public partial class Window1 : Window
2: {
3: public Window1()
4: {
5: InitializeComponent();
6: }
7:
8: private void Window_Loaded(object sender, RoutedEventArgs e)
9: {
10: try
11: {
12: Glassificator.Glassify(this, -1, -1, -1, -1);
13: }
14: catch (Exception)
15: {
16: this.Background = Brushes.White;
17: }
18: }
19: }
Tutto qui! Come avete visto, quest’effetto piuttosto semplice da ottenere potrà sicuramente abbellire alcuni dei vostri progetti. Il codice del progetto lo potete trovare qui.