Five Ways to add tabs in the dialog box

Source: Internet
Author: User
(Blog migration collection)

Tabs are a bit difficult to use in the MFC control. Today I saw a related article and thought it was quite systematic and easy to understand, I will share this with you and keep it for future reference.
(Which of the following is transferred from http://www.vckbase.com/document/viewdoc? Id = 398, Original Author: yellow morning volume)

When a dialog box-based program contains a considerable number of controls, you will surely think of using property pages to classify these controls. This article discusses several possible implementations of this method.

Solution 1

Place a Tab Control on the dialog box, and then place the required Control on the dialog box (in this example, two buttons are placed to try to display one in each label ). Then use the Class
Create a Control variable for the Tab Control. The variable is of the CTabCtrl class, and the corresponding Control class is also created for other controls.
In the initial function of the Main Dialog Box, add the following code to CProperty1Dlg: OnInitDialog:

// In this example, two tags are inserted. In actual use, you can insert the required number of tags in a loop. After running, the first tag is selected by default.
M_tab.InsertItem (0, _ T ("Tab1 "));
M_tab.InsertItem (1, _ T ("Tab2 "));
// Hide the control that is not the first label, leaving only the control you want
M_button2.ShowWindow (SW_HIDE );

Use ClassWizard to process the TCN_SELCHANGE message of Tab Control. In the message processing function, CWnd: ShowWindow is used to display and hide corresponding controls.

Void CProperty1Dlg: OnSelchangeTab1 (NMHDR * pNMHDR, LRESULT * pResult)
{
// Getcursel returns the index number of the selected tag (based on 0)
Int sel = m_tab.getcursel ();

Switch (SEL)
{
Case 0:
M_button1.showwindow (sw_show );
M_button2.showwindow (sw_hide );
Break;
Case 1:
M_button2.showwindow (sw_show );
M_button1.showwindow (sw_hide );
Break;
}

* Presult = 0;
}

After doing so, the controls on the interface will be displayed in different labels, but this solution also has many disadvantages.

All controls are still in the same dialog box. It is inconvenient to edit them using the dialog box editor.
To be able to classify the display controls, you must use classwizard for each
Controls to use the showwindow function of the cwnd base class of each control variable to display and
Hide. Sometimes, to use the DDX and DDV mechanisms for data exchange, you also need to create some variables that store values, which makes the entire dialog box class very large and difficult to operate.
Of course, you can also use arrays to store those control variables or value variables, but this is not the best. Sometimes some irrelevant control variables are put into an array, access control through array index numbers that have no practical significance
Program compilation will cause trouble. It is best to classify all the controls and place them in the dialog box class. These dialogs appear as subdialogs in the main dialog box. Yes. Now let's look at solution 2.

Solution 2

In this solution, I will use the ready-made CPropertySheet and CPropertyPage classes in MFC to distribute controls to various dialog box classes.

First, add two (or more) dialog box resources. Modify the resource attributes of each dialog box and change the Caption attribute of the dialog box to the text you want to display on the tab. Label the Style in the dialog box
Changed to: Child, and changed the Border attribute to: Thin. Only the Title is selected.
Bar check box, remove other check boxes. Then you can add the controls to be separately displayed in these dialog boxes.

Create a dialog box class for the preceding dialog box resources, which is inherited from CPropertyPage. In this way, the sub-Dialog Box classes are ready, and the Main Dialog Box class can be directly used as the CPropertySheet class. Use the following code:

CPropertySheet sheet ("attribute page dialog box ");
CPage1 page1;
CPage2 page2;
// Add subdialog box as an attribute page
Sheet. AddPage (& page1 );
Sheet. AddPage (& page2 );
// Generate a modal dialog box, or use the Create method to generate a non-modal dialog box (see MSDN for details)
Sheet. DoModal ();

In this case, the dialog box is as follows:

However, someone may ask how to place other controls in the main dialog box? If you use CPropertySheet directly, it is not possible, but don't forget that we can inherit our own classes from the CPropertySheet class! Let's take a look at solution 3.

Solution 3

The first step is to create the subdialog box classes to be displayed on the property page. The creation steps are the same as solution 2 and are inherited from CPropertyPage.

This time, we will inherit our class from the CPropertySheet class (assuming the class name is CMySheet ). We need to put a button control here. Now, add a member variable m_button of the CButton class to CMySheet.

In the OnInitDialog () function of the CMySheet class, write as follows:

BOOL bResult = CPropertySheet: OnInitDialog ();

// Get the size of the property page
CRect rectWnd;
GetWindowRect (rectWnd );
// Adjust the dialog box width
SetWindowPos (NULL, 0, 0, rectWnd. Width () + 100, rectWnd. Height (), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
CRect rectButton (rectWnd. Width () + 25, 25, rectWnd. Width () + 75, 75 );
// Create a button with the program
M_button.Create ("Button", BS_PUSHBUTTON, CRect (rectWnd. Width (), 25, rectWnd. Width () + 75, 50), this, 1 );
// Display this button
M_button.ShowWindow (SW_SHOW );
CenterWindow ();
Return bResult;

The effect is as follows:

Solution 3 although you can add controls in the main dialog box, it is also troublesome. The added controls can only be on the right or bottom of the property page. It is cumbersome to use programs to generate controls, and the location and size are not easy to control. There are other ways to add a property page in the dialog box and add controls in the Main Dialog Box at will? There are still. Let's take a look at solution 4.

Solution 4

This time we will not inherit our class from cpropertysheet, or use it directly. The subdialog classes on each property page are still required. The creation method is the same as the preceding two schemes.

First, create a dialog box-based project. You can add some required controls to edit an existing main dialog box, but you have to leave some space to place the property pages.

Add a member variable (m_sheet) of the cpropertysheet class to the Main Dialog Box class to represent the entire property page. Add instances of subdialog classes as member variables (m_page1, m_page2 ......).

In the oninitdialog () function of the Main Dialog Box class, add:

// Add a tag. The tag name is determined by the title bar of each subdialog box.
M_sheet.addpage (& m_page1 );
M_sheet.addpage (& m_page2 );
// Use create to create an attribute page
M_sheet.create (this, ws_child | ws_visible, ws_ex_controlparent );

Rect;
M_sheet.getwindowrect (& rect );
Int width = rect. Right-rect. Left;
Int Height = rect. Bottom-rect. Top;

// Adjust the size and position of the property page
M_sheet.SetWindowPos (NULL, 20, 50, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );

The effect is as follows:

This solution allows you to add necessary controls in the main dialog box, and the controls on the property page are also scattered in various subdialog box classes, which is very convenient to use.

However, this also has some drawbacks: The Main Dialog Box cannot process the tag messages on the property page, that is, the Main Dialog Box cannot be notified when a tag is clicked. (I may be at a limited level. Theoretically, I should be able to solve this problem)

Solution 5

This time, we still need to use Tab Control and inherit the class (CTabSheet) from the CTabCtrl Control class. (This method is from an article by CodeGuru. I will make some modifications to make it easier to use)

First, I will introduce how to use CTabSheet.

You must first create a subdialog box class. This subdialog box class should not be inherited from CPropertyPage, but directly from CDialog. In addition, the attributes of the sub-Dialog Box resources should be set to: Style, Border, and None.

In the main dialog box, add a Tab Control and adjust the position and size as appropriate. Use ClassWizard to create a CTabSheet Control variable for this Tab Control.

Add OnInitDialog () in the Main Dialog Box:

m_sheet.AddPage("tab1", &m_page1, IDD_DIALOG1);
m_sheet.AddPage("tab2", &m_page2, IDD_DIALOG2);
m_sheet.Show();

In this way, you can create a perfect property page on the dialog box. The effect is exactly the same.

Next I will talk about the details of the CTabSheet class.

CTabSheet is inherited from CTabCtrl and is used as the Control class for Tab Control. There is a member variable in the class to record the pointer CDialog * m_pPages [MAXPAGE] for each subdialog box; MAXPAGE is the maximum value of the labels that can be loaded by the class.

Class has an AddPage method, used to record the sub-Dialog Box pointer and the ID of the used dialog box resource.

Bool ctabsheet: addpage (lpctstr title, cdialog * pdialog, uint ID)
{
If (maxpage = m_nnumofpages)
Return false;

// Save the total number of subdialogs
M_nnumofpages ++;

// Record the sub-Dialog Box pointer, resource ID, and text to be displayed on the tab
M_ppages [m_nNumOfPages-1] = pdialog;
M_idd [m_nNumOfPages-1] = ID;
M_title [m_nNumOfPages-1] = title;

Return true;
}

After adding subdialogs to addpage, you must call the show method of ctabsheet to generate tags and subdialogs.

Void ctabsheet: Show ()
{
// Use cdialog: Create to create a subdialog box, and use ctabctrl: insertitem to add the corresponding tag
For (INT I = 0; I <m_nnumofpages; I ++)
{
M_ppages [I]-> Create (m_idd [I], this );
Insertitem (I, m_title [I]);
}

// Because the first label is selected by default when the dialog box is displayed, the first subdialog box should be displayed, and other subdialogs should be hidden.
M_pPages [0]-> ShowWindow (SW_SHOW );
For (I = 1; I <m_nNumOfPages; I ++)
M_pPages [I]-> ShowWindow (SW_HIDE );

SetRect ();

}

After the tag and subdialog box are generated, call CTabSheet: SetRect to calculate and adjust the size of the attribute page.

Void CTabSheet: SetRect ()
{
CRect tabRect, itemRect;
Int nX, nY, nXc, nYc;

// Obtain the size of the Tab Control.
GetClientRect (& tabRect );
GetItemRect (0, & itemRect );

// Calculate the position and size of each subdialog box relative to Tab Control.
NX = itemRect. left;
NY = itemRect. bottom + 1;
NXc = tabRect. right-itemRect.left-2;
NYc = tabRect. bottom-nY-2;

// Adjust the subdialog box using the calculated data
M_pPages [0]-> SetWindowPos (& wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW );
For (int nCount = 1; nCount <m_nNumOfPages; nCount ++)
M_ppages [ncount]-> setwindowpos (& wndtop, NX, NY, nxc, NYC, swp_hidewindow );

}

After you click the tab bar, the corresponding subdialog box is displayed, and the displayed subdialog box is hidden. Therefore, classwizard is used to process wm_lbuttondown messages.

Void ctabsheet: onlbuttondown (uint nflags, cpoint point)
{
Ctabctrl: onlbuttondown (nflags, point );

// Determine whether other labels are clicked
If (m_ncurrentpage! = Getcurfocus ())
{
// Hide the original subdialog box
M_ppages [m_ncurrentpage]-> showwindow (sw_hide );
M_ncurrentpage = getcurfocus ();
// Display the subdialog box corresponding to the current tag
M_ppages [m_ncurrentpage]-> showwindow (sw_show );
}

}

In this way, the ctabsheet class can be used to easily place its own property pages in the dialog box, and controls are scattered in each subdialog box class, in line with the idea of object encapsulation. And use this method to create
As an attribute page, you can use classwizard to easily generate a message ing processing tab.
Control Message. For example, you can process the tcn_selchange message to perform some actions when the tag is switched.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.