Reputation: 550
I have WPF borderless Transparent window.
By using this.DragMove(); I can successfully move the window.
I wanted to restrict window within screen area. It's also working using below snippet.
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;
}
But using above code, whenever window reach its max bounds using mouse drag, It starts flickering.
Could anybody suggest how to avoid this flickering?
Upvotes: 1
Views: 776
Reputation: 3424
The best way I know to deal with this issue is to handle the WM_MOVING
windows message in your window and adjust the position there. Since the WM_MOVING
message is received before the window actually moves and allows the position to be modified, you never see any jitter. Here is an example code-behind for a 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;
}
}
Here are the helper objects that are used in the code:
[StructLayout(LayoutKind.Sequential)]
struct RECT
{
public int Left, Top, Right, Bottom;
}
enum WindowsMessage
{
WM_MOVING = 0x0216
}
P.S. The LocationChanged
event (and associated OnLocationChanged
override) is called in response to WM_MOVE
, which is not called until the window has already moved. There does not seem to be a corresponding OnLocationChanging
event.
Upvotes: 1