Как вы, возможно, догадались из названия этого поста, я собираюсь взломать.
Итак, вот оно: у меня есть окно 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
. У кого-нибудь есть опыт в этом? Заранее благодарим за любой совет, который вы можете предложить.
TL; DR; Вызов DragMove()
из события System.Windows.Controls.MouseDown
приводит к сбою приложения. На данный момент я открыт для любого обходного пути.
2 ответа
Посмотрев на код 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.
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (e.LeftButton == MouseButtonState.Pressed)
Window.GetWindow(this).DragMove();
}
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.