代码之家  ›  专栏  ›  技术社区  ›  Roman Starkov

如何修复WPF窗体调整大小的滞后和黑色背景?

wpf
  •  25
  • Roman Starkov  · 技术社区  · 16 年前

    我有一个非常简单的WPF窗口,里面只有一个右对齐的按钮。当我通过拖动左边界来调整窗口大小时,按钮会跳来跳去——跳得很多。自己试试,来回拖动左边界。

    this

    enter image description here

    黑色边框示例:这是在调整窗口大小时捕获的;这种情况只持续了一瞬间,但非常明显:

    enter image description here

    我做错什么了吗?在调整大小的过程中,如何使我的控件在视觉上保持在一个位置?如何避开黑色边框?

    -它只是四处跳跃 在调整大小的过程中。

    5 回复  |  直到 8 年前
        1
  •  10
  •   ghord    13 年前

    这是基于Wieser软件有限公司的第二个解决方案的完整工作代码。

    public partial class MainView : Window
    {
        public MainView()
        {
            InitializeComponent();
    
            //ensure win32 handle is created
            var handle = new WindowInteropHelper(this).EnsureHandle();
    
            //set window background
            var result = SetClassLong(handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW));
        }
    
        public static IntPtr SetClassLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
        {
            //check for x64
            if (IntPtr.Size > 4)
                return SetClassLongPtr64(hWnd, nIndex, dwNewLong);
            else
                return new IntPtr(SetClassLongPtr32(hWnd, nIndex, unchecked((uint)dwNewLong.ToInt32())));
        }
    
        private const int GCL_HBRBACKGROUND = -10;
        private const int COLOR_WINDOW = 5;
    
        [DllImport("user32.dll", EntryPoint = "SetClassLong")]
        public static extern uint SetClassLongPtr32(IntPtr hWnd, int nIndex, uint dwNewLong);
    
        [DllImport("user32.dll", EntryPoint = "SetClassLongPtr")]
        public static extern IntPtr SetClassLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
    
        [DllImport("user32.dll")]
        static extern IntPtr GetSysColorBrush(int nIndex);
    }
    
        2
  •  3
  •   Roman Starkov    16 年前

    在当前版本的WPF中,这似乎是不可能的。

        3
  •  3
  •   Anthony Wieser    13 年前

    这里描述了两种解决方案: http://wieser-software.blogspot.co.uk/2012/06/wpf-window-rendering-woes.html

    1. 勾选WndProc并处理WM_ERASEBKGND,然后在背景上绘制系统WINDOW_COLOR,或者根据应用程序主题绘制其他颜色。
    2. 调用SetClassLong来设置窗口类背景画笔

      SetClassLong(句柄、GCL_HBRBACKGROUND、GetSysColorBrush(COLOR_WINDOW));

        4
  •  1
  •   Martin Liversage    16 年前

    我认为临时黑色背景是WPF的一个问题,与WPF使用DirectX作为渲染机制有关,当你调整窗口大小时,它必须将绘图与窗口系统同步。这也可以解释为什么在拖动窗口边框时,按钮相对于窗口放错了位置。绘制窗口的非客户端区域比绘制窗口内部的区域要慢得多,如果你在慢速计算机上快速移动鼠标,窗口边界端和内部之间的差异可能会更明显。

    假设这只发生在启用Aero的Vista上,并且应该在Vista SP1中修复。然而,我刚刚在SP2上进行了测试,我仍然看到了一点黑色背景,但只有在启用Aero时。我的显卡速度很快,所以几乎不引人注意。

    如果我的分析是正确的,那么解决问题的唯一方法就是获取更快的显卡或关闭Aero。

        5
  •  0
  •   Louis Semprini    7 年前

    其他答案已经解决了如何填充不同的背景颜色,以尝试减轻WPF慢速绘图的影响。

    我无法提供任何魔法来加速WPF,但我可以提供一些关于黑色来源的见解。

    第一个屏幕截图中的视觉错误是由于Aero添加了额外的调整大小问题,并且有一个部分解决方法。

    我正在与原生Win32应用程序中丑陋的实时调整大小问题作斗争,我创建了一个综合问题/答案,汇集了10年来关于调整大小问题的帖子,并提供了一些新的见解(太长了,无法在这个问题中粘贴内容)。请参阅:

    How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?