Пересылка событий MouseMove дочернего элемента управления без проблем. - PullRequest
2 голосов
/ 07 октября 2011

У меня есть собственный UserControl, который я рисую, используя GDI +.Это прозрачный элемент управления, который рисует маленькие фигуры поверх родительского элемента управления.

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

Чертежная часть работает отлично, но сейчас мне нужно как можно более плавно переслать все события MouseMove, MouseClick и т. д. в родительский элемент управления, ЕСЛИ эти событияпроизошло за пределами фигур.

Формы нарисованы с использованием GraphicsPath, и я уже могу определить, находится ли позиция мыши над формой, с помощью GraphicsPath.IsVisible ().

Я хочу сделатьэто так, что для родительского элемента требуется ноль или минимальный дополнительный код.Родитель не обязательно должен знать, было ли перенаправлено событие MouseMove от дочернего элемента управления, он должен обрабатывать их все одинаково.

Должен ли я сделать это с помощью pinvoke / SendMessage ()?Или есть более простой способ использования .NET Framework?

1 Ответ

6 голосов
/ 08 октября 2011

Это возможно в winapi, оконный менеджер отправляет сообщение WM_NCHITTEST, чтобы спросить, над какой частью элемента управления находится мышь. Что вы можете сделать, это вернуть HTTRANSPARENT, и он попросит родительское окно. Вот пример UserControl, который реализует это. Для перехвата сообщения требуется переопределение WndProc ():

public partial class UserControl1 : UserControl {
    public UserControl1() {
        InitializeComponent();
        paths = new List<GraphicsPath>();
        GraphicsPath example = new GraphicsPath();
        example.AddEllipse(new Rectangle(10, 10, 50, 30));
        paths.Add(example);
    }
    List<GraphicsPath> paths;

    protected override void OnPaint(PaintEventArgs e) {
        foreach (var path in paths) e.Graphics.FillPath(Brushes.Blue, path);
        base.OnPaint(e);
    }

    protected override void WndProc(ref Message m) {
        base.WndProc(ref m);
        // Trap WM_NCHITTEST on the client area
        if (m.Msg == 0x84 && m.Result == (IntPtr)1) {
            Point pos = new Point(m.LParam.ToInt32());
            pos = this.PointToClient(pos);
            bool oncurve = false;
            foreach (var path in paths)
                if (path.IsVisible(pos)) oncurve = true;
            if (!oncurve) m.Result = (IntPtr)(-1);  // HTTRANSPARENT
        }
    }
}

Тестовый код в виде:

    private void userControl11_MouseMove(object sender, MouseEventArgs e) {
        Console.WriteLine("On shape {0}", e.Location);
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e) {
        Console.WriteLine("On form  {0}", e.Location);
    }
...