Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wpf custom window, Windows edge resize feature

Tags:

c#

windows

wpf

Got a custom wpf window (WindowStyle=None, AllowTransparancy=true) and wondering how to get Windows edge resize features to work.. you know when draging window and mouse touches left, right or top edge of screen (even corners in W10).

Tried looking into WM notification but none of them seems to be what im looking for..

To clearify, not ordinary window resizeing.. but draging to screen edge and letting Windows resize it to half/full/quarter (think its called Aero Snap). And I can do it with ordinary resize calls but that doesnt show the transparent preview window or drop animation on mouse when touches edge.

Thanks

like image 756
Joel R Avatar asked Nov 26 '14 19:11

Joel R


1 Answers

Step 1

Create a Style (in <Window1.Resources>) for rectangles as the Grip area around the window:

<Style x:Key="RectBorderStyle" TargetType="Rectangle">
    <Setter Property="Focusable" Value="False" />
    <Setter Property="Fill" Value="Transparent" />
    <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}" />
    <EventSetter Event="MouseLeftButtonDown" Handler="Resize_Init"/>
    <EventSetter Event="MouseLeftButtonUp" Handler="Resize_End"/>
    <EventSetter Event="MouseMove" Handler="Resizeing_Form"/>
</Style>

Step 2

Add these styled rectangles to your window. (You can add them inside a simple grid within your window)

<Rectangle x:Name="leftSizeGrip"
    Width="7"
    HorizontalAlignment="Left"
    Cursor="SizeWE"
    Style="{StaticResource RectBorderStyle}" />
<Rectangle x:Name="rightSizeGrip"
    Width="7"
    HorizontalAlignment="Right"
    Cursor="SizeWE"
    Style="{StaticResource RectBorderStyle}" />
<Rectangle x:Name="topSizeGrip"
    Height="7"
    VerticalAlignment="Top"
    Cursor="SizeNS"
    Style="{StaticResource RectBorderStyle}" />
<Rectangle x:Name="bottomSizeGrip"
    Height="7"
    VerticalAlignment="Bottom"
    Cursor="SizeNS"
    Style="{StaticResource RectBorderStyle}" />
<!--  Corners  -->
<Rectangle Name="topLeftSizeGrip"
    Width="7"
    Height="7"
    HorizontalAlignment="Left"
    VerticalAlignment="Top"
    Cursor="SizeNWSE"
    Style="{StaticResource RectBorderStyle}" />
<Rectangle Name="bottomRightSizeGrip"
    Width="7"
    Height="7"
    HorizontalAlignment="Right"
    VerticalAlignment="Bottom"
    Cursor="SizeNWSE"
    Style="{StaticResource RectBorderStyle}" />
<Rectangle Name="topRightSizeGrip"
    Width="7"
    Height="7"
    HorizontalAlignment="Right"
    VerticalAlignment="Top"
    Cursor="SizeNESW"
    Style="{StaticResource RectBorderStyle}" />
<Rectangle Name="bottomLeftSizeGrip"
    Width="7"
    Height="7"
    HorizontalAlignment="Left"
    VerticalAlignment="Bottom"
    Cursor="SizeNESW"
    Style="{StaticResource RectBorderStyle}" />

Step 3

Add these codes to the code behind of your window (window1.xaml.cs) (or to MyStyle.xaml.cs if you are using a template for window and you have added the 8 rectangles inside the template)

#region ResizeWindows
bool ResizeInProcess = false;
private void Resize_Init(object sender, MouseButtonEventArgs e)
{
    Rectangle senderRect = sender as Rectangle;
    if (senderRect != null)
    {
        ResizeInProcess = true;
        senderRect.CaptureMouse();
    }
}

private void Resize_End(object sender, MouseButtonEventArgs e)
{
    Rectangle senderRect = sender as Rectangle;
    if (senderRect != null)
    {
        ResizeInProcess = false; ;
        senderRect.ReleaseMouseCapture();
    }
}

private void Resizeing_Form(object sender, MouseEventArgs e)
{
    if (ResizeInProcess)
    {
        Rectangle senderRect = sender as Rectangle;
        Window mainWindow = senderRect.Tag as Window;
        if (senderRect != null)
        {
            double width = e.GetPosition(mainWindow).X;
            double height = e.GetPosition(mainWindow).Y;
            senderRect.CaptureMouse();
            if (senderRect.Name.ToLower().Contains("right"))
            {
                width += 5;
                if (width > 0)
                    mainWindow.Width = width;
            }
            if (senderRect.Name.ToLower().Contains("left"))
            {
                width -= 5;
                mainWindow.Left += width;
                width = mainWindow.Width - width;
                if (width > 0)
                {
                    mainWindow.Width = width;
                }
            }
            if (senderRect.Name.ToLower().Contains("bottom"))
            {
                height += 5;
                if (height > 0)
                    mainWindow.Height = height;
            }
            if (senderRect.Name.ToLower().Contains("top"))
            {
                height -= 5;
                mainWindow.Top += height;
                height = mainWindow.Height - height;
                if (height > 0)
                {
                    mainWindow.Height = height;
                }
            }
        }
    }
}
#endregion

Step 4

Press F5 and enjoy!

note:

these 8 rectangles are transparent. if you can't make it properly work, just change the Fill value of the style to Red to see where are they positioned.

Another note:

When maximized you might want to disable all these rectangles. well the easiest way is to handle the WindowStateChanged event and disable the grid containing them.

like image 102
Bizhan Avatar answered Sep 22 '22 00:09

Bizhan