[2008] MDI TabControl - Including TabGroups (Now with example!)
Hi,
I have been thinking some time to try to create a MDI TabControl that behaves like the MDI TabControl in the Visual Studio 2008 (probably 2005 too) IDE.
What am I talking about? Here are a few screenshots of the VS2008 IDE doing what my MDI TabControl can do too:
Right-clicking brings up a menu where you can choose to create a new Horizontal or Vertical Tab Group:
http://i42.tinypic.com/65pixi.jpg
After choosing Horizontal, we get two Tab Groups. Right-clicking another Tab now allows you to create another (up to 3) Horizontal Tab Group, or you can move the Tab to the Next or Previous Tab Group:
http://i40.tinypic.com/2vkkboi.jpg
Here is my control in action:
Right-clicking the Tab:
http://i44.tinypic.com/qoissp.jpg
After choosing Horizontal and moving a few more tabs to the bottom Tab Group:
http://i41.tinypic.com/2502df8.jpg
Extra: by specifying the MdiWindowListItem property, my control automatically adds a list of each TabPage text into that Menu Item, just like a MenuStrip does with ordinary MDI Forms:
http://i39.tinypic.com/2r251rp.jpg
There are a few differences, for example, my control supports as many Tab Groups as you like (as long as they are all Horizontal or all Vertical; it does not (yet?) support both at the same time).
Also, in the VS2008 IDE, it is possible to drag tabs from one Tab Group to another. I think I am close to making that work, but it does not work yet so hang on!
So, how does this work?
First of all, I created a blank UserControl called a mdiTabGroupContainer. This container acts as the MdiClient control in an MDI Form application. It holds all the TabGroups and manages many interactions between the user and TabPages / TabGroups etc...
The most important property is the TabGroups property, which is a custom Collection that notifies the container of any changes so they are redrawn correctly; as soon as the TabGroups collection changes, a RedrawTabGroups method is called that draws each TabGroup in the correct place, including a Splitter to make them resizable.
The mdiTabGroup controls are the actual TabGroups (they are just custom TabControls). They handle the ContextMenuStrips and their events.
The mdiTabPage controls are the TabPages belonging to the mdiTabGroups. They are just custom TabPages holding an extra property for the ContextMenuStrip (you can set your own ContextMenuStrip or change the existing ContextMenuStrip if you wish).
Using the control is pretty easy. You need to add one mdiTabGroupContainer to your form (usually it will be Docked to Fill but it doesn't need to be). It will always hold one TabGroup by default, which can be accessed via the MainTabControl property.
Any possible other TabGroups can be accessed using the TabGroups property.
To add TabPages, you will usually use the MainTabControl just like you would use any other TabControl. You use the TabPages property of the MainTabControl.
The mdiTabGroupContainer however also has a TabPages property, which returns ALL the TabPages, from each TabGroup. To get the TabPages from any particular TabGroup you just use the TabGroups property again to get the TabGroup of your liking and use its TabPages property.
It will usually not be necessary to even access the other TabGroups; it is all handled internally. You just add your TabPages to the MainTabControl, and the user can decide which of these TabPages they want to put into a new TabGroup.
Anyway, the control is not finished yet, but I will be updating it when I find the time. It is not ready to be posted yet as I'm still testing it. I am building a quick Tabbed MDI Text Editor application to test the functionality, once that is finished I will post the example here (won't be long!).
2 Attachment(s)
Re: [2008][WIP] MDI TabControl - Including TabGroups
I have finished the example. Note that it is a very crude example, you should not rely on the underlying 'text editor' principles to work 100% accurately. The idea is just to show how my control can be used. See my 'Extensive MDI Text Editor' codebank submission for a much better MDI Text Editor.
I have added the Save/Close/Close All But This/Copy Path and Open Folder ContextMenuStrip items just like the ones used in the Visual Studio IDE. While the Tab Group related ContextMenuStrip items are handled internally, you need to handle each of the new items manually. For that, there are a number of events available in the mdiTabGroupContainer (SaveTabPageContextMenuItemClicked for example). You can retrieve the corresponding TabPage by casting the 'sender' object into an mdiTabPage control, as is shown by my example.
http://i44.tinypic.com/2w1w39l.jpg
I have attached the MDI Text Editor example.
Because this example forced me to add a few subtle things (such as an RichTextBox to the tabpage) I have also added the 'blank' controls in the 'SeparateControls' zip file:
- mdiTabGroupContainer
- mdiTabGroup
- mdiTabPage
(These are therefore not exactly the same as used in the example!)
------------------------------------------
Usage of this control is pretty straightforward:
Drop an mdiTabGroupContainer on your form.
It will always have at least one TabGroup, which can be accessed using the MainTabControl property.
Adding tabs, setting the SelectedTab, and things like that, can therefore usually be done via myMdiTabGroupContainer.MainTabControl.TabPages
, myMdiTabGroupContainer.MainTabControl.SelectedTab etc.
You can treat the MainTabControl property as just being a TabControl on your form.
For easy access, the Container control also has a TabPages property. You should not add or remove pages from this property. This is just a property that returns a collection of ALL TabPages, no matter in which TabGroup they currently reside.
For more information, see the attached example.
If you have a question, if something is not clear, if something does not function properly, and especially if I did something wrong, don't hesitate to ask/tell me about it!
Enjoy.
Re: [2008] MDI TabControl - Including TabGroups (Now with example!)
Hi Nick,
too bad, that your Tabcontrol hasn't the X-closing functionality of tabs like in the VS-IDE...
Regards
Dietrich
Re: [2008] MDI TabControl - Including TabGroups (Now with example!)
I believe there is another codebank thread that deals with closing buttons on the tabs, perhaps you can mix the two examples? If I remember correctly, this example adds actual Button controls to the tabs.
I did briefly consider adding close buttons to my VS2010 themed TabControl, and got it working for about 80% I guess. Since the tabs are custom drawn I could simply draw the close buttons manually on the tab and handle mouse events on them (by checking if the mouse is inside the close button rectangle). It worked except for two problems:
- It requires custom TabPage controls which quickly becomes a mess in the designer
- The tabs need to be wider to accomodate the button, and I've tried a number of ways to do that but none seem to work in each case...