Тянутся "шлейфы" за окнами внутри MDI-интерфейса при их перемещении
Ради более симпатичного внешнего вида дочерних окон отключил у них "рамку". Теперь перемещением окна управляет следующий код, предварительно запоминая координаты "клика":
private void MoveDocument(object sender, MouseEventArgs e)
{
this.Left += e.X - _mouseClickPoint.X;
this.Top += e.Y - _mouseClickPoint.Y;
}
Включение двойной буферизации ни для дочерней, ни для главной формы не помогает. Со стандартной рамкой у окон такой проблемы не наблюдается.
Ответы (1 шт):
Нашел решение с использованием методов библиотеки "user32.dll":
public static class WindowMovementManager
{
[DllImport("user32.dll")]
private static extern bool ReleaseCapture();
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
private const int Msg = 0xA1; // Код сообщения, определяющий действие. Для перетаскивания окна используется WM_NCLBUTTONDOWN (значение 0xA1), что указывает системе начать обработку "нажатия" на неклиентскую (заголовок) часть окна.
private const int wParam = 0x2; // Дополнительная информация о сообщении. В данном случае это значение HTCAPTION (0x2), чтобы указать системе, что нужно двигать окно за область заголовка, независимо от того, откуда идет перетаскивание.
public static void Move(Form form)
{
ReleaseCapture();
SendMessage(form.Handle, Msg, wParam, 0);
}
}
Для упрощения использования сделал класс статическим. По желанию можно сделать его методом расширения для класса Form, только будет нужно другое имя.
Итого - для перемещения окна нам нужно вызвать данный метод в обработчике события MouseDown (именно в нем - это важно) у интересующего нас компонента, передав ему ссылку на данную форму. Самому методу от формы нужен только дескриптор, так что этот момент можно поменять если нужно.
Таким образом, вызывая данный метод в обработчике события MouseDown для интересующего нас контрола, мы фактически будем имитировать перемещение окна за рамку.