WPF 窗口移动在“限制”上闪烁

本文关键字:闪烁 限制 窗口 移动 WPF | 更新日期: 2023-09-27 17:57:01

我有WPF无边框透明窗口。

通过使用这个。拖动移动();我可以成功地移动窗口。

我想限制屏幕区域内的窗口。它也使用以下代码片段工作。

    private void Window_LocationChanged(object sender, EventArgs e)
            {
                CheckBounds();
    }
private void CheckBounds()
        {
            var height = System.Windows.SystemParameters.PrimaryScreenHeight;
            var width = System.Windows.SystemParameters.PrimaryScreenWidth;
            if (this.Left < 0)
                this.Left = 0;
            if (this.Top < 0)
                this.Top = 0;
            if (this.Top + this.Height > height)
                this.Top = height - this.Height;
            if (this.Left + this.Width > width)
                this.Left = width - this.Width;
        }

但是使用上面的代码,每当窗口使用鼠标拖动达到其最大边界时,它就会开始闪烁。

有人可以建议如何避免这种闪烁吗?

WPF 窗口移动在“限制”上闪烁

我知道处理

此问题的最佳方法是处理窗口中的WM_MOVING窗口消息并调整那里的位置。由于WM_MOVING消息是在窗口实际移动并允许修改位置之前收到的,因此您永远不会看到任何抖动。下面是一个Window的示例代码隐藏。

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
public partial class MainWindow : Window
{
    private HwndSource mSource;
    public MainWindow()
    {
        InitializeComponent();
    }
    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        mSource = (HwndSource)PresentationSource.FromVisual(this);
        mSource.AddHook(WndProc);
    }
    protected override void OnClosed(EventArgs e)
    {
        mSource.RemoveHook(WndProc);
        mSource.Dispose();
        mSource = null;
        base.OnClosed(e);
    }
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == (int)WindowsMessage.WM_MOVING)
        {
            // TODO: Substitute realistic bounds
            RECT bounds = new RECT() { Left = 0, Top = 0, Right = 1000, Bottom = 800 };
            RECT window = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT));
            if (window.Left < bounds.Left)
            {
                window.Right = window.Right + bounds.Left - window.Left;
                window.Left = bounds.Left;
            }
            if (window.Top < bounds.Top)
            {
                window.Bottom = window.Bottom + bounds.Top - window.Top;
                window.Top = bounds.Top;
            }
            if (window.Right >= bounds.Right)
            {
                window.Left = bounds.Right - window.Right + window.Left - 1;
                window.Right = bounds.Right - 1;
            }
            if (window.Bottom >= bounds.Bottom)
            {
                window.Top = bounds.Bottom - window.Bottom + window.Top - 1;
                window.Bottom = bounds.Bottom - 1;
            }
            Marshal.StructureToPtr(window, lParam, true);
            handled = true;
            return new IntPtr(1);
        }
        handled = false;
        return IntPtr.Zero;
    }
}

下面是代码中使用的帮助程序对象:

[StructLayout(LayoutKind.Sequential)]
struct RECT
{
    public int Left, Top, Right, Bottom;
}
enum WindowsMessage
{
    WM_MOVING = 0x0216
}

附言LocationChanged事件(以及关联的OnLocationChanged覆盖)被调用以响应WM_MOVE,直到窗口已经移动时才被调用。似乎没有相应的OnLocationChanging事件。