无缝地将子控件MouseMove事件转发给父控件
本文关键字:控件 事件 转发 MouseMove | 更新日期: 2023-09-27 18:10:38
我有一个自定义UserControl,我正在使用GDI+绘制。它是一个透明控件,在父控件的顶部绘制小形状。
所有父窗口所做的就是创建控件,给它一个矩形来绘制自己,然后如果用户单击非透明区域,它会接收事件。
绘图部分工作完美,但现在我需要做的是尽可能无缝地将所有的MouseMove, MouseClick等事件转发到父控件,如果这些事件发生在形状之外。
图形是使用GraphicsPath绘制的,并且我已经能够使用GraphicsPath. isvisible()检测鼠标位置是否在图形上方。
我想以一种不需要或最少额外代码的方式在父节点上完成此操作。父控件不必知道是否从子控件转发了MouseMove事件,它应该平等地对待它们。
我必须pinvoke/SendMessage()来做到这一点吗?或者有更简单的方法使用。net框架?
这在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);
}