Передача событий мыши в родительский контроль
-
23-08-2019 - |
Вопрос
Среда:.NET Framework 2.0, VS 2008.
Я пытаюсь создать подкласс определенных элементов управления .NET (метка, панель), которые будут проходить через определенные события мыши (MouseDown
, MouseMove
, MouseUp
) в родительский элемент управления (или, альтернативно, в форму верхнего уровня).Я могу сделать это, создав обработчики этих событий в экземплярах стандартных элементов управления, например:
public class TheForm : Form
{
private Label theLabel;
private void InitializeComponent()
{
theLabel = new Label();
theLabel.MouseDown += new MouseEventHandler(theLabel_MouseDown);
}
private void theLabel_MouseDown(object sender, MouseEventArgs e)
{
int xTrans = e.X + this.Location.X;
int yTrans = e.Y + this.Location.Y;
MouseEventArgs eTrans = new MouseEventArgs(e.Button, e.Clicks, xTrans, yTrans, e.Delta);
this.OnMouseDown(eTrans);
}
}
Я не могу переместить обработчик событий в подкласс элемента управления, поскольку методы, вызывающие события в родительском элементе управления, защищены, и у меня нет квалификатора для родительского элемента управления:
Невозможно получить доступ к защищенному члену
System.Windows.Forms.Control.OnMouseDown(System.Windows.Forms.MouseEventArgs)
через квалификатор типаSystem.Windows.Forms.Control
;квалификатор должен иметь типTheProject.NoCaptureLabel
(или производное от него).
Я рассматриваю возможность переопределить WndProc
метод управления в моем подклассе, но, надеюсь, кто-нибудь сможет дать мне более чистое решение.
Решение
Да.После долгих поисков я нашел статью «Плавающие элементы управления в стиле всплывающей подсказки», который использует WndProc
чтобы изменить сообщение с WM_NCHITTEST
к HTTRANSPARENT
, делая Control
прозрачен для событий мыши.
Для этого создадим элемент управления, унаследованный от Label
и просто добавьте следующий код.
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x0084;
const int HTTRANSPARENT = (-1);
if (m.Msg == WM_NCHITTEST)
{
m.Result = (IntPtr)HTTRANSPARENT;
}
else
{
base.WndProc(ref m);
}
}
Я тестировал это в Visual Studio 2010 с клиентским профилем .NET Framework 4.
Другие советы
Вам нужно написать общедоступный/защищенный метод в базовом классе, который будет вызывать для вас это событие.Затем вызовите этот метод из производного класса.
ИЛИ
Это то, чего ты хочешь?
public class MyLabel : Label
{
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
//Do derived class stuff here
}
}
А WS_EX_TRANSPARENT
расширенный стиль окна действительно делает это (это то, что используют всплывающие подсказки на месте).Возможно, вы захотите применить этот стиль, а не писать множество обработчиков, которые сделают это за вас.
Для этого переопределите CreateParams
метод:
protected override CreateParams CreateParams
{
get
{
CreateParams cp=base.CreateParams;
cp.ExStyle|=0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
Для дальнейшего чтения: