简体   繁体   中英

trouble creating custom event handler

I've been trying to get my head around creating a custom event to handle mouse controls and such, but i keep running into certain errors that none of the tutorials seem to address. I'm pretty sure my logic of creation / assigning is correct, but maybe theres something fundamentally wrong that I'm missing here.

First off i create my delegate with the same signature as the method;

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

And then i assign it my event;

public event MouseDown OnMouseDown;

and then finally i try and subscribe to the event;

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.

However on this section I'm getting the error "an ohject reference is required for the non-static field, method, or propery "blah blah.OnMouseDown""

Finally heres my method I'm trying to subscribe to on mouseDown;

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

It probably doesn't help that I'm trying to modify a helper class i found somewhere. If any further information is needed feel free to ask.

Note: The prime objective of this class is to allow controls to be moved at runtime.

Edit:

I believe the first two have worked, but to move i need to use the following method;

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

so i need to send Direction direction, which i can't send as sender. The reason I'm making these changes to the whole system is, i had it working before using anonymous delegates, but these proved tough to unsubscribe from when i wanted to re-lock a control in place.

Edit 2:
scratch that, the mouseDown and mouseUp won't work if i don't pass the correct control, at least subscribing the way i was doing it before. i could try your method but, the way i was doing it i was just calling one method which subscribed to all 3 MouseControls. it looks like either i can subscribe in sepearate methods as suggest, or i need to pass the right control correctly, ie not sender as control. any ideas?

Currently I'm subscribing by running this method from anywhere;

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

and then it runs through these methods before subscribing the button to my mouseup, down and 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);
        }
    };
}

Note: the third subscription is how they were before (anon delegates). I believe i need to pass the correct control in the events though. Does this give more clarity to my problem?

Answer to this question:

However on this section i'm getting the error "an ohject reference is required for the non-static field, method, or propery "blah blah.OnMouseDown""

Init method is static which means that any non local variable used inside it must be static. In your code, the public event MouseDown OnMouseDown; must be static.

Just do this and it will work fine (without the need for a delegate):

EDIT Please see code below to see how to get the control that has been clicked.

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

You should write:

control.MouseDown += new MouseEventHandler(MouseDownEvent);

Be careful here that you must change the signature of MouseDownEvent, here, since the MouseDown event of Control needs only the sender and the MouseEventArgs as parameters.

But I'm not sure if this is what you really want. The effect of this instruction is that when the mouse goes down on the control MouseDownEvent is executed. Is this what you want?

The instruction public event MouseDown OnMouseDown; is unesuful unless somewhere in the same class where this appears you do not write something that fires this event in this way:

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

And to subscribe to thgis event you should write this (here hc anObj is an instance of the class where the event is defined):

anObj.OnMouseDown+= new MouseDown(MouseDownEvent);

Hope it helps. Maybe a little more context could be useful.

EDIT:

If you are trying to implement a class that manages the movement of controls you could have the Helper class that contains:

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

If you want to be able to "register" a control to your class this is the way to do it (note that the event is static). Here you say that when the mouse goes down on control, FireMouseDown is executed.

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

In FireMouseDown you have to fire the OnMouseEvent with the right arguments:

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

Now you can subscribe to OnMouseDown your original method from outside Helper:

Helper.OnMouseDown += new MouseDown(MouseDownEvent);

EDIT2:

I didn't specify it, but what's happening here is that the OnMouseDown event is fired everytime there is a MouseDown event (the windows event, I mean) on one of the controls that were passed to Init. This means that the registration to OnMouseDown has to be done only once. After that, every time you have a MouseDown on one of these controls MouseDownEvent is executed passing these parameters:

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

With regard to the MouseMove event, you should do something like for MouseDown, just adding the extra parameters you need (even if it's not clear to me what is the meaning of container and direction, since it seems that container is always equal to control and direction is always Direction.Any). I mean something like:

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

What I don't understand here is from where you are going to find out aContainer and aDirection. If I should replicate your Init I would write OnMouseMove(this, e, sender as Control, sender as Control, Direction.Any); , but I don't think that it would work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM