Сквозные события мыши для родительского контроля - PullRequest
31 голосов
/ 13 февраля 2009

Среда: .NET Framework 2.0, VS 2008.

Я пытаюсь создать подкласс определенных элементов управления .NET (метка, панель), которые будут проходить через определенные события мыши (MouseDown, MouseMove, MouseUp) к его родительскому элементу управления (или в качестве альтернативы верхнему форма) Я могу сделать это, создав обработчики для этих событий в экземплярах стандартных элементов управления, например ::1006

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 метод управления в моем подклассе, но, надеюсь, кто-нибудь может дать мне более чистое решение.

Ответы [ 3 ]

64 голосов
/ 26 декабря 2011

Да. После долгих поисков я нашел статью "Плавающие элементы управления в стиле всплывающей подсказки" , в которой 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.

3 голосов
/ 13 февраля 2009

Расширенный стиль окна WS_EX_TRANSPARENT фактически делает это (это то, что используют всплывающие подсказки на месте). Возможно, вы захотите применить этот стиль, а не писать множество обработчиков, чтобы сделать это за вас.

Для этого переопределите метод CreateParams:

protected override CreateParams CreateParams
{
  get
  {
    CreateParams cp=base.CreateParams;
    cp.ExStyle|=0x00000020; //WS_EX_TRANSPARENT
    return cp;
  }
}

Для дальнейшего чтения:

3 голосов
/ 13 февраля 2009

Вам нужно написать открытый / защищенный метод в вашем базовом классе, который вызовет событие для вас. Затем вызовите этот метод из производного класса.

OR

Это то, что вы хотите?

public class MyLabel : Label
{
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        //Do derived class stuff here
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...