If your objective is to develop a software with highly customized Windows then start a new WPF application in Visual Studio (VS). Currently I am developing a new ‘Desktop Sticky Notes’ software hence it is important that my windows (notes) are designed like an e-replica of a real sticky note on your desktop.
As such I started a new WPF project, dragged a Grid control from the Toolbox and decided to set my WindowStyle property to None, AllowTransparency to True and finally ResizeMode to NoResize. These steps would generate the following XAML code in VS:
1 2 3 4 5 6 7 8 | <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" ResizeMode="NoResize" AllowsTransparency="True" Opacity="1" WindowStyle="None"> <Grid> <Grid Height="311" HorizontalAlignment="Left" Name="grid1" VerticalAlignment="Top" Width="503" /> </Grid> </Window> |
Running this code will generate a white empty grid. Although we can now add any type of control, our layout can not be resized!
It seems that there are currently no built-in methods in VS to accomplish this task. However, a suitable solution has been posted online. This code must be repeated for every window. I decided to develop the necessary piece of codes into a separate C# class to provide a reusable, easy-to-use methods to resize WPF transparent windows. In the following few steps I will explain how easily it is now to let your transparent windows resized on all corners and sides.
- From the Toolbox, use the Rectangle control to draw 4 borders and 4 corners around your Grid similar to Figure 1. For the code to work you must give these rectangles the following names appropriately: top, left, right, bottom, topLeft, topRight, bottomLeft and finally bottomRight. If you dont use these names, the code will not work!
In addition, set the HorizontalAlignment, VerticalAlignment, Width and Height for each of the rectangles. Make sure you set them to Stretch and Auto when appropriate. For instance, the top rectangle will have HorizontalAlignment set to Stretch, VerticalAlignment set to Top, Width to Auto and Height to a suitable number such as 15.
- In your ‘Solution Explorer’ right-click your project’s name (in my example it is WpfApplication1) to add a new C# file. Make sure you call it: WindowResizer.cs and replace its content with the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Interop; using System.Runtime.InteropServices; using System.Diagnostics; class WindowResizer { private const int WM_SYSCOMMAND = 0x112; private HwndSource hwndSource; Window activeWin; public WindowResizer(Window activeW) { activeWin = activeW as Window; activeWin.SourceInitialized += new EventHandler(InitializeWindowSource); } public void resetCursor() { if (Mouse.LeftButton != MouseButtonState.Pressed) { activeWin.Cursor = Cursors.Arrow; } } public void dragWindow() { activeWin.DragMove(); } private void InitializeWindowSource(object sender, EventArgs e) { hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource; hwndSource.AddHook(new HwndSourceHook(WndProc)); } IntPtr retInt = IntPtr.Zero; private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { Debug.WriteLine("WndProc messages: " + msg.ToString()); // // Check incoming window system messages // if (msg == WM_SYSCOMMAND) { Debug.WriteLine("WndProc messages: " + msg.ToString()); } return IntPtr.Zero; } public enum ResizeDirection { Left = 1, Right = 2, Top = 3, TopLeft = 4, TopRight = 5, Bottom = 6, BottomLeft = 7, BottomRight = 8, } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); private void ResizeWindow(ResizeDirection direction) { SendMessage(hwndSource.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero); } public void resizeWindow(object sender) { Rectangle clickedRectangle = sender as Rectangle; switch (clickedRectangle.Name) { case "top": activeWin.Cursor = Cursors.SizeNS; ResizeWindow(ResizeDirection.Top); break; case "bottom": activeWin.Cursor = Cursors.SizeNS; ResizeWindow(ResizeDirection.Bottom); break; case "left": activeWin.Cursor = Cursors.SizeWE; ResizeWindow(ResizeDirection.Left); break; case "right": activeWin.Cursor = Cursors.SizeWE; ResizeWindow(ResizeDirection.Right); break; case "topLeft": activeWin.Cursor = Cursors.SizeNWSE; ResizeWindow(ResizeDirection.TopLeft); break; case "topRight": activeWin.Cursor = Cursors.SizeNESW; ResizeWindow(ResizeDirection.TopRight); break; case "bottomLeft": activeWin.Cursor = Cursors.SizeNESW; ResizeWindow(ResizeDirection.BottomLeft); break; case "bottomRight": activeWin.Cursor = Cursors.SizeNWSE; ResizeWindow(ResizeDirection.BottomRight); break; default: break; } } public void displayResizeCursor(object sender) { Rectangle clickedRectangle = sender as Rectangle; switch (clickedRectangle.Name) { case "top": activeWin.Cursor = Cursors.SizeNS; break; case "bottom": activeWin.Cursor = Cursors.SizeNS; break; case "left": activeWin.Cursor = Cursors.SizeWE; break; case "right": activeWin.Cursor = Cursors.SizeWE; break; case "topLeft": activeWin.Cursor = Cursors.SizeNWSE; break; case "topRight": activeWin.Cursor = Cursors.SizeNESW; break; case "bottomLeft": activeWin.Cursor = Cursors.SizeNESW; break; case "bottomRight": activeWin.Cursor = Cursors.SizeNWSE; break; default: break; } } }
- Now that we added the WindowResizer class, we can make use of its methods to resize our window. View the code of your window class where you want to support resizing and do the following:
- Initiate an object before the constructor: WindowResizer ob;
- Add the following line inside the constructor: ob = new WindowResizer(this);
- Then add the following methods (read the comment inside for further instructions):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// for each rectangle, assign the following method to its MouseEnter event. private void DisplayResizeCursor(object sender, MouseEventArgs e) { ob.displayResizeCursor(sender); } // for each rectangle, assign the following method to its MouseLeave event. private void ResetCursor(object sender, MouseEventArgs e) { ob.resetCursor(); } // for each rectangle, assign the following method to its PreviewMouseDown event. private void Resize(object sender, MouseButtonEventArgs e) { ob.resizeWindow(sender); } // finally, you may use the following method to enable dragging! private void Drag(object sender, MouseButtonEventArgs e) { ob.dragWindow(); }
- Click run to test your code, if everything has been done correctly you can now make the 8 rectangles transparent to have a neat look for your window. Of course you may reuse these methods for as many windows as you have as part of your project.
- Finally, a working example (WPF Project) of the above steps can be downloaded from here!
GOOD LUCK


A very very mega thank you for the WindowResizer class!! It’s brilliant and works perfectly! This spares some hours for me =)