/ src / modules / cmdpal / Microsoft.CmdPal.UI / Helpers / WindowExtensions.cs
WindowExtensions.cs
 1  // Copyright (c) Microsoft Corporation
 2  // The Microsoft Corporation licenses this file to you under the MIT license.
 3  // See the LICENSE file in the project root for more information.
 4  
 5  using Microsoft.UI;
 6  using Microsoft.UI.Windowing;
 7  using Microsoft.UI.Xaml;
 8  using Windows.Win32;
 9  using Windows.Win32.Foundation;
10  using Windows.Win32.Graphics.Dwm;
11  using Windows.Win32.UI.WindowsAndMessaging;
12  
13  namespace Microsoft.CmdPal.UI.Helpers;
14  
15  internal static class WindowExtensions
16  {
17      public static void SetIcon(this Window window)
18      {
19          var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
20          WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
21          AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
22          appWindow.SetIcon(@"Assets\icon.ico");
23      }
24  
25      public static HWND GetWindowHwnd(this Window window)
26      {
27          return window is null
28              ? throw new ArgumentNullException(nameof(window))
29              : new HWND(WinRT.Interop.WindowNative.GetWindowHandle(window));
30      }
31  
32      /// <summary>
33      /// Toggles the specified extended window style on or off for the supplied <see cref="Window"/>.
34      /// </summary>
35      /// <param name="window">The <see cref="Window"/> whose extended window styles will be modified. Cannot be null.</param>
36      /// <param name="style">The <see cref="WINDOW_EX_STYLE"/> flag(s) to set or clear.</param>
37      /// <param name="isStyleSet">When true, the specified <paramref name="style"/> bit(s) will be set (added). When false, the bit(s) will be cleared (removed).</param>
38      /// <returns>True if the call to SetWindowLong succeeded and the style was applied; otherwise false.</returns>
39      /// <exception cref="ArgumentNullException">Thrown if <paramref name="window"/> is null.</exception>
40      internal static bool ToggleExtendedWindowStyle(this Window window, WINDOW_EX_STYLE style, bool isStyleSet)
41      {
42          var hWnd = GetWindowHwnd(window);
43          var currentStyle = PInvoke.GetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
44  
45          if (isStyleSet)
46          {
47              currentStyle |= (int)style;
48          }
49          else
50          {
51              currentStyle &= ~(int)style;
52          }
53  
54          var wasSet = PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, currentStyle) != 0;
55  
56          // SWP_FRAMECHANGED - invalidate cached window style
57          PInvoke.SetWindowPos(hWnd, new HWND(IntPtr.Zero), 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_FRAMECHANGED | SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOZORDER | SET_WINDOW_POS_FLAGS.SWP_NOOWNERZORDER);
58  
59          return wasSet;
60      }
61  
62      /// <summary>
63      /// Sets the window corner preference
64      /// </summary>
65      /// <param name="window">The window</param>
66      /// <param name="cornerPreference">The desired corner preference</param>
67      /// <returns>True if the operation succeeded</returns>
68      public static bool SetCornerPreference(this Window window, DWM_WINDOW_CORNER_PREFERENCE cornerPreference)
69      {
70          return window.GetWindowHwnd().SetDwmWindowAttribute(DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE, cornerPreference);
71      }
72  
73      /// <summary>
74      /// Unified wrapper for DwmSetWindowAttribute calls with enum values
75      /// </summary>
76      private static bool SetDwmWindowAttribute<T>(this HWND hwnd, DWMWINDOWATTRIBUTE attribute, T value)
77          where T : unmanaged, Enum
78      {
79          unsafe
80          {
81              var result = PInvoke.DwmSetWindowAttribute(hwnd, attribute, &value, (uint)sizeof(T));
82              return result.Succeeded;
83          }
84      }
85  }