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.

  1. 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.

    Figure 1

  2. 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;
                }
            }
     
        }
  3. 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();
      }
  4. 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.

  5. Finally, a working example (WPF Project) of the above steps can be downloaded from here!

    GOOD LUCK

One Response to “Methods to drag and resize your C# transparent WPF application with the WindowStyle property set to None”

Leave a Reply

*

Haider’s WebSpace
Welcome to my technical blog. This is where I write, archive and share computer related articles. Subjects vary from posting technical solutions to researching particular topics. Feel free to comment and talk IT!
Sponsored Links
My Tweets
Posts Calendar
May 2012
M T W T F S S
« Mar    
 123456
78910111213
14151617181920
21222324252627
28293031