无法创建自定义事件处理程

时间:2012-06-08 10:27:42

标签: c# events parameters

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

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

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.

然而,在本节中,我收到错误“非静态字段,方法或属性需要一个参考值”blah blah.OnMouseDown“”

最后继承我的方法我试图在mouseDown上订阅;

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:
如果我没有传递正确的控件,那么mouseDown和mouseUp将不起作用,至少订阅我以前做过的方式。我可以尝试你的方法,但是,我这样做的方式我只是调用一个订阅所有3个MouseControls的方法。它看起来像我可以在sepearate方法中订阅建议,或者我需要正确地传递正确的控制,即不是发送者作为控制。任何想法?

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

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

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

2 个答案:

答案 0 :(得分:2)

回答这个问题:

  

然而,在这部分我得到的错误“一个参考是   非静态字段,方法或属性所需要的“等等   blah.OnMouseDown “”

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

答案 1 :(得分:1)

你应该写:

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);

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

编辑:

如果您正在尝试实现一个管理控件移动的类,您可以使用包含以下内容的Helper类:

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

现在,您可以从Helper外部订阅OnMouseDown原始方法:

Helper.OnMouseDown += new MouseDown(MouseDownEvent);

EDIT2:

我没有指定它,但是这里发生的是每次在传递给Init的其中一个控件上有一个MouseDown事件(我的意思是windows事件)时会触发OnMouseDown事件。这意味着OnMouseDown的注册只需要进行一次。之后,每次在其中一个控件上有MouseDown时,会通过以下参数执行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);,但我不认为它会起作用。