Подтвердить что ты не робот

Проходные события мыши для родительского контроля

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

Я пытаюсь создать подкласс определенных элементов управления .NET(label, panel), которые пройдут через определенные события мыши (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 элемента управления в моем подклассе, но, надеюсь, кто-то может дать мне более чистое решение.

4b9b3361

Ответ 1

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

Ответ 2

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

ИЛИ

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

public class MyLabel : Label
{
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        //Do derived class stuff here
    }
}

Ответ 3

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

Чтобы сделать это, переопределите метод CreateParams:

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

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