c# Перемещение формы, на которую добавлен UserControl
Всем привет. У меня есть UserControl (обычный TitleBar). Этот UserControl находится на MainForm (BorderStyle - none). В чём собственно проблема - при клике на этот UserControl, который находится в Форме, она должна перемещаться, как и любая другая форма, которая имеет границы, вместе с этим TitlePanel. Я попытался это реализовать. Ниже код, который находится в UserControl:
private const int WM_NCLBUTTONDOWN = 0xA1;
private const int HT_CAPTION = 0x2;
public void TitlePanel_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
[DllImport("user32.DLL", EntryPoint = "ReleaseCapture")]
private extern static void ReleaseCapture();
[DllImport("user32.DLL", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
Но прикол в том, что двигается только собственно сам UserControl, а не форма вместе с ним. Пробовал по-разному гуглить, но как-то всё очень грустно.
Да, конечно, можно всё реализовать тупо в лоб: для каждой формы копировать и вставлять этот TitleBar в каждую форму, все ивенты, переменные настраивать в каждой форме, но это больше похоже на очень некрасивую реализацию или даже костыль. Может можно как-то всё-таки передавать информацию о клике на TitlePanel в основную форму и двигать их вместе?
Ответы (1 шт):
Тут winapi вообще не нужен. Указатель захватывается сам во время drag-n-drop'а и с этим ничего делать не надо. Надо просто двигать саму форму в обработчике MouseMove.
А чтобы посчитать, что именно двигать, надо подняться наверх по цепочке Parentов.
Что-то такое:
private Form form;
private int baseLeft;
private int baseTop;
private void TitlePanel_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
for (var x = this.Parent; x != null; x = x.Parent)
{
if (x is Form f)
{
form = f;
baseLeft = f.Left - e.X;
baseTop = f.Top - e.Y;
break;
}
}
}
}
private void TitlePanel_MouseMove(object sender, MouseEventArgs e)
{
if (form != null)
form.Location = new Point(baseLeft + e.X, baseTop + e.Y);
}
private void TitlePanel_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
form = null;
}
А ещё мне что-то вспоминается, что надо не подписываться на события, а переопределять методы on*.