首页 > 解决方案 > 自定义调整窗口大小

问题描述

我想要一个自定义更大的句柄来调整我的 WPF 窗口的大小。

在到处跟踪几个线程(尤其是这个这个)之后,我最终卡住了我的窗口,因为它似乎设置了 Width/Height 和 Left/Top 使渲染不稳定,正如你在这个gif中看到的那样。

(您可以注意到使用标准窗口调整大小处理效果很好,但它们非常薄。也许它是操作系统管理的??)

试图RenderTransform TranslateTransform在后面的代码中使用自定义,但没有成功。

我试图在渲染之前“批量”分配这两个值(要么thread.Sleep()using(Dispatcher.DisableProcessing())),但没有任何成功,我认为渲染仍然是按顺序进行的。

这是我的参考代码:

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);
}

标签: c#wpfxamlresize

解决方案


把这个问题放在一边后,我终于回到了它。发现这个问题非常有启发性。而且,正如另一个 SO question指出的那样,我找到的解决方案是使用ControlzEx WindowChromeBehavior。

当我有点想知道如何使用它时,这是我的 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 !!! -->

推荐阅读