我有WPF无边界透明窗口。
使用this.DragMove();我可以成功地移动窗口。
我想限制屏幕区域内的窗口。 它也使用下面的代码段工作。
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;
}
但是使用上面的代码,每当窗口使用鼠标拖动达到其最大界限时,它就会开始闪烁。
有人可以建议如何避免这种闪烁吗?
答案 0 :(得分:1)
我知道处理此问题的最佳方法是在窗口中处理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
}
P.S。调用LocationChanged
事件(以及关联的OnLocationChanged
覆盖)以响应WM_MOVE
,在窗口已经移动之前不会调用它。似乎没有相应的OnLocationChanging
事件。