1

I'm having some trouble doind a custom window resizing behavior. What I need is when you resize the window(dragging from the border) it has to show a resizing border that changes its size according to the mouse position and when the mouse left click is released it applies the new size to the window, like Skype does.

What I have is this:

Window XAML:

<Window x:Class="View.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:sw="clr-namespace:View.WindowStyle"
    Title="CustomWindow" Height="600" Width="800"    
    MinWidth="800"
    MinHeight="600"
    WindowStartupLocation="CenterScreen">
    <Grid>
        <!-- windows items -->
        <Thumb x:Name="ThumbTop" Height="6" Margin="8,0" VerticalAlignment="Top" Cursor="SizeNS"  Opacity="0" sw:WindowResizeBehavior.TopResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
        <Thumb x:Name="ThumbTopLeft" Height="8" Width="8" VerticalAlignment="Top" HorizontalAlignment="Left" Cursor="SizeNWSE"  Opacity="0" sw:WindowResizeBehavior.TopLeftResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
        <Thumb x:Name="ThumbBottom" Height="6" Margin="8,0" VerticalAlignment="Bottom" Cursor="SizeNS" Opacity="0" sw:WindowResizeBehavior.BottomResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
        <Thumb x:Name="ThumbTopRight" Height="8" Width="8" VerticalAlignment="Top" HorizontalAlignment="Right" Cursor="SizeNESW"  Opacity="0" sw:WindowResizeBehavior.TopRightResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
        <Thumb x:Name="ThumbRight" HorizontalAlignment="Right" Margin="0,6" Width="6" Cursor="SizeWE"  Opacity="0" sw:WindowResizeBehavior.RightResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
        <Thumb x:Name="ThumbBottomRight" Height="8" Width="8" VerticalAlignment="Bottom" HorizontalAlignment="Right" Cursor="SizeNWSE"  Opacity="0" sw:WindowResizeBehavior.BottomRightResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
        <Thumb x:Name="ThumbLeft" HorizontalAlignment="Left" Margin="0,8" Width="6" Cursor="SizeWE"  Opacity="0" sw:WindowResizeBehavior.LeftResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
        <Thumb x:Name="ThumbBottomLeft" Height="8" Width="8" VerticalAlignment="Bottom" HorizontalAlignment="Left" Cursor="SizeNESW"  Opacity="0" sw:WindowResizeBehavior.BottomLeftResize="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
    </Grid>

 </Window>

I'm using 8 thumbs to handle the resizing behavior and this is handled in a class, this is how the resize is done (just for one thumb but its the same logic for the other 7):

public static class WindowResizeBehavior
{
    public static Window GetBottomRightResize(DependencyObject obj)
    {
        return (Window)obj.GetValue(BottomRightResize);
    }

    public static void SetBottomRightResize(DependencyObject obj, Window window)
    {
        obj.SetValue(BottomRightResize, window);
    }

    public static readonly DependencyProperty BottomRightResize = DependencyProperty.RegisterAttached("BottomRightResize",
        typeof(Window), typeof(WindowResizeBehavior),
        new UIPropertyMetadata(null, OnBottomRightResizeChanged));

    private static void OnBottomRightResizeChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var thumb = sender as Thumb;

        if (thumb != null)
        {
            thumb.DragCompleted += DragBottomRight;
        }
    }
    private static void DragBottomRight(object sender, DragCompletedEventArgs e)
    {
        var thumb = sender as Thumb;
        var window = thumb.GetValue(BottomRightResize) as Window;

        if (window != null)
        {
            var verticalChange = window.SafeHeightChange(e.VerticalChange);
            var horizontalChange = window.SafeWidthChange(e.HorizontalChange);

            window.Width += horizontalChange;
            window.Height += verticalChange;
        }
    }
    private static double SafeWidthChange(this Window window, double change, bool positive = true)
    {
        var result = positive ? window.Width + change : window.Width - change;

        if (result <= window.MinWidth)
        {
            if (positive)
                return window.MinWidth - window.Width;
            else
                return window.Width - window.MinWidth;
        } else if(result >= window.MaxWidth)
        {
            return 0;
        } else if(result < 0)
        {
            return 0;
        }
        else
        {
            return change;
        }
    }

    private static double SafeHeightChange(this Window window, double change, bool positive = true)
    {
        var result = positive ? window.Height + change : window.Height - change;

        if (result <= window.MinHeight)
        {
            if (positive)
                return window.MinHeight - window.Height;
            else                    
                return window.Height - window.MinHeight;
        }
        else if (result >= window.MaxHeight)
        {
            return 0;
        }
        else if (result < 0)
        {
            return 0;
        }
        else
        {
            return change;
        }
    }
}

With this the resize is done when the mouse is release but now I don't know how to add the resizable border. By the way I'm using .NET 4.5 with MVVM. Many thanks

  • Please give us more info about 'resizable border' and what do you mean under this term. Right now it looks, for me, that you are trying to copy Skype's Main page (wich contains contacts info of the day and some adds) – Shakra Jan 10 '17 at 06:28
  • When the window border or corner is dragged, it shows a grey border (usually dotted) that changes its size according to the mouse position (just the border is changing its size, the window remains intact) and only when the mouse is released, the actual size of the border is applied to the window (changing its size). – Fabricio Monsalve Jan 10 '17 at 21:21
  • In pure wpf it's impossible, but can be done some workaround with border-less window + custom styles. If you newer mind of win32 usage then [this](http://stackoverflow.com/questions/14385838/draw-on-screen-without-form) might help you, there is a description how to draw a rectangle with pure win32 calls. – Shakra Jan 12 '17 at 08:56

1 Answers1

0
<Window WindowStyle="None"
        AllowsTransparency="True"
        Background="Transparent" 
        ResizeMode="CanResize"
        Title="WareHouse" 
        Height="600" 
        Width="1000"
        >
    
    <WindowChrome.WindowChrome>
        <WindowChrome/>   
    </WindowChrome.WindowChrome>
</Window>

WindowsChrome will let you resize the custom window.