我有一个非常基本的测试应用程序,仅由 aWindow
和 a组成CustomControl
。该窗口包含自定义控件并具有以下附加属性:
TextOptions.TextFormattingMode="Display"
SnapsToDevicePixels="True"
UseLayoutRounding="True"
RenderOptions.EdgeMode="Aliased"
自定义控件将以下 5 行添加到代码隐藏文件中:
protected override void OnRender(DrawingContext drawingContext)
{
var pen = new Pen(Brushes.Black, 1);
drawingContext.DrawLine(pen, new Point(0, 0), new Point(ActualWidth, ActualHeight));
}
一切都很好。从左上角到右下角对角绘制一条黑色的 1px 线。完美的。诚然像素化,但正是我需要的。但是,当我最小化窗口并再次恢复它时,线条变得“模糊”。OnRender
在窗口恢复后,不会再次调用该方法,就会发生这种情况。那么为什么在窗口最小化后绘制的图形会发生根本性的变化(失去焦点似乎不是问题)?为什么在简单地调整窗口大小后一切都恢复正常,我该如何处理这种不需要的行为?每次WindowState
更改似乎有点过分时,强制完全调整大小/无效,不是吗?
更新1:
正如@Backlash 建议的那样,我将自定义控件放在画布中
<Canvas Name="CanvasControl" SizeChanged="FrameworkElement_OnSizeChanged">
<wpfTest:CustomControl x:Name="ChildControl" />
</Canvas>
并像这样处理SizeChanged
事件
private void FrameworkElement_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
ChildControl.Width = CanvasControl.ActualWidth;
ChildControl.Height = CanvasControl.ActualHeight;
}
因为画布内的元素不会自动布局。然而,结果并没有改变。
更新 2:
我想到的一个想法是监听窗口状态的变化并通过稍微改变窗口的Width
orHeight
属性来强制调整窗口及其所有控件的大小 - 因此完全重绘 -
protected override void OnStateChanged(EventArgs e)
{
if (WindowState != WindowState.Minimized)
{
Width += 1;
}
}
这在某些情况下有效(尽管Window
例如在最大化时不起作用),但一般来说,由于多种原因,这是一种非常糟糕的方法。我试图了解在更改大小时导致(正确)重绘的原因,并且它可能与CoreFlags.AreTransformsClean
.
更新 3:
鉴于 WPF 似乎无法直接在屏幕上绘制直线,因此我尝试先在内存中绘制位图,然后再将位图绘制到屏幕上。它有效。这是方法:
protected override void OnRender(DrawingContext drawingContext)
{
var rtb = new RenderTargetBitmap((int)ActualWidth, (int)ActualHeight, 96, 96, PixelFormats.Pbgra32);
var line = new Line();
RenderOptions.SetEdgeMode(line, EdgeMode.Aliased);
line.Stroke = Brushes.Black;
line.StrokeThickness = 1;
line.X1 = 0;
line.X2 = ActualWidth;
line.Y1 = 0;
line.Y2 = ActualHeight;
line.Arrange(new Rect(new Size((int)ActualWidth, (int)ActualHeight)));
rtb.Render(line);
drawingContext.DrawImage(rtb, new Rect(0, 0, (int)ActualWidth, (int)ActualHeight));
}
至少可以说,“解决方案”很老套。这真的很糟糕,但与我迄今为止从 WPF 看到的其他方法相比,这可能是一种合法的方法。但是,将保留线程以获取更多答案。