-1

Im creating winforms c# application with multiple user controls. It's flat application without any borders, so the only way to move windows is by using mouse control events. I used this part of code in my main window, but I cant apply it in any other user controls. I don't want to copy & paste for all user controls, so is there any way to use it?

This code works in my main form, but when i create user control i dont have access to those and i cant wire them up to objects.

    private bool mouseDown;
    private Point lastLocation;

    private void _MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        lastLocation = e.Location;
    }

    private void _MouseMove(object sender, MouseEventArgs e)
    {
        if (mouseDown)
        {
            this.Location = new Point((this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);
            this.Update();
        }
    }
    private void _MouseUp(object sender, MouseEventArgs e)
    {
        mouseDown = false;
    }

Can I make event handler / delegate to solve it?

BrandNew
  • 13
  • 5
  • So, do you want to move the window by mouseclicking/mousemoving on any location? Can't you make a makeshift caption (Title Bar) and move the window just when clicking on it. – Jimi May 25 '19 at 21:59
  • You can choose the existing event handlers from the drop-down in the properties window for the corresponding events (switch to events view by clicking the flash icon). But you could also just do this with the form events. The user would then have to click on the free space between the controls to move the form. – Olivier Jacot-Descombes May 25 '19 at 22:02
  • Possible Duplicate: https://stackoverflow.com/questions/10566617/c-how-to-create-an-event-and-listen-for-it-in-another-class – DCCoder May 25 '19 at 22:33
  • Possible duplicate of [C#, How to create an event and listen for it in another class?](https://stackoverflow.com/questions/10566617/c-how-to-create-an-event-and-listen-for-it-in-another-class) – DCCoder May 25 '19 at 22:33
  • Recursively **SEARCH** for all control types in your form that you are interested in and dynamically wire up their handlers to your existing methods. Change those existing methods (mainly _MouseMove) to cast the **sender** parameter to a control and use that instead of `this.`. – Idle_Mind May 25 '19 at 22:49
  • @Jimi It's a window without title bar, so i decided to move window by using empty space on form – BrandNew May 26 '19 at 00:57
  • @OlivierJacot-Descombes I implemeted those events by clicking flash icon and assigned it to objects that i wanted. The question is how to use it in another form without duplicating code – BrandNew May 26 '19 at 01:07
  • @Idle_Mind This is what I did in the "main form", but without some changes i can't wire up it to another user control form. Could you explain little more how to cast sender parameter to a control? – BrandNew May 26 '19 at 01:08
  • "... but without some changes i can't wire up it to another user control form." Why not? – Idle_Mind May 26 '19 at 01:55
  • User control is just like another form. I cannot access private functions from the main form. I need to delegate it somehow, but the thing is that i don't know how. – BrandNew May 26 '19 at 02:36
  • Give me more to work from. So you have a UserControl, and there are controls within that UserControl that you want to wire up? Is it all controls, or only certain kinds? There are definitely ways to do this; I just need to understand your setup first. – Idle_Mind May 26 '19 at 02:38

2 Answers2

1

Could you explain little more how to cast sender parameter to a control?

Sure:

private void _MouseMove(object sender, MouseEventArgs e)
{
    Control source = (Control)sender; // cast "sender" to a control
    if (mouseDown)
    {
        source.Location = new Point((source.Location.X - lastLocation.X) + e.X, (source.Location.Y - lastLocation.Y) + e.Y);
    }
}

Now whatever control is the "source" of the event will be acted upon (instead of always being the form with "this").

Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • Thanks! Do you know how can i access it from another user control? Cuz its still private function so i need to delegate it somehow.. – BrandNew May 26 '19 at 03:02
1

Here's a helper class that you can pass a Form and a Control Type to and it will wire up all of the controls that match. In this example, all Buttons are wired up so you can drag them around. Just change "Button" to the type of control you're interested in:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        this.WireControlsOfType<Button>();
    }      

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 f2 = new Form2();
        f2.Show();
        f2.WireControlsOfType<Button>();
    }

}

The helper class in a different file:

public static class FormHelper
{

    public static void WireUserControl(this UserControl uc)
    {
        uc.MouseDown += _MouseDown;
        uc.MouseMove += _MouseMove;
        uc.MouseUp += _MouseUp;
    }

    public static void WireControlsOfType<T>(this Control sourceControl)
    {
        foreach(var ctl in sourceControl.RecursiveFindControlsByType<T>())
        {
            ctl.MouseDown += _MouseDown;
            ctl.MouseMove += _MouseMove;
            ctl.MouseUp += _MouseUp;
        }
    }

    // Code by Jon Skeet: https://stackoverflow.com/a/2055946/2330053
    public static IEnumerable<Control> RecursiveFindControlsByType<T>(this Control control)
    {
        foreach (Control c in control.Controls)
        {
            if (c is T)
            {
                yield return c;
            }

            if (c.Controls.Count > 0)
            {
                foreach (Control ctl in c.RecursiveFindControlsByType<T>())
                {
                    yield return ctl;
                }
            }
        }
    }

    private static bool mouseDown;
    private static Point lastLocation;

    private static void _MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        lastLocation = e.Location;
    }

    private static void _MouseMove(object sender, MouseEventArgs e)
    {
        Control source = (Control)sender;
        if (mouseDown)
        {
            source.Location = new Point((source.Location.X - lastLocation.X) + e.X, (source.Location.Y - lastLocation.Y) + e.Y);
        }
    }

    private static void _MouseUp(object sender, MouseEventArgs e)
    {
         mouseDown = false;
    }

}

Note that I'm wiring up Form1 in the Load() event with "this", but I'm also demonstrating it for a new instance of Form2 in the Click() handler.

Additional Post Based on Comment Questions

Based on your comments, here's an example showing the Buttons inside a UserControl being wired up to allow them to be moved around. (I changed the WireControlsOfType<> method to accept generic control instead of Form.) Nothing was changed in the default UserControl properties to allow this:

    private void button1_Click(object sender, EventArgs e)
    {
        panel1.Controls.Clear();

        UserControlA ucA = new UserControlA();
        ucA.Dock = DockStyle.Fill;         
        panel1.Controls.Add(ucA);
        ucA.WireControlsOfType<Button>();
    }

The static FormHelper class is what allows this magic. It can be its own class and does not need to be copied/associated with any of the Forms/UserControls; in fact, it's independent of them and can be in its own file.

If you want the entire UserControl itself to be able to be dragged around its container, I added in a different helper method called WireUserControl() to the helper class above. So the snippet below is adding multiple instances of UserControlA to panel1, and each one could be dragged around separately:

    private void button1_Click(object sender, EventArgs e)
    {
        UserControlA ucA = new UserControlA();        
        panel1.Controls.Add(ucA);
        ucA.WireUserControl();
    }
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • I feel like it's getting too complicated for my basic skills. To make sure that there is no easier way I'll try to clarify my intentions. So I have main form window with side panel to switch between user control forms. I implemented this part of code to move the main window and wired it with mouse events in that form. I would like to do the same for every user control that I have. So should I copy & paste this function to user controls and wire this events or can I somehow write it once and use for every form / user control? – BrandNew May 26 '19 at 15:13
  • Sorry if you already answered this question, maybe im too newbie to implement that and i will stay with copy & paste till I get whats going on here :D – BrandNew May 26 '19 at 15:14
  • It's still a bit unclear to me, however...are you wanting to have controls **within** your UserControls be able to be dragged around? (this is what I'm demonstrating) ...or do you want the **entire** UserControl (whatever one was added to your main form) to be dragged around as a unit? – Idle_Mind May 26 '19 at 15:34
  • See edits added to the bottom of the main post. Hope that helps clear things up and is useful to you. – Idle_Mind May 26 '19 at 15:43