Using Reflection to open a form by name

Here is a quick example of how the System.Reflection namespace can be utilised to open form instances in a method that accepts the form name as a string. It also shows how you can pass across variables to forms with overloaded constructors.

It’s particularly useful when working with a main menu structure, such as I have in a current project loaded into a Treeview.


private void LoadNewForm(string formName)
{
    try
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        Type type = assembly.GetType(formName);

        //for this form I have an overloaded constructor, accepting a 'User' object
        ConstructorInfo ci = type.GetConstructor(new Type[1] { typeof(User) }); 
        object[] argVals = new object[] { CurrentUser };  //pass 'CurrentUser' variable to form constructor
        Form frm = (Form)ci.Invoke(argVals);

        frm.Show();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
} 

Pocket PC – Actually closing a form

You would be forgiven for thinking that clicking on the ‘X’ in the top right of your form would close it, as per all standard Windows applications…but be warned this is NOT the case with Pocket PC applications! I’m not sure what the wisdom is behind this decision, I guess it doesn’t really matter, I just wish it were more obvious!

Anyway, clicking the cross does nothing more than minimise your form, in order to fully close it, you must set it’s ‘MinimizeBox’ property to false. This will in turn display an ‘ok’ button instead of a ‘X’ at the top of your form, and it is clicking this ‘ok’ button that fires the form closing events!…obvious when you think about it!…hmmmmm.

So there’s an hour of my life I’ll never get back! Thanks Microsoft.

Drag and Drop from TreeView

This is pretty straight forward, in the sample code below it shows how to add a TreeView node with an image into a ListBox. You’ll need an ImageList loaded with images to link both the TreeView and ListBox to and set the ListView to a view that allows images, i.e ‘Tile’.

private TreeNode sourceNode;

private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
    sourceNode = (TreeNode)e.Item;

    if (sourceNode.Parent != null)
        DoDragDrop(sourceNode, DragDropEffects.Move);
}

private void DragEnter_Event(object sender, DragEventArgs e)
{
    if (e.Data.GetData(typeof(TreeNode)) != null)
        e.Effect = DragDropEffects.Move;
    else
        e.Effect = DragDropEffects.None;
}

private void listView1_DragDrop(object sender, DragEventArgs e)
{
    listView.Items.Add(sourceNode.Text, sourceNode.ImageIndex);
}

Just add the DragEnter event to the _DragEnter event of the controls you want to allow the DragDropEffects.Move to show on.

Prevent Form being moved

I recently had a need to dock a form to the right hand side of the screen and prevent users from dragging it away. The form can be minimised into the system tray but not resized or moved, of course I could have removed the forms control box and drawn my own but wanted it to fit with the other forms in the project.

Method 1: Override WndProc.

protected override void WndProc(ref Message msg)
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MOVE = 0xF010;

    switch (msg.Msg)
    {
        case WM_SYSCOMMAND:
            int cmd = msg.WParam.ToInt32() & 0xfff0;
    
            if (cmd == SC_MOVE)
                return;
        
            break;
    }

    base.WndProc(ref msg);
}

Method 2: This is the preferred method and allows the form to be dragged onto multiple monitors but will always dock to the right hand side of whichever screen it is dragged to.

private const int scrnBuffer = 5;
private Screen scrn;

private void Form1_Move(object sender, EventArgs e)
{
    SizeForms();
}

private void SizeForms()
{
    scrn = Screen.FromControl(this);

    this.Height = scrn.WorkingArea.Height - scrnBuffer * 2;
    this.Location = new Point(scrn.WorkingArea.Right - this.Width - scrnBuffer, scrn.WorkingArea.Top + scrnBuffer);
}