创建自定义事件处理程序时遇到问题

本文关键字:遇到 问题 程序 自定义 事件处理 创建 | 更新日期: 2023-09-27 18:36:30

我一直在尝试创建自定义事件来处理鼠标控件等,但我不断遇到某些教程似乎都没有解决的错误。我很确定我的创建/分配逻辑是正确的,但也许我在这里缺少一些根本错误。

首先,我使用与方法相同的签名创建我的委托;

public delegate void MouseDown(object sender, MouseEventArgs e, Control control);

然后我把它分配给我的事件;

public event MouseDown OnMouseDown;

最后我尝试订阅该活动;

public static void Init(Control control, Control container, Direction direction)
{
    control.MouseDown += OnMouseDown;
}
//ignore the parameters I'm passing, these are out of the scope of my problem.

但是,在本节中,我收到错误"非静态字段、方法或属性需要 ohject 引用"等等。鼠标向下"

最后这是我尝试在鼠标向下订阅的方法;

public void MouseDownEvent(object sender, MouseEventArgs e, Control control)
{
    Dragging = true;
    DragStart = new Point(e.X, e.Y);
    control.Capture = true;
}

我尝试修改我在某处找到的帮助程序类可能无济于事。如果需要任何进一步的信息,请随时询问。

注意:此类的主要目标是允许在运行时移动控件。

编辑:

我相信前两个已经奏效,但是要移动我需要使用以下方法;

public void MouseMoveEvent(object sender, MouseEventArgs e, Control control, Control container, Direction direction)
{
     if (Dragging)
    {
        if (direction != Direction.Vertical)
            container.Left = Math.Max(0, e.X + container.Left - DragStart.X);
        if (direction != Direction.Horizontal)
            container.Top = Math.Max(0, e.Y + container.Top - DragStart.Y);
    }
}

所以我需要发送方向方向,我不能作为发件人发送。我对整个系统进行这些更改的原因是,我在使用匿名委托之前让它工作,但是当我想重新锁定控件时,这些更改很难取消订阅。

编辑 2:
刮擦一下,如果我没有传递正确的控件,鼠标向下和鼠标向上将无法工作,至少订阅我以前的方式。我可以尝试您的方法,但是,我这样做的方式只是调用了一个订阅所有 3 个鼠标控件的方法。看起来我可以按照建议订阅单独的方法,或者我需要正确传递正确的控件,即不是发件人作为控件。有什么想法吗?

目前,我正在通过从任何地方运行此方法来订阅;

helper.Init(this.Controls["btn" + i]);

然后它通过这些方法运行,然后订阅我的鼠标向上,向下和移动按钮。

public static void Init(Control control)
{
    Init(control, Direction.Any);
}
public static void Init(Control control, Direction direction)
{
    Init(control, control, direction);
}
public static void Init(Control control, Control container, Direction direction)
{
    control.MouseDown += new MouseEventHandler(FireOnMouseDown);
    control.MouseUp += new MouseEventHandler(FireOnMouseUp);
    control.MouseMove += delegate(object sender, MouseEventArgs e)
    {
        if (Dragging)
        {
            if (direction != Direction.Vertical)
                container.Left = Math.Max(0, e.X + container.Left - DragStart.X);
            if (direction != Direction.Horizontal)
                container.Top = Math.Max(0, e.Y + container.Top - DragStart.Y);
        }
    };
}

注意:第三次订阅是他们之前的样子(匿名代表)。我相信我需要在事件中传递正确的控制。这是否更清楚地说明了我的问题?

创建自定义事件处理程序时遇到问题

回答这个问题:

但是在本节中,我收到错误"ohject 引用是 非静态字段、方法或属性"等等"所必需的 等等。鼠标向下"

Init方法是静态的,这意味着其中使用的任何非局部变量都必须是静态的。在代码中,public event MouseDown OnMouseDown;必须是静态的。

只需这样做,它将正常工作(无需委托):

编辑请参阅下面的代码,了解如何获取已单击的控件。

public static void Init(Control control, Control container, Direction direction)
{
   control.MouseDown += new System.Windows.Forms.MouseEventHandler(On_MouseDown);;
}
private static void On_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)       
{     
   Control control = sender as Control;
   if(control != null){
       // Here we go, use the control to do whatever you want with it 
   } 
}

你应该写:

control.MouseDown += new MouseEventHandler(MouseDownEvent);

请注意,您必须在此处更改 MouseDownEvent 的签名,因为 Control 的 MouseDown 事件只需要发送方和 MouseEventArgs 作为参数。

但我不确定这是否是你真正想要的。此指令的效果是,当鼠标按下控件时,将执行 MouseDownEvent。这是你想要的吗?

指令public event MouseDown OnMouseDown;是不可理解的,除非在出现此问题的同一类中的某个地方,您不会以这种方式编写触发此事件的内容:

if (OnMouseDown!= null)
   OnMouseDown(aSenderObject, aMouseEventArgs, aControl);

要订阅thgis事件,您应该编写以下内容(此处hc anObj是定义事件的类的实例):

anObj.OnMouseDown+= new MouseDown(MouseDownEvent);

希望对您有所帮助。也许更多的背景可能会有用。

编辑:

如果尝试实现管理控件移动的类,则可以使用包含以下内容的帮助程序类:

public delegate void MouseDown(object sender, MouseEventArgs e, Control control);
public static event MouseDown OnMouseDown;

如果您希望能够将控件"注册"到您的类,这就是执行此操作的方法(请注意,事件是静态的)。在这里,您说当鼠标按下控制时,FireMouseDown 被执行。

public static void Init(Control control, Control container, Direction direction)
    {
        control.MouseDown += new MouseEventHandler(FireOnMouseDown);
    }

在FireMouseDown中,你必须使用正确的参数触发OnMouseEvent:

public static void FireOnMouseDown(object sender, MouseEventArgs e)
    {
        if (OnMouseDown != null)
            OnMouseDown(this, e, sender as Control);
    }

现在,您可以从帮助程序外部订阅原始方法的OnMouseDown:

Helper.OnMouseDown += new MouseDown(MouseDownEvent);

编辑2:

我没有指定它,但这里发生的事情是,每次在传递给 Init 的控件之一上出现 MouseDown 事件(我的意思是 Windows 事件)时,都会触发 OnMouseDown 事件。这意味着注册到OnMouseDown只需要完成一次。之后,每次您在这些控件之一上具有鼠标按下时,都会执行 MouseDownEvent 并传递以下参数:

sender -> the Helper class
e -> the original MouseEventArgs generated by Windows
control -> the control that generated the original event

关于 MouseMove 事件,您应该像 MouseDown 一样做一些事情,只需添加您需要的额外参数(即使我不清楚容器和方向的含义是什么,因为似乎容器总是等于控制和方向总是 Direction.Any)。我的意思是这样的:

public delegate void MouseMove(object sender, MouseEventArgs e, Control control, Control container, Direction direction);
public static event MouseMove OnMouseMove;
public static void FireOnMouseMove(object sender, MouseEventArgs e) 
{ 
    if (OnMouseMove != null) 
        OnMouseMove(this, e, sender as Control, aContainer, aDirection); 
}

我不明白的是,您将从哪里找到aContainer和aDirection。如果我应该复制你的 Init,我会写OnMouseMove(this, e, sender as Control, sender as Control, Direction.Any);,但我认为它不起作用。