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;
}
但是使用上面的代码,每当窗口使用鼠标拖动达到其最大边界时,它就会开始闪烁。
有人可以建议如何避免这种闪烁吗?
我知道处理
此问题的最佳方法是处理窗口中的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
事件。