0

I want to have a custom bigger handle to resize my WPF window.

After following several thread here and there (especially this and this) I end up stuck with my window shaking hard because it appear set both Width/Height AND Left/Top make the rendering shaky, as you can see in this gif.

(you can note using standard Window resize handle work well, but they are very thin. Maybe it is OS managed ??)

Tried to play with a custom RenderTransform TranslateTransform in code behind but didn't worked out.

I tried to "batch" the assignation to both those value before rendering (Either thread.Sleep() or using(Dispatcher.DisableProcessing())), but without any success, that I think the rendering is still happening sequentially anyway.

Here is my code for reference :

XAML

<Window [....]>
[...]
<Style x:Key="ThumbStyle" TargetType="Thumb">
                <Setter Property="Focusable" Value="False" />
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}" />
                <EventSetter Event="DragStarted" Handler="Thumb_DragStarted"/>
                <EventSetter Event="DragCompleted" Handler="Thumb_DragCompleted"/>
                <EventSetter Event="DragDelta" Handler="Thumb_DragDelta"/>
            </Style>

<!--This doesn't work like it worked for a Canvas unfortunately-->
<Window.RenderTransform>
        <TransformGroup>
            <ScaleTransform x:Name="scl"/>
            <TranslateTransform x:Name="translate"/>
        </TransformGroup>
    </Window.RenderTransform>

<Grid x:Name="RootGrid" Background="Black">    
        <Thumb x:Name="leftSizeGrip"
    Width="20"
    HorizontalAlignment="Left"
    Cursor="SizeWE"
    Style="{StaticResource ThumbStyle}" />
        <Thumb x:Name="rightSizeGrip"
    Width="20"
    HorizontalAlignment="Right"
    Cursor="SizeWE"
    Style="{StaticResource ThumbStyle}" />
        <Thumb x:Name="topSizeGrip"
    Height="20"
    VerticalAlignment="Top"
    Cursor="SizeNS"
    Style="{StaticResource ThumbStyle}" />
        <Thumb x:Name="bottomSizeGrip"
    Height="20"
    VerticalAlignment="Bottom"
    Cursor="SizeNS"
    Style="{StaticResource ThumbStyle}" />
        <!--  Corners  -->
        <Thumb Name="topLeftSizeGrip"
    Width="20"
    Height="20"
    HorizontalAlignment="Left"
    VerticalAlignment="Top"
    Cursor="SizeNWSE"
    Style="{StaticResource ThumbStyle}" />
        <Thumb Name="bottomRightSizeGrip"
    Width="20"
    Height="20"
    HorizontalAlignment="Right"
    VerticalAlignment="Bottom"
    Cursor="SizeNWSE"
    Style="{StaticResource ThumbStyle}" />
        <Thumb Name="topRightSizeGrip"
    Width="20"
    Height="20"               
    HorizontalAlignment="Right"
    VerticalAlignment="Top"
    Cursor="SizeNESW"
    Style="{StaticResource ThumbStyle}" />
        <Thumb Name="bottomLeftSizeGrip"
    Width="20"
    Height="20"
    HorizontalAlignment="Left"
    VerticalAlignment="Bottom"
    Cursor="SizeNESW"
    Style="{StaticResource ThumbStyle}" />
[...]
</Window>

C#

private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
    Thumb senderThumb = sender as Thumb;

    if (senderThumb == null)
        return;

    int horizontalMultiplier = 0, verticalMultiplier = 0;
    
    Window mainWindow = senderThumb.Tag as Window;

    var dragDelta = Mouse.GetPosition(mainWindow) - lastMousePos;
    lastMousePos = Mouse.GetPosition(mainWindow);
    
    if (senderThumb.Name.Contains("right", StringComparison.OrdinalIgnoreCase))
    {                
        horizontalMultiplier = 1;
    }
    if (senderThumb.Name.Contains("left", StringComparison.OrdinalIgnoreCase))
    {
        horizontalMultiplier = -1;
    }            
    if (senderThumb.Name.Contains("bottom", StringComparison.OrdinalIgnoreCase))
    {             
        verticalMultiplier = 1;
    }
    if (senderThumb.Name.ToLower().Contains("top", StringComparison.OrdinalIgnoreCase))
    {
        verticalMultiplier = -1;                
    }            

    var xadjust = mainWindow.Width + horizontalMultiplier * dragDelta.X;
    var yadjust = mainWindow.Height + verticalMultiplier * dragDelta.Y;

    if (xadjust > 0)
    {
        mainWindow.Width = xadjust;
        
        //translate.X += dragDelta.X * (horizontalMultiplier < 0 ? 1 : 0);
        Left += dragDelta.X * (horizontalMultiplier < 0 ? 1 : 0);
        
        if (yadjust > 0)
        {
            mainWindow.Height = yadjust;
            
            //translate.Y += dragDelta.Y * (verticalMultiplier < 0 ? 1 : 0);
            Top += dragDelta.Y * (verticalMultiplier < 0 ? 1 : 0);

            //Canvas.SetTop(myThumbBR, Canvas.GetTop(myThumbBR) +
            //           verticalMultiplier * dragDelta.Y);

            //Canvas.SetTop(myThumbBL, Canvas.GetTop(myThumbBL) +
            //            verticalMultiplier * dragDelta.Y);

            //Canvas.SetTop(myThumbB, Canvas.GetTop(myThumbB) +
            //            verticalMultiplier * dragDelta.Y);
        }

        //Canvas.SetLeft(myThumbBR, Canvas.GetLeft(myThumbBR) +
        //                 horizontalMultiplier * dragDelta.X);

        //Canvas.SetLeft(myThumbTR, Canvas.GetLeft(myThumbTR) +
        //                 horizontalMultiplier * dragDelta.X);

        //Canvas.SetLeft(myThumbR, Canvas.GetLeft(myThumbR) +
        //                 horizontalMultiplier * dragDelta.X);                    
    }
}

private void Thumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
    ((Thumb)sender).Background = Brushes.Red;
}        

private void Thumb_DragStarted(object sender, DragStartedEventArgs e)
{
    ((Thumb)sender).Background = Brushes.IndianRed;
    lastMousePos = Mouse.GetPosition(this);
}
TRex
  • 127
  • 1
  • 8

1 Answers1

0

After keeping this issue aside, I finally get back to it. Found this question to be extremely instructive. And, as pointed from another SO question, the solution I found was to use ControlzEx WindowChromeBehavior.

As I struggled a bit to know how to use it, here is my XAML :

<Window>
  xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
  xmlns:ctzex="urn:controlzex"
  [...]
</Window>
<i:Interaction.Behaviors>
    <ctzex:WindowChromeBehavior TryToBeFlickerFree="True" ResizeBorderThickness="30" 
                                EnableMinimize="True" EnableMaxRestore="True" KeepBorderOnMaximize="True"/>
</i:Interaction.Behaviors> <!--It does work !!! -->
TRex
  • 127
  • 1
  • 8