简体   繁体   中英

MFC dialog-based app with tab control - Visual Studio bugs/restrictions make recommended path impossible?

Create a dialog-based application in Visual Studio 2019. Insert a new dialog in the resources. Place a control (or two) on that dialog that you will later (try to) hook up to a variable (eg an edit box to enter your name).

Prepare to add that control variable by creating a class for this second dialog. If you inherit from CDialogEx (or perhaps other classes too - not tested), you can go on to add a variable for the control you added - easy, normal.

But if you had the "tab control" context from the title above in your mind, and chose to inherit from CMFCPropertyPage instead, can you add a variable subsequently? No you cannot - the class added makes no reference to the ID of the dialog resource, and so the Add Variable process has no basis to find a class to add the variable to.

I think this is a bug in Visual Studio... but I'm not 100% sure because I have always found the documentation around property sheets and property pages somewhat confusing. Specifically:

  • Do the classes implementing the tabs contents on a tab control "contain" the controls "on" the tab... or is the tab control really just a way to provide visual cues to show/hide sets of controls, and all of those controls and associated variables reside in one class?

I believe it's intended to be the former, but I can imagine that one uses a tab control because there are strong similarities between tab contents, and therefore potential benefits in implementing all the control variables in one place so as to avoid duplication. I just wish it was stated explicitly somewhere what the intention was.

Wider context: I'm trying to implement a dialog-based app with a tab control dominating that dialog. MS documentation says to implement a tab control using CPropertySheet and CPropertyPage to implement the tabbed dialog and tab contents. However, there is no (direct) way to create a dialog-based application whose main dialog inherits from CPropertySheet . When you look for examples of tab controls at the application level, you readily find things that deviate from the documented path considerably - using neither CPropertySheet nor CPropertyPage and using the WM_LBUTTONDOWN event instead of TCN_SELCHANGE , both without obvious reasons.

Any tips on (a) how to repair the apparent Visual Studio bug and/or (b) how to inherit from CPropertySheet for my application dialog and/or (c) where to find a clearer and more conventional example of tab control use at the top level would be greatly appreciated.

One time, I had made on application as such. I don't remember if I used the Visual Studio new project wizard. Most probably, I did. But I will assist you on how to do it if you can not reach how to do it via the assistant.

The essential things:

  1. Define the main dialog in the resources and the respective class in its H and CPP files.

  2. In the YourAppClass::InitInstance you will need to have something like:

     YourMainDlgClass dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } else if (nResponse == -1) { TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\\n"); TRACE(traceAppMsg, 0, "Warning: if you are using MFC controls on the dialog, you cannot #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS.\\n"); }
  3. Insert a CMFCTabCtrl element in your dialog for tabs, instead of using a CPropertySheet .

Given that there appears to be no clear and consistent way of approaching this, if (like me) you think "how hard can it be?", you might naively set out to see if you can create a new dialog-based application based on CDialog and manually convert it to CPropertyPage . You might fare better; I quickly hit a weird problem with the app compiling but not running - it could not load the window caption from the resource ID, despite the caption literally being there in black and white. Due to the weirdness, this was a red flag, and so to my mind problem (b) seems to be not worth the effort.

Without a CPropertySheet at the top level, there is no point having any kind of CPropertyPage or CMFCPropertyPage involved, making problem (a) pointless. That said, if you manually convert from (default) CDialogEx to CPropertyPage for your tab classes, it seems to have no problem compiling and running - the tabs just don't have any functionality that integrates with the main dialog.

Instead, I can now recommend working through the details of the video example even though it does strange things at first glance. You can achieve the desired result in more or less the same way as follows:

  • Use plain CDialogEx throughout, and so provide all the tab switching/showing/hiding/control work yourself (which the example demonstrates).
  • Create your main dialog and all tabs in the resource editor, adding the CDialog -based classes from there.
  • If you create your tab dialog resources via Insert Dialog (generic) instead of Add Resource (uses specific templates) then you will have to manually set certain dialog properties for each tab:
    • Border: Thin (or I preferred None)
    • Style: Child
    • System Menu: false
    • Title Bar: false
  • You can simplify the repositioning of the tabs (see below; it barely justifies the separate SetRectangle() function)
  • You should (probably) drive the tab changing from the TCN_SELCHANGE event instead of WM_LBUTTONDOWN

As noted, repositioning the tabs can be simplified to something like:

CRect tabRect;
m_tabControl.GetWindowRect( &tabRect );
for ( int i = 0; i < m_totalTabs; i++ )
{
    m_pTabPage[ i ]->SetWindowPos( &wndTop, tabRect.left, tabRect.top, 0, 0,
                i == m_currentTab? SWP_NOSIZE|SWP_SHOWWINDOW : SWP_NOSIZE|SWP_HIDEWINDOW );
}

Additional calls to ShowWindow() for each tab shown in the example are redundant.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM