Способ сделать окно без окон WPF перетаскиваемым без получения InvalidOperationException

У меня есть окно меньше основного окна WPF. Я пытаюсь сделать так, чтобы конечный пользователь мог перетащить окно.

Я добавил следующее в конструктор окна:

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

Проблема в том, что у меня есть диалоговое окно, которое открывается с двумя кнопками. Когда я нажимаю одну из этих кнопок, я получаю InvalidOperationException, необработанное с сообщением "Может вызывать DragMove только тогда, когда основная кнопка мыши нажата".

Это ставит несколько вопросов: почему событие mousedown в диалоге как-то связано с этим? Как я могу сделать это без этого исключения?

Спасибо!

4 ответа

"Правильный" способ сделать окно без полей подвижным - это вернуть HTCAPTION в сообщении WM_NCHITTEST. Следующий код показывает, как это сделать. Обратите внимание, что вы захотите вернуть HTCLIENT, если курсор находится над определенными визуальными элементами вашего Window, поэтому этот код только для начала.

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;
    }
}

Установите атрибут MouseDown окна или любого другого элемента управления, который вы хотите использовать:

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

И внедрите это в коде так:

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

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

Вы можете переопределить оригинальный метод:

 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);
        }
    }

Есть проект Microsoft, который обрабатывает все "безоконный" стиль и многое другое, и он с открытым исходным кодом, вы можете взглянуть на http://code.msdn.microsoft.com/WPFShell. Я использую коммерческое финансовое приложение, и еще не сталкивался с какими-либо проблемами ни в одной версии Windows.

Другие вопросы по тегам