Way to make a Windowless WPF window draggable without getting InvalidOperationException
Asked Answered
P

4

9

I have a borderless WPF main window. I'm trying to make it so that the end user can drag the window.

I've added the following to the Window's constructor:

this.MouseLeftButtonDown += delegate { DragMove(); };

The problem is, I have a dialog box that opens up with two buttons. When I click one of these buttons, I get an InvalidOperationException unhandled with the message "Can only call DragMove when the primary mouse button is down."

This poses a few questions: Why would a mousedown event in a dialog have anything to do with this? How can I do this without this exception?

Thanks!

Polestar answered 18/7, 2010 at 2:31 Comment(1)
I also have border less windows with buttons and let the user drag it by pressing left mouse button and it works fine. Please provide a minimal but complete code sample showing this behavior.Probability
P
8

The 'correct' way to make a borderless window movable is to return HTCAPTION in the WM_NCHITTEST message. The following code shows how to do that. Note that you will want to return HTCLIENT if the cursor is over certain of your Window's visual elements, so this code is just to get you started.

http://msdn.microsoft.com/en-us/library/ms645618(VS.85).aspx

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(this);
        hwndSource.AddHook(WndProcHook); 
        base.OnSourceInitialized(e);
    }

    private static IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
    {
        if (msg == 0x0084) // WM_NCHITTEST
        {
            handeled = true;
            return (IntPtr)2; // HTCAPTION
        }
        return IntPtr.Zero;
    }
}
Piet answered 18/7, 2010 at 13:37 Comment(2)
If you try to "return HTCAPTION in the WM_NCHITTEST message" as Tergiver suggests, then the buttons will not be clickable i.e. the click event will not work for the buttons. Does anyone have a workaround for this?Eleanoreleanora
Note that I stated that that code was only a starting point. You cannot return HTCAPTION for the entire rectangle of your window as the code above does. You have to decide what area(s) of your window should not be 'caption' areas. This might be as simple as a rectangle in your control area, or as complex as walking the visual tree and looking for controls.Piet
E
1

Set the MouseDown atrribute of the window or any other control you want to use:

<TextBlock Grid.Column="0" HorizontalAlignment="Stretch"  MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" >Handy Dandy</TextBlock>

And implement it in the code behind like this:

private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
     this.DragMove();
}

From: http://www2.suddenelfilio.net/2007/01/19/wpf-draggable-windowless-windows/

Efferent answered 13/3, 2012 at 17:8 Comment(0)
H
0

There is a Microsoft project that handles all the "windowless" style and much more, and it is opensource, you might want to take a look at http://code.msdn.microsoft.com/WPFShell. I am using on a commercial financial application, and hasn't run into any issues on any version of windows yet.

Heath answered 29/8, 2010 at 14:13 Comment(0)
R
0

you can override the original method:

 public new void DragMove()
     {
        if (this.WindowState == WindowState.Normal)
        {
            SendMessage(hs.Handle, WM_SYSCOMMAND, (IntPtr)0xf012, IntPtr.Zero);
            SendMessage(hs.Handle, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
        }
    }
Ruskin answered 27/7, 2012 at 16:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.