Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Tab Control in existing dialog box

Tab Control in existing dialog box

Scheduled Pinned Locked Moved C / C++ / MFC
questionc++comtutorial
28 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    acerunner316
    wrote on last edited by
    #1

    I am using MFC. I want to add a tab control in an existing dialog box. I found this example: http://www.codeproject.com/useritems/Simple\_Tab\_Control.asp but it seems that you have to create a window for each tab, with the main Window having just the tab control. How can I add a tab control without having to redo what I already have?

    M 1 Reply Last reply
    0
    • A acerunner316

      I am using MFC. I want to add a tab control in an existing dialog box. I found this example: http://www.codeproject.com/useritems/Simple\_Tab\_Control.asp but it seems that you have to create a window for each tab, with the main Window having just the tab control. How can I add a tab control without having to redo what I already have?

      M Offline
      M Offline
      Mark Salsbery
      wrote on last edited by
      #2

      The Windows tab common control provides the tabs but you still need to provide a window for each tab. What is it you are trying to do by adding a tab control without additional windows?

      A 1 Reply Last reply
      0
      • M Mark Salsbery

        The Windows tab common control provides the tabs but you still need to provide a window for each tab. What is it you are trying to do by adding a tab control without additional windows?

        A Offline
        A Offline
        acerunner316
        wrote on last edited by
        #3

        Well, not necessary WITHOUT additional windows, but place my existing dialog window inside a tab. The reason I want to do that is because my app really will be performing the task of two related apps. So instead of having two seperate executables, I was thinking use two tabs, one for each "app".

        M 1 Reply Last reply
        0
        • A acerunner316

          Well, not necessary WITHOUT additional windows, but place my existing dialog window inside a tab. The reason I want to do that is because my app really will be performing the task of two related apps. So instead of having two seperate executables, I was thinking use two tabs, one for each "app".

          M Offline
          M Offline
          Mark Salsbery
          wrote on last edited by
          #4

          Cool. You could make the dialogs modeless child dialogs if they aren't already (they could even be the same class). Instead of making the tab control a child of the dialog, make it a child of a simple frame window. The frame window can hold the tab control and the dialogs and handle all the associated resizing/repositioning. That gives you the option of a common toolbar and status bar as well. Just a thought.

          A 1 Reply Last reply
          0
          • M Mark Salsbery

            Cool. You could make the dialogs modeless child dialogs if they aren't already (they could even be the same class). Instead of making the tab control a child of the dialog, make it a child of a simple frame window. The frame window can hold the tab control and the dialogs and handle all the associated resizing/repositioning. That gives you the option of a common toolbar and status bar as well. Just a thought.

            A Offline
            A Offline
            acerunner316
            wrote on last edited by
            #5

            how do I change my existing dialog (which is the main dialog window for the project) to a child? And how to I set another window (frame window) to be the new parent of the project? Thanks Also, would it be necessary for the main window to have OnInitDialog, OnSysCommand, OnPaint, and OnQueryDragIcon. In which case, I would have to add those functions in the new main window, and remove them from what is now the child window? And also transfering the system menu (including the about...)? -- modified at 22:10 Monday 18th December, 2006

            M 1 Reply Last reply
            0
            • A acerunner316

              how do I change my existing dialog (which is the main dialog window for the project) to a child? And how to I set another window (frame window) to be the new parent of the project? Thanks Also, would it be necessary for the main window to have OnInitDialog, OnSysCommand, OnPaint, and OnQueryDragIcon. In which case, I would have to add those functions in the new main window, and remove them from what is now the child window? And also transfering the system menu (including the about...)? -- modified at 22:10 Monday 18th December, 2006

              M Offline
              M Offline
              Mark Salsbery
              wrote on last edited by
              #6

              It'll just take a little rearranging....not too much code.

              acerunner316 wrote:

              how do I change my existing dialog (which is the main dialog window for the project) to a child? And how to I set another window (frame window) to be the new parent of the project?

              In your application class' InitInstance() override you probably have something like this:

              CMyMainDlg dlg;
              m\_pMainWnd = &dlg;
              INT\_PTR nResponse = dlg.DoModal();
              if (nResponse == IDOK)
              ...
              

              You'd replace that with something like:

              CMainFrame\* pFrame = new CMainFrame;
              if (!pFrame)
              	return FALSE;
              m\_pMainWnd = pFrame;
              if (!Create(NULL, \_T("Window Name"), 
              		WS\_VISIBLE|WS\_OVERLAPPEDWINDOW, 
              		CRect(50,50,400,400), NULL, NULL, 0, NULL))
              	return FALSE;
              ...
              

              CMainFrame would be a CFrameWnd-derived class. You can override CFrameWnd::OnCreateClient() and in your implementation create the tab window and the two modeless dialogs. All the necessary code for managing a tab control will need to be added as well.

              acerunner316 wrote:

              Also, would it be necessary for the main window to have OnInitDialog, OnSysCommand, OnPaint, and OnQueryDragIcon. In which case, I would have to add those functions in the new main window, and remove them from what is now the child window? And also transfering the system menu (including the about...)?

              The main window has OnCreateClient(). Instead of OnInitDialog there's OnCreate() (handler for WM_CREATE). Your dialog classes would stay the same. They still need their OnInitDialog() overrides to initialize their controls and whatever else you do there. Same with OnPaint. OnQueryDragIcon., OnSysCommand, and the about-window stuff would probably move to the frame window class.

              A 1 Reply Last reply
              0
              • M Mark Salsbery

                It'll just take a little rearranging....not too much code.

                acerunner316 wrote:

                how do I change my existing dialog (which is the main dialog window for the project) to a child? And how to I set another window (frame window) to be the new parent of the project?

                In your application class' InitInstance() override you probably have something like this:

                CMyMainDlg dlg;
                m\_pMainWnd = &dlg;
                INT\_PTR nResponse = dlg.DoModal();
                if (nResponse == IDOK)
                ...
                

                You'd replace that with something like:

                CMainFrame\* pFrame = new CMainFrame;
                if (!pFrame)
                	return FALSE;
                m\_pMainWnd = pFrame;
                if (!Create(NULL, \_T("Window Name"), 
                		WS\_VISIBLE|WS\_OVERLAPPEDWINDOW, 
                		CRect(50,50,400,400), NULL, NULL, 0, NULL))
                	return FALSE;
                ...
                

                CMainFrame would be a CFrameWnd-derived class. You can override CFrameWnd::OnCreateClient() and in your implementation create the tab window and the two modeless dialogs. All the necessary code for managing a tab control will need to be added as well.

                acerunner316 wrote:

                Also, would it be necessary for the main window to have OnInitDialog, OnSysCommand, OnPaint, and OnQueryDragIcon. In which case, I would have to add those functions in the new main window, and remove them from what is now the child window? And also transfering the system menu (including the about...)?

                The main window has OnCreateClient(). Instead of OnInitDialog there's OnCreate() (handler for WM_CREATE). Your dialog classes would stay the same. They still need their OnInitDialog() overrides to initialize their controls and whatever else you do there. Same with OnPaint. OnQueryDragIcon., OnSysCommand, and the about-window stuff would probably move to the frame window class.

                A Offline
                A Offline
                acerunner316
                wrote on last edited by
                #7

                is it necessary to derive a CFrameWnd class? Is there anything wrong with creating a dialog window (called IDD_MAINFRAME) in resource editor and changing the first line of... CMyMainDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) ... ...to CMainFrame dlg;? What's the benefit of CFrameWnd vs CDialog in my situation? Also how does a child tab window handle OnCancel, OnDestroy, and PostNcDestroy. Do I even need that anymore? -- modified at 15:05 Tuesday 19th December, 2006

                M 1 Reply Last reply
                0
                • A acerunner316

                  is it necessary to derive a CFrameWnd class? Is there anything wrong with creating a dialog window (called IDD_MAINFRAME) in resource editor and changing the first line of... CMyMainDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) ... ...to CMainFrame dlg;? What's the benefit of CFrameWnd vs CDialog in my situation? Also how does a child tab window handle OnCancel, OnDestroy, and PostNcDestroy. Do I even need that anymore? -- modified at 15:05 Tuesday 19th December, 2006

                  M Offline
                  M Offline
                  Mark Salsbery
                  wrote on last edited by
                  #8

                  Use whatever you want. They are all windows (have an HWND). A dialog implies a dialog resource. If you are going to have a tab control with 2 tabs, each containing a dialog then there is no reason to use a dialog to contain the tabs, inless you have other controls placed around the tabs that are laid out in a DIALOG resource. If that's the case then a dialog will work fine too. The advantage of CFrameWnd over CWnd is the automagic handling of decorations - toolbar, status bar, etc - and auto-sizing/positioning of an imbedded "client" window (around any decorations). A CWnd will work fine. So will a dialog if that's what you need. There's nothing wrong with handling it all yourself. You have complete control over all the windows in your app.

                  A 1 Reply Last reply
                  0
                  • M Mark Salsbery

                    Use whatever you want. They are all windows (have an HWND). A dialog implies a dialog resource. If you are going to have a tab control with 2 tabs, each containing a dialog then there is no reason to use a dialog to contain the tabs, inless you have other controls placed around the tabs that are laid out in a DIALOG resource. If that's the case then a dialog will work fine too. The advantage of CFrameWnd over CWnd is the automagic handling of decorations - toolbar, status bar, etc - and auto-sizing/positioning of an imbedded "client" window (around any decorations). A CWnd will work fine. So will a dialog if that's what you need. There's nothing wrong with handling it all yourself. You have complete control over all the windows in your app.

                    A Offline
                    A Offline
                    acerunner316
                    wrote on last edited by
                    #9

                    I've successfully added a tab control with two dialog windows as child. The first tab is my original app that WAS my main window, and the second tab is a completely new dialog window (for now just has an editbox). The code compiles and I can run it, and it opens with default on the first tab. But none of the controls from the first tab works properly. Debugger says access violation.

                    M 1 Reply Last reply
                    0
                    • A acerunner316

                      I've successfully added a tab control with two dialog windows as child. The first tab is my original app that WAS my main window, and the second tab is a completely new dialog window (for now just has an editbox). The code compiles and I can run it, and it opens with default on the first tab. But none of the controls from the first tab works properly. Debugger says access violation.

                      M Offline
                      M Offline
                      Mark Salsbery
                      wrote on last edited by
                      #10

                      What type is the main window now?

                      acerunner316 wrote:

                      But none of the controls from the first tab works properly. Debugger says access violation.

                      These two are maybe related? Where does the exception occur? If it's MFC can you trace the stack back into your code? Without seeing the code for how you create the two dialogs and how you handle placing them in the tabs it's tough to guess :) Mark

                      A 1 Reply Last reply
                      0
                      • M Mark Salsbery

                        What type is the main window now?

                        acerunner316 wrote:

                        But none of the controls from the first tab works properly. Debugger says access violation.

                        These two are maybe related? Where does the exception occur? If it's MFC can you trace the stack back into your code? Without seeing the code for how you create the two dialogs and how you handle placing them in the tabs it's tough to guess :) Mark

                        A Offline
                        A Offline
                        acerunner316
                        wrote on last edited by
                        #11

                        The main window is a CDialog, and so are the two child tab windows. All generated in resource editor. I've removed theOnSysCommand, OnPaint, and OnQueryDragIcon from the original main window, and added into the new main window. OnInitDialog stayed but I removed the part that generates the about box. Not sure what to do about OnCancel, OnDestroy, and PostNcDestroy, so I left it as it is. To create the tabs I basically followed this example exactly (http://www.codersource.net/mfc\_ctabctrl.html). The error is "Unhandled exception in [myappname].exe (NTDLL.DLL): 0xC0000005: Access Violation." Thanks.

                        M 1 Reply Last reply
                        0
                        • A acerunner316

                          The main window is a CDialog, and so are the two child tab windows. All generated in resource editor. I've removed theOnSysCommand, OnPaint, and OnQueryDragIcon from the original main window, and added into the new main window. OnInitDialog stayed but I removed the part that generates the about box. Not sure what to do about OnCancel, OnDestroy, and PostNcDestroy, so I left it as it is. To create the tabs I basically followed this example exactly (http://www.codersource.net/mfc\_ctabctrl.html). The error is "Unhandled exception in [myappname].exe (NTDLL.DLL): 0xC0000005: Access Violation." Thanks.

                          M Offline
                          M Offline
                          Mark Salsbery
                          wrote on last edited by
                          #12

                          acerunner316 wrote:

                          The error is "Unhandled exception in [myappname].exe (NTDLL.DLL): 0xC0000005: Access Violation."

                          Right, but where? If it's not stopped on a line of your code can you view the stack trace and find the last line of your code that executed before the exception?

                          A 2 Replies Last reply
                          0
                          • M Mark Salsbery

                            acerunner316 wrote:

                            The error is "Unhandled exception in [myappname].exe (NTDLL.DLL): 0xC0000005: Access Violation."

                            Right, but where? If it's not stopped on a line of your code can you view the stack trace and find the last line of your code that executed before the exception?

                            A Offline
                            A Offline
                            acerunner316
                            wrote on last edited by
                            #13

                            Ok, I fixed the problem. For some reason, a clean and a rebuild fixed the problem. But now another minor problem has arisen. I have a small popup loading dialog window that should be popping up centered relative to the main dialog window. (If you recall, you helped me with that in another forum thread.) Now with the tab, the popup window is created in the upper left corner of the tab window. Here is how it is created. EnableWindow(FALSE); pLoadingDlg = new CLoading; pLoadingDlg->Create(IDD_LOADING, this); //"this" or "GetParent()" pLoadingDlg->ShowWindow(SW_SHOW); I tried using this to move it. CRect MainDialogRect, LoadDialogRect; GetClientRect(&MainDialogRect); pLoadingDlg->GetWindowRect(&LoadDialogRect); pLoadingDlg->MoveWindow((MainDialogRect.Width() - LoadDialogRect.Width()) / 2, (MainDialogRect.Height() - LoadDialogRect.Height()) / 2, LoadDialogRect.Width(), LoadDialogRect.Height()); But it just places the window at the correct location, but relative to the screen, and not to the main window. Also the EnableWindow(FALSE); no longer works. Is it safe to use GetParent()->EnableWindow(FALSE);? -- modified at 16:02 Wednesday 20th December, 2006

                            M 1 Reply Last reply
                            0
                            • A acerunner316

                              Ok, I fixed the problem. For some reason, a clean and a rebuild fixed the problem. But now another minor problem has arisen. I have a small popup loading dialog window that should be popping up centered relative to the main dialog window. (If you recall, you helped me with that in another forum thread.) Now with the tab, the popup window is created in the upper left corner of the tab window. Here is how it is created. EnableWindow(FALSE); pLoadingDlg = new CLoading; pLoadingDlg->Create(IDD_LOADING, this); //"this" or "GetParent()" pLoadingDlg->ShowWindow(SW_SHOW); I tried using this to move it. CRect MainDialogRect, LoadDialogRect; GetClientRect(&MainDialogRect); pLoadingDlg->GetWindowRect(&LoadDialogRect); pLoadingDlg->MoveWindow((MainDialogRect.Width() - LoadDialogRect.Width()) / 2, (MainDialogRect.Height() - LoadDialogRect.Height()) / 2, LoadDialogRect.Width(), LoadDialogRect.Height()); But it just places the window at the correct location, but relative to the screen, and not to the main window. Also the EnableWindow(FALSE); no longer works. Is it safe to use GetParent()->EnableWindow(FALSE);? -- modified at 16:02 Wednesday 20th December, 2006

                              M Offline
                              M Offline
                              Mark Salsbery
                              wrote on last edited by
                              #14

                              What class is this called from (which window)? EnableWindow(FALSE); pLoadingDlg = new CLoading; pLoadingDlg->Create(IDD_LOADING, this); //"this" or "GetParent()" pLoadingDlg->ShowWindow(SW_SHOW);

                              A 1 Reply Last reply
                              0
                              • M Mark Salsbery

                                What class is this called from (which window)? EnableWindow(FALSE); pLoadingDlg = new CLoading; pLoadingDlg->Create(IDD_LOADING, this); //"this" or "GetParent()" pLoadingDlg->ShowWindow(SW_SHOW);

                                A Offline
                                A Offline
                                acerunner316
                                wrote on last edited by
                                #15

                                it is called from what is now a child tab window. The code worked fine as the main dialog window until i started using tabs.

                                M 3 Replies Last reply
                                0
                                • M Mark Salsbery

                                  acerunner316 wrote:

                                  The error is "Unhandled exception in [myappname].exe (NTDLL.DLL): 0xC0000005: Access Violation."

                                  Right, but where? If it's not stopped on a line of your code can you view the stack trace and find the last line of your code that executed before the exception?

                                  A Offline
                                  A Offline
                                  acerunner316
                                  wrote on last edited by
                                  #16

                                  Another question, since the two tabs does very similar tasks and functions, is it possible to use the same dialog class for both tabs, but different resource dialog (ie IDD_TAB1 and IDD_TAB2 both associated with CTabDlg)? The layout will be different, but I will be reusing most of the same functions.

                                  M 1 Reply Last reply
                                  0
                                  • A acerunner316

                                    it is called from what is now a child tab window. The code worked fine as the main dialog window until i started using tabs.

                                    M Offline
                                    M Offline
                                    Mark Salsbery
                                    wrote on last edited by
                                    #17

                                    Does this work? CRect MainDialogRect, LoadDialogRect; GetParent()->GetClientRect(&MainDialogRect); pLoadingDlg->GetWindowRect(&LoadDialogRect); pLoadingDlg->MoveWindow((MainDialogRect.Width() - LoadDialogRect.Width()) / 2, (MainDialogRect.Height() - LoadDialogRect.Height()) / 2, LoadDialogRect.Width(), LoadDialogRect.Height());

                                    1 Reply Last reply
                                    0
                                    • A acerunner316

                                      Another question, since the two tabs does very similar tasks and functions, is it possible to use the same dialog class for both tabs, but different resource dialog (ie IDD_TAB1 and IDD_TAB2 both associated with CTabDlg)? The layout will be different, but I will be reusing most of the same functions.

                                      M Offline
                                      M Offline
                                      Mark Salsbery
                                      wrote on last edited by
                                      #18

                                      Yes it's possible. You'll need to create with the appropriate resource ID. You can also use a common base class containing the code for the controls they have in common and derive 2 classes, each with whatever code they need for the unique parts of the dialogs.

                                      A 1 Reply Last reply
                                      0
                                      • A acerunner316

                                        it is called from what is now a child tab window. The code worked fine as the main dialog window until i started using tabs.

                                        M Offline
                                        M Offline
                                        Mark Salsbery
                                        wrote on last edited by
                                        #19

                                        Argg sorry - try this :) CRect MainDialogRect, LoadDialogRect; GetWindowRect(&MainDialogRect); ::MapWindowPoints(0, *this, (LPPOINT)&MainDialogRect, 2); pLoadingDlg->GetWindowRect(&LoadDialogRect); pLoadingDlg->MoveWindow((MainDialogRect.Width() - LoadDialogRect.Width()) / 2, (MainDialogRect.Height() - LoadDialogRect.Height()) / 2, LoadDialogRect.Width(), LoadDialogRect.Height()); Tab control doesn't really have a useful client rect so I've taken it's window rect (relative to the screen) and mapped it to be relative to itself. I think that will work...

                                        1 Reply Last reply
                                        0
                                        • A acerunner316

                                          it is called from what is now a child tab window. The code worked fine as the main dialog window until i started using tabs.

                                          M Offline
                                          M Offline
                                          Mark Salsbery
                                          wrote on last edited by
                                          #20

                                          :laugh: Now that I think about it more, the MapWindowPoints() isn't necessary since you only need the size of the tabs control, not it's position. You can probably eliminate that call. The important part is using GetWindowRect instead of GetClientRect.

                                          A 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups