Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Advanced CtrlTab in MDI Form with Preview

3.25/5 (4 votes)
27 Feb 2007CPOL1 min read 1   1.5K  
Advanced CtrlTab in MDI form with preview.

Screenshot - AdvancedCtrlTabDemo.jpg

Introduction

A few weeks ago, I downloaded Vista Business, not from a torrent site, directly from MSDN Academic Alliance Software Center ;-). In Vista, the first thing that everybody takes notice of is the ALT-TAB 'method': if you hold down the CTRL key, you see not only the list of Programs with icons, but you can see a preview of each program too.

It seems difficult at first, but it isn't! So I decided that I implement it in my own "Framework". I made a simple test application to test it and try it, and when I was "finished", I thought I will submit it to CodeProject.

Background

The only thing that we need to do this is to develop an inherited Form, add event handlers, and add some code.

Here is the form:

C#
namespace KBAdvancedCtrlTab    
{    
    public class KBMDIForm:Form 
    { 

    public KBMDIForm() 
    {
         InitializeComponent(); 
        //search the MDIClient Control 
        foreach (Control act in this.Controls) 
        { 
            if (act is MdiClient) 
            { 
                //use the MouseWheel event to show the panel with previews 
                //and scroll between the forms 
                act.MouseWheel += new MouseEventHandler(MdiClient_MouseWheel); 
                break; 
            } 
        } 
        //Initialize the 'Feature 
        InitializeAdvancedCtrlTab(true);    
    }
    private void InitializeComponent() 
    {
        ...
        this.KeyUp += new System.Windows.Forms.KeyEventHandler
                                         (this.KBMDIForm_KeyUp);
        ...
    }
...

The controls and variables we need are listed here:

C#
//the selected(focused) picturePox->Form 
private int intFocusedPicID =-1; 
//the panel size 
private Size sizeAdvCtrlTabPanel = new Size(330, 240); 
//picture box size 
private Size sizeAdvCtrlTabPic = new Size(95, 72); 
//picture box count in one row 
private int intPreviewPicCountInRow = 3; 
//the Preview panel 
private Panel pnlAdvancedCtrlTab = new Panel(); 
//the label that contains the caption of the selected Form 
private Label lblSelectedChildCaption = new Label();

And the two event handler functions:

Here is the KeyUp event that is raised when we activate a form:

C#
private void KBMDIForm_KeyUp(object sender, KeyEventArgs e)
{
    if (ModifierKeys != Keys.Control)
    {
        if (intFocusedPicID == -1)
        {
            return;
        }
        //if the user release the control key we activate the selected Form

        if (this.MdiChildren[intFocusedPicID].WindowState == FormWindowState.Minimized)
        {
            this.MdiChildren[intFocusedPicID].WindowState = FormWindowState.Normal;
        }
        this.MdiChildren[intFocusedPicID].Activate();

        //remove the panel and the label from MDIForm controls
        this.Controls.Remove(pnlAdvancedCtrlTab);
        this.Controls.Remove(lblSelectedChildCaption);
        intFocusedPicID = -1;
    }
}

Here is the MouseWheel event raised when we activate a form:

C#
private void MdiClient_MouseWheel(object sender, MouseEventArgs e)
{
    if (this.MdiChildren.Length > 0)
    {
        //if there is any ChildForm
        if (ModifierKeys == Keys.Control)
        {                 
            //control key is down
            if (!this.Contains(pnlAdvancedCtrlTab))
            {
                //if this is the first time, than mouse wheel scroll
                //so we need the initialize the panel

                //clear all PictureBox
                pnlAdvancedCtrlTab.Controls.Clear();

                //set the position of the pnl
                //it set to be the center of the MDI form
                pnlAdvancedCtrlTab.Location
                              = new Point((int)(this.Width / 2) - 
                               (int)(pnlAdvancedCtrlTab.Width / 2), 
                               (int)(this.Height / 2) - 
                               (int)(pnlAdvancedCtrlTab.Height / 2));

                //the position of the label
                lblSelectedChildCaption.Location
                         = new Point(pnlAdvancedCtrlTab.Location.X, 
                            pnlAdvancedCtrlTab.Location.Y - 50);

                //style...
                pnlAdvancedCtrlTab.BorderStyle = BorderStyle.Fixed3D;
                //if the autosroll property is true and we have lot 
                         of opened childwindow, 
                //the vertical scrollbar automatically appear
                pnlAdvancedCtrlTab.AutoScroll = true;

                //the x-y "index"
                int i = 0;
                int j = 0;
                foreach (Form act in this.MdiChildren)
                {
                    if (i == intPreviewPicCountInRow)
                    {
                        //if we need to change row...
                        i = 0;
                        j++;
                    }

                    //the new picture box
                    PictureBox pc = new PictureBox();
                    //set its size and location
                    pc.Location = new Point(20+i * (sizeAdvCtrlTabPic.Width + 5), 
                              20+j * (sizeAdvCtrlTabPic.Height + 10));
                    pc.Size = sizeAdvCtrlTabPic;
                    //add it to the panel controls collection
                    pnlAdvancedCtrlTab.Controls.Add(pc);

                    //set the image and image size
                    pc.Image = SaveBitmap(act);
                    pc.SizeMode = PictureBoxSizeMode.Zoom;
                    i++;

                    if (act.Focused)
                    {
                        //if it is the foucused ChildWindow set its border to 3d
                        pc.BorderStyle = BorderStyle.Fixed3D;
                        intFocusedPicID = pnlAdvancedCtrlTab.Controls.Count - 1;
                        //set the label to the ChildForm caption
                        lblSelectedChildCaption.Text = act.Text;
                    }
                }

                if (intFocusedPicID == -1)
                {
                    //if there isnt any focused child... we set the first selected
                    intFocusedPicID = 0;
                    (pnlAdvancedCtrlTab.Controls[0] as PictureBox).BorderStyle =
                                            BorderStyle.Fixed3D;
                }
                //add the panel and the textbox to to controls collection of the MDIForm
                this.Controls.Add(pnlAdvancedCtrlTab);
                this.Controls.Add(lblSelectedChildCaption);
            }
            else
            {
                //if it isnt the first mouse scroll

                //set the actual picBox border to default
                (pnlAdvancedCtrlTab.Controls[intFocusedPicID] as
                            PictureBox).BorderStyle = BorderStyle.None;

                //increment,or decrement the selection
                if (e.Delta > 0)
                {
                    intFocusedPicID++;
                    if (intFocusedPicID == pnlAdvancedCtrlTab.Controls.Count)
                    {
                        intFocusedPicID = 0;
                    }
                }
                else if (e.Delta < 0)
                {
                    intFocusedPicID--;
                    if (intFocusedPicID == -1)
                    {
                        intFocusedPicID = pnlAdvancedCtrlTab.Controls.Count - 1;
                    }
                }
                //set the new picBox selected
                (pnlAdvancedCtrlTab.Controls[intFocusedPicID]
                    as PictureBox).BorderStyle = BorderStyle.Fixed3D;
                lblSelectedChildCaption.Text = this.MdiChildren[intFocusedPicID].Text;
            }
        }
    }
}

Using the code

The only thing you need is to inherit your MDI form KBAdvancedCtrlTab.KBMDIForm (or copy the code to your own form):

For example...

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace AdvancedCtrlTabDemo
{
    public partial class DemoApp : KBAdvancedCtrlTab.KBMDIForm
    {
        public DemoApp()
        {
            InitializeComponent();
            newToolStripMenuItem_Click(null, null);
            newToolStripMenuItem_Click(null, null);
            newToolStripMenuItem_Click(null, null);
        }

        private int act_im_index = 0;
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form frm = new Form();
            frm.MdiParent = this;
            frm.BackgroundImage = imageList1.Images[act_im_index];
            act_im_index++;
            if (act_im_index == 4)
            {
                act_im_index = 0;
            }
            frm.Text = "ChildForm - " + this.MdiChildren.Length.ToString();
            frm.Show();
        }
    }
}

Finally

Of course, this isn't the final version, and there can be lots of problem with it, and the design isn't cool... But I think you can use it as a skelton, and customize it the way you want to... I think it's very easy to change the design, the method of changing between the forms (for example, Ctrl + PageUp, mouse-click, etc.), the size of the panel, etc...

History

  • 1.0: Basic operations...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)