Передача событий мыши в родительский контроль

StackOverflow https://stackoverflow.com/questions/547172

  •  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;
  }
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top