WPF, WinForms, элементы управления ActiveX и мое исчезающее здравомыслие (вызов DragMove () в ответ на событие WinForms Control MouseDown) - PullRequest
2 голосов
/ 18 марта 2011

Как вы уже поняли из названия этого поста, я собираюсь взломать.

Хорошо, вот оно: у меня есть окно WPF, в котором размещается форма WinForms, которая, в свою очередь, содержитэлемент управления ActiveX.Это все из-за устаревших компонентов и желания анимировать непрозрачность прозрачного окна WPF.Разве ты уже не чувствуешь веселья ?!

... Итак, я хотел бы иметь возможность перетаскивать мое прозрачное окно WPF, вызывая DragMove мышью вниз для различных областей окна.Это прекрасно работает, и я могу жить с текущим поведением, но было бы неплохо, если бы я мог также перетаскивать окно через событие MouseDown, сгенерированное моим компонентом WinForms.Итак, я выбрал очевидный подход:

void Init()
{
    MyWinForm form = new MyWinForm();
    form.SomeControl.MouseDown = form_MouseDown;
}

void form_MouseDown( object sender, MouseEventArgs e )
{
    if( e.Button == MouseButtons.Left )
    {
        DragMove();
    }
}

Однако мое приложение аварийно завершает работу со следующим сообщением:

Может вызывать DragMove только тогда, когда основная кнопка мыши нажата.

Да, справа, кроме левой (основной) кнопки - это нажатая кнопка (я понимаю, что это может быть проблематично для левшей, но давайте пока этого не будем).Итак, еще раз, простой код, который работает для события Mouse, сгенерированного элементом управления WPF, завершается ошибкой для System.Windows.Forms.Control.У кого-нибудь есть опыт с этим?Заранее благодарим за любой совет, который вы можете предложить.

TLDR;Вызов DragMove() изнутри события System.Windows.Controls.MouseDown приводит к сбою приложения.Я открыт для любого обходного пути на этом этапе.

Ответы [ 2 ]

2 голосов
/ 18 марта 2011

Глядя на DragMove() код с помощью рефлектора, я пришел к этому решению: мы можем написать или владеть DragMove(IntPtr hWnd), который не выполняет проверку состояния кнопки, но мы должны явно освободить захват мыши в MouseDown обработчике событий.

public static class Utility
{
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr h, int msg, IntPtr lp, IntPtr wp);

    public static void DragMove(IntPtr hwnd)
    {
        const int WM_SYSCOMMAND = 0x112;
        const int WM_LBUTTONUP = 0x202;

        SendMessage(hwnd, WM_SYSCOMMAND, (IntPtr)0xf012, IntPtr.Zero);
        SendMessage(hwnd, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
    }
}

и немного измените ваш обработчик MouseDown:

void form_MouseDown( object sender, MouseEventArgs e )
{
    if( e.Button == MouseButtons.Left )
    {
        // it is necessary to release mouse capture, so that
        // WPF window will be able to capture mouse input
        ((Control)sender).Capture = false;
        // use helper to acquire window handle
        var helper = new System.Windows.Interop.WindowInteropHelper(
            your_window_reference_goes_here);
        Utility.DragMove(helper.Handle);
    }
}

Я не тестировал его с элементами управления ActiveX, но он работает с простым элементом управления WinForms, размещенным в WindowsFormsControlHost по крайней мере на Win7 Ultimate x64.

0 голосов
/ 10 января 2019
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);
        if (e.LeftButton == MouseButtonState.Pressed)
            Window.GetWindow(this).DragMove();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...