4
votes

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

3

3 Answers

12
votes

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.

0
votes

Answer of Bizhan is great! But he made a small mistake. It's solution does not take into account the maximum and minimum window sizes. Because of this, instead of changing the window, it shifts. It work:

    private void Resizeing_Form(object sender, MouseEventArgs e)
    {
        if (ResizeInProcess)
        {
            double temp = 0;
            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.Contains("right", StringComparison.OrdinalIgnoreCase))
                {
                    width += 5;
                    if (width > 0)
                        mainWindow.Width = width;
                }
                if (senderRect.Name.Contains("left", StringComparison.OrdinalIgnoreCase))
                {
                    width -= 5;
                    temp = mainWindow.Width - width;
                    if ((temp > mainWindow.MinWidth) && (temp < mainWindow.MaxWidth))
                    {
                        mainWindow.Width = temp;
                        mainWindow.Left += width;
                    }
                }
                if (senderRect.Name.Contains("bottom", StringComparison.OrdinalIgnoreCase))
                {
                    height += 5;
                    if (height > 0)
                        mainWindow.Height = height;
                }
                if (senderRect.Name.ToLower().Contains("top", StringComparison.OrdinalIgnoreCase))
                {
                    height -= 5;
                    temp = mainWindow.Height - height;
                    if ((temp > mainWindow.MinHeight) && (temp < mainWindow.MaxHeight))
                    {
                        mainWindow.Height = temp;
                        mainWindow.Top += height;
                    }
                }
            }
        }
    }
0
votes

And for @GMIKE answer to work you need this String extension method (taken from here) :

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source?.IndexOf(toCheck, comp) >= 0;
    }
}