Best way to have a tabbed MDI application

  • Thread starter Mac via DotNetMonster.com
  • Start date
M

Mac via DotNetMonster.com

Hi all,

As some of you would know from my previous posts that I am rewriting our Unix
based system into .Net with a MDI interface.

Recently I have added a tab control to the top of the MDI parent form that
will contain a tab page for each open MDI child form. It is only 24 pixels
high so all you see is the tabstrip. Then I only have to add a bit of code to
the "changed index" event of the tab control as well as the "on activate"
event for the child forms (which is actually done on a baseform which is
inherited by all the child forms) to ensure that if either a tab is clicked
or another child form is activated then the current child form and current
tab are in sync.

Nothing too complicated here, but I am currently tossing up whether to
actually do away with having MDI child forms and just create all the intended
child forms as user controls which when required are inserted onto a new tab
page. But I am unsure if this is going to create headaches for me in managing
tab pages rather than MDI child forms.

The problem I have with an MDI app is preventing the users from changing the
state of the child form - I would like to have it maximised all the time. Is
there way to prevent the control box in the upper right corner of the MDI
form from being displayed?

Anyway, it would be great if people could share their experiences on tabbed
MDI applications so I can be aware of any pitfalls before I make the decision.


tia,

Mac
 
J

Jeff Jarrell

Mac,

I did this and I thought it worked out pretty well. Use the tab control,
then instantiate each form setting its parent to the tab page. You take the
boder off, set the dock to fill and there you go.

something like this...
dim fObjSelector as frmObjectSelector
fObjSelector = New frmObjectSelector
fObjSelector.FormBorderStyle = FormBorderStyle.None
fObjSelector.TopLevel = False
fObjSelector.Parent = Me.FromHandle(TabControl1.TabPages(0).Handle)
fObjSelector.Dock = DockStyle.Fill
fObjSelector.Show()

jeff
 
C

Cor Ligthert [MVP]

Mac,

Go first sit on the chair of your user.

Imaging that are using word and instead of that it is a MDI application as
it is, you have extended it with a Tab control where in can be all your
documents that are open.

I become already confused if I have 4 mdi doc files open in Word direct on
my screen. While you want to hide them even in tabpages.

I hope that this gives you an idea.
To give an exact answer, it is in my opinion a MDI or a Tab page, not both.

For me is a technical nice solution is not always a good user solution.

Just my thought,

Cor
 
M

Mac via DotNetMonster.com

Hi Jeff,

I am having difficulty trying to reproduce your solution. If I understand
correctly, it appears as though you have a form which you are slotting in as
a tabpage, which means you don't actually set the MDIParent property of these
forms at all? Is this correct?

And your frmObjectSelector is of type form? Also where exactly is this code
placed - in your container form? Even though I know they exist, I cannot
access the Me.Fromhandle property or the TopLevel property.

Can you give me some further info on how you got this solution going - I
really like the sound of it. It if it behaves like it I think it will, it
will overcome the issue I had (and Cor pointed out) of having a detached
tabcontrol and MDI forms.


regards,

Mac

Jeff said:
Mac,

I did this and I thought it worked out pretty well. Use the tab control,
then instantiate each form setting its parent to the tab page. You take the
boder off, set the dock to fill and there you go.

something like this...
dim fObjSelector as frmObjectSelector
fObjSelector = New frmObjectSelector
fObjSelector.FormBorderStyle = FormBorderStyle.None
fObjSelector.TopLevel = False
fObjSelector.Parent = Me.FromHandle(TabControl1.TabPages(0).Handle)
fObjSelector.Dock = DockStyle.Fill
fObjSelector.Show()

jeff
[quoted text clipped - 37 lines]
 
M

Mac via DotNetMonster.com

Thanks for that Cor - I think I got your point (actually I kinda feel like
Neo after a visit to the Oracle - I need a cookie!! :)

My concerns with having a tabfolder with all the forms as tab pages rather
than an MDI was that I would lose all the functionality that goes with forms?
Is this something I shouldn't be concerned about? Also being able to merge
the menu of the child form into that of the MDI parent is something that is
going to be handy for us. Is there a way to get around this?

I suppose what I would like is the best of both worlds, but in the end I may
just have to choose. But this a decision I am kinds dreading having to make
as it will determine the whole make up of the application!!

How have you seen the tab setup work because I really think this is way I
want to go. Just having MDI forms I think is a bit "old" and the users cannot
see what all the screens are that they have opened. I suppose also with the
tab setup I am trying to reproduce something similar to how Lotus Note is
setup.

Any thoughts appreciated

Mac
Mac,

Go first sit on the chair of your user.

Imaging that are using word and instead of that it is a MDI application as
it is, you have extended it with a Tab control where in can be all your
documents that are open.

I become already confused if I have 4 mdi doc files open in Word direct on
my screen. While you want to hide them even in tabpages.

I hope that this gives you an idea.
To give an exact answer, it is in my opinion a MDI or a Tab page, not both.

For me is a technical nice solution is not always a good user solution.

Just my thought,

Cor
[quoted text clipped - 37 lines]
 
J

Jeff Jarrell

Mac,

You have a MainForm that has a tab control. You have more forms in the
project that you will instantiate and insert into each tab page (where the
tab page the owner of the form. Most likely you'd put the sample code into
the form load of the MainForm. Nothing is marked as special like MDI
parent.

The seven lines of code would occur for each form you insert (or you would
generalize this.

frmObjectSelector is a form with controls and stuff on it. nothing special.

I have used this techique to on complex forms to split out complexity into a
number of smaller forms (so multiple developers can work on it) rather than
a single, big, complex, monolithic form.

If you are still having problems let me know and i will get extract a
working sample for you.

jeff

Mac via DotNetMonster.com said:
Hi Jeff,

I am having difficulty trying to reproduce your solution. If I understand
correctly, it appears as though you have a form which you are slotting in
as
a tabpage, which means you don't actually set the MDIParent property of
these
forms at all? Is this correct?

And your frmObjectSelector is of type form? Also where exactly is this
code
placed - in your container form? Even though I know they exist, I cannot
access the Me.Fromhandle property or the TopLevel property.

Can you give me some further info on how you got this solution going - I
really like the sound of it. It if it behaves like it I think it will, it
will overcome the issue I had (and Cor pointed out) of having a detached
tabcontrol and MDI forms.


regards,

Mac

Jeff said:
Mac,

I did this and I thought it worked out pretty well. Use the tab control,
then instantiate each form setting its parent to the tab page. You take
the
boder off, set the dock to fill and there you go.

something like this...
dim fObjSelector as frmObjectSelector
fObjSelector = New frmObjectSelector
fObjSelector.FormBorderStyle = FormBorderStyle.None
fObjSelector.TopLevel = False
fObjSelector.Parent =
Me.FromHandle(TabControl1.TabPages(0).Handle)
fObjSelector.Dock = DockStyle.Fill
fObjSelector.Show()

jeff
[quoted text clipped - 37 lines]
 
M

Mac via DotNetMonster.com

Hi again Jeff,

Have managed to get further - I can access those properties, they just
weren't in the intellisense box. Don't quite understand that but I am not
going to worry about.

Will continue to play with it - getting an invalid index message at the
moment. Will let you know how I go.


Mac
Thanks for that Cor - I think I got your point (actually I kinda feel like
Neo after a visit to the Oracle - I need a cookie!! :)

My concerns with having a tabfolder with all the forms as tab pages rather
than an MDI was that I would lose all the functionality that goes with forms?
Is this something I shouldn't be concerned about? Also being able to merge
the menu of the child form into that of the MDI parent is something that is
going to be handy for us. Is there a way to get around this?

I suppose what I would like is the best of both worlds, but in the end I may
just have to choose. But this a decision I am kinds dreading having to make
as it will determine the whole make up of the application!!

How have you seen the tab setup work because I really think this is way I
want to go. Just having MDI forms I think is a bit "old" and the users cannot
see what all the screens are that they have opened. I suppose also with the
tab setup I am trying to reproduce something similar to how Lotus Note is
setup.

Any thoughts appreciated

Mac
[quoted text clipped - 21 lines]
 
M

Mac via DotNetMonster.com

Jeff,

couldn't seem to get past the index error - "0 is not a valid value for
index". In an attempt to resolve it before the Me.FromHandle statement I
actually added a blank tabpage to the tab control.

The Me.FromHandle statement was then fine, but I then got an "object not
instantiated" error when I attempt myForm.show. I then tried a more basic
form and there was no error but the form doesn't actually show! So in the end
my workaround doesn't work, so I guess I am back to trying to fix the index
error. Do you have any suggestions? Do I need to do something to the
tabcontrol first before referencing it?


Mac
Hi again Jeff,

Have managed to get further - I can access those properties, they just
weren't in the intellisense box. Don't quite understand that but I am not
going to worry about.

Will continue to play with it - getting an invalid index message at the
moment. Will let you know how I go.

Mac
Thanks for that Cor - I think I got your point (actually I kinda feel like
Neo after a visit to the Oracle - I need a cookie!! :)
[quoted text clipped - 24 lines]
 
J

Jeff Jarrell

you do need to have (read insert) a blank tab page for each sub form you are
instantiating.

Mac via DotNetMonster.com said:
Jeff,

couldn't seem to get past the index error - "0 is not a valid value for
index". In an attempt to resolve it before the Me.FromHandle statement I
actually added a blank tabpage to the tab control.

The Me.FromHandle statement was then fine, but I then got an "object not
instantiated" error when I attempt myForm.show. I then tried a more basic
form and there was no error but the form doesn't actually show! So in the
end
my workaround doesn't work, so I guess I am back to trying to fix the
index
error. Do you have any suggestions? Do I need to do something to the
tabcontrol first before referencing it?


Mac
Hi again Jeff,

Have managed to get further - I can access those properties, they just
weren't in the intellisense box. Don't quite understand that but I am not
going to worry about.

Will continue to play with it - getting an invalid index message at the
moment. Will let you know how I go.

Mac
Thanks for that Cor - I think I got your point (actually I kinda feel
like
Neo after a visit to the Oracle - I need a cookie!! :)
[quoted text clipped - 24 lines]
 
S

Simon Verona

Out of interest, I have done the same as Jeff in his answer, but instead of
using the tab control, I've used a toolbar and a panel.

What I do is respond to the click event of the toolbar, work out which
button has been selected and change it to "pressed" so the user can see
which is the active button and then set the mdiparent of the form in
question to the panel (after creating the form if necessary)... (you need to
switch the "toplevel" property of the form to false You can turn off the
control box and title for the form to make it appear "properly" (rather than
looking like a form on a panel!).

I'm presuming that you are not using mdi forms in the same way as word - ie
open multiple documents, but more as a way of breaking the functionality of
an application up ?

Just another way forward. I prefer it to the tabcontrol because you can
assign images easily to the buttons and have more control of the visuals...

You do still have the "menus" problems, but you could pretty easily merge
the menus if required in code..

Regards
Simon
 
M

Mac via DotNetMonster.com

Jeff,

Thank you for confirming that. Good news though - it was actually working and
I didn't realise it!! I only had the tabfolder big enough to see the only the
tabs and not the contents of the page. Have now got the tabfolder to fill the
container form now.

Many thanks for taking the time to reply to my post and help me out - it was
just what I was after. Sending you a virtual carton of beer now.......any
requests?

One final question, when you want to close one of the forms, do you execute a
MyForm.Close() as well as execute the remove method on the tabfolder?


regards,

Mac

Jeff said:
you do need to have (read insert) a blank tab page for each sub form you are
instantiating.
[quoted text clipped - 30 lines]
 
M

Mac via DotNetMonster.com

Hi Simon,

Thanks for your thoughts.

I have actually come across a custom tab control that looks a lot like the
tab strip at the bottom of some of the docking windows in Visual Studio, so
it is defintely more visually appealing that the standard .Net tabcontrol.

As for why I chose MDI, I was originally using it as a way to assist in the
user management of having multiple windows open in the application and to
have a central point for menu and functions. Then I realised that I wanted
more and actually wanted something similar to the Lotus Notes interface, but
at the same time be easy to manage behind the scenes for the developers. I am
confident that the tabcontrol solution will do the trick. It would be good to
get out the crystal ball and see 6 mths into the future to see if I have made
the right decision :)

And when it comes to showing a specific pull-down menu for the current form,
I agree that we will just have to do it in code through the form.load and
form.activate functions.

Thanks again for your comments. I am fairly new to .Net so its good to hear
how other developers implement solutions.

regards,

Mac

Simon said:
Out of interest, I have done the same as Jeff in his answer, but instead of
using the tab control, I've used a toolbar and a panel.

What I do is respond to the click event of the toolbar, work out which
button has been selected and change it to "pressed" so the user can see
which is the active button and then set the mdiparent of the form in
question to the panel (after creating the form if necessary)... (you need to
switch the "toplevel" property of the form to false You can turn off the
control box and title for the form to make it appear "properly" (rather than
looking like a form on a panel!).

I'm presuming that you are not using mdi forms in the same way as word - ie
open multiple documents, but more as a way of breaking the functionality of
an application up ?

Just another way forward. I prefer it to the tabcontrol because you can
assign images easily to the buttons and have more control of the visuals...

You do still have the "menus" problems, but you could pretty easily merge
the menus if required in code..

Regards
Simon
[quoted text clipped - 37 lines]
 
J

Jeff Jarrell

Mac,
One final question, when you want to close one of the forms, do you
execute a
MyForm.Close() as well as execute the remove method on the tabfolder?

You got it. Enjoying my virtual beer now.. :)



Mac via DotNetMonster.com said:
Jeff,

Thank you for confirming that. Good news though - it was actually working
and
I didn't realise it!! I only had the tabfolder big enough to see the only
the
tabs and not the contents of the page. Have now got the tabfolder to fill
the
container form now.

Many thanks for taking the time to reply to my post and help me out - it
was
just what I was after. Sending you a virtual carton of beer now.......any
requests?

One final question, when you want to close one of the forms, do you
execute a
MyForm.Close() as well as execute the remove method on the tabfolder?


regards,

Mac

Jeff said:
you do need to have (read insert) a blank tab page for each sub form you
are
instantiating.
[quoted text clipped - 30 lines]
 
M

Mac via DotNetMonster.com

Have got the tabs up and running but have encountered an issue.

I have a toolbar on the container form. Previously with the MDI setup, I then
implemented an interface (IToolbar) on each child form so that when I clicked
on a toolbar button on the MDI parent it would run the procedure as named in
the interface.

Obviously with making the tabcontrol the parent now, the child form still
implements an interface, however I am not sure how to now check for the type
of the form that is the current tabpage.

Can anyone assist?

Here is the code that was on the MDI container when I clicked a button on the
toolbar:

If (TypeOf (Me.ActiveMdiChild) Is IToolbar) Then
CType(Me.ActiveMdiChild, IToolbar).SomeMethod()
End If


regards,

Mac
 
M

Mac via DotNetMonster.com

I must actually be starting to understand it - I resolved the issue.

I realised in the end that each tabpage you create has one control on it
which is of course the form you associate to it. As each of my child forms
inherits from a baseform and it is this baseform that actually implements the
interface, all I have to do is get the control on the current tabpage
(through the controls collection) and check that it is of type "baseform" and
if it is then I simply execute the relevant method.

Too easy!! I am going home now.....


btw here is the code:

For Each c As Control In Me.FormTabControl.SelectedTab.Controls
If TypeOf c Is BaseForm Then
CType(c, IToolbar).SomeMethod()
End If
Next


regards,

Mac
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top