Как сделать Я делаю окно WPF подвижным, перетаскивая фрейм расширенного окна?

В таких приложениях, как Windows Explorer и Internet Explorer, можно захватить области расширенного фрейма под строкой заголовка и перетащить окна.

Для приложений, форм и элементов управления WinForms максимально приближены к собственным Win32 API; можно просто переопределить обработчик WndProc () в их форме, обработать сообщение окна WM_NCHITTEST и обмануть систему, заставив ее думать, что щелчок по области фрейма на самом деле был щелчком по строке заголовка, возвращая HTCAPTION . Я сделал это в своих собственных приложениях WinForms, чтобы добиться восхитительного эффекта.

В WPF я также могу реализовать аналогичный метод WndProc () и привязать его к дескриптору окна WPF, расширяя рамку окна до клиентской области, например:

// In MainWindow
// For use with window frame extensions
private IntPtr hwnd;
private HwndSource hsource;

private void Window_SourceInitialized(object sender, EventArgs e)
{
    try
    {
        if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero)
        {
            throw new InvalidOperationException("Could not get window handle for the main window.");
        }

        hsource = HwndSource.FromHwnd(hwnd);
        hsource.AddHook(WndProc);

        AdjustWindowFrame();
    }
    catch (InvalidOperationException)
    {
        FallbackPaint();
    }
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    switch (msg)
    {
        case DwmApiInterop.WM_NCHITTEST:
            handled = true;
            return new IntPtr(DwmApiInterop.HTCAPTION);

        default:
            return IntPtr.Zero;
    }
}

Проблема в том, что, поскольку я вслепую устанавливаю handled = true и возвращаю HTCAPTION , щелкая где угодно кроме значок окна или кнопки управления вызывают перетаскивание окна. То есть все, что ниже выделено красным, вызывает перетаскивание. Сюда входят даже ручки изменения размера по бокам окна (неклиентская область). Мои элементы управления WPF, а именно текстовые поля и вкладка, в результате также перестают получать клики:

Я хочу только

  1. строку заголовка и
  2. области клиентской области ...
  3. . .. которые не заняты моими элементами управления

, чтобы их можно было перетащить. То есть я хочу, чтобы перетаскивались только эти красные области (клиентская область + строка заголовка):

Как мне изменить мой метод WndProc () и остальную часть XAML / кода программной части моего окна, чтобы определить, какие области должны возвращать HTCAPTION , а какие нет? Я думаю о чем-то вроде использования Point s для проверки местоположения щелчка по местоположению моих элементов управления, но я не уверен, как это сделать в среде WPF.

РЕДАКТИРОВАТЬ [4/24]: один простой способ - иметь невидимый элемент управления или даже само окно, ответьте на MouseLeftButtonDown , вызвав DragMove () в окне (см. ответ Росс ). Проблема в том, что по какой-то причине DragMove () не работает, если окно развернуто, поэтому это не очень хорошо работает с Windows 7 Aero Snap. Поскольку я собираюсь интегрировать Windows 7, в моем случае это неприемлемое решение.

52
задан Community 23 May 2017 в 00:29
поделиться