自定义调整大小Window 抖动
Custom resize Window shaking
我想要自定义更大的句柄来调整我的 WPF window。
在关注了几个线程之后(尤其是 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。
(您可以注意到使用标准 Window 调整大小手柄效果很好,但它们非常薄。也许它是 OS 管理的??)
尝试在代码隐藏中使用自定义 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);
}
搁置这个问题后,我终于回到了正题。
发现这个 非常有指导意义。
并且,正如另一个 SO , the solution I found was to use 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 !!! -->
我想要自定义更大的句柄来调整我的 WPF window。
在关注了几个线程之后(尤其是 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。
(您可以注意到使用标准 Window 调整大小手柄效果很好,但它们非常薄。也许它是 OS 管理的??)
尝试在代码隐藏中使用自定义 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);
}
搁置这个问题后,我终于回到了正题。
发现这个
因为我有点想知道如何使用它,这是我的 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 !!! -->