1

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

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

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 的方法。看起来我可以按照建议订阅单独的方法,或者我需要正确传递正确的控件,即不是发送者作为控件。有任何想法吗?

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

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

然后在将按钮订阅到我的 mouseup、down 和 move 之前,它会运行这些方法。

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

注意:第三次订阅是他们之前的样子(匿名代表)。我相信我需要在事件中通过正确的控制。这是否让我的问题更加清晰?

4

2 回答 2

2

回答这个问题:

但是,在本节中,我收到错误“非静态字段、方法或属性“blah blah.OnMouseDown”需要 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 
   } 
}
于 2012-06-08T10:38:50.977 回答
1

你应该写:

control.MouseDown += new MouseEventHandler(MouseDownEvent);

注意这里必须更改 MouseDownEvent 的签名,因为 Control 的 MouseDown 事件只需要 sender 和 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);

编辑2:

我没有指定它,但这里发生的是每次在传递给 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);,但我不认为它会起作用。

于 2012-06-08T10:44:54.877 回答