MFC Note: The Initialization tab control point improvement

Background:
MFC tool with tab labels as navigation. Needs to be initialized when the dialog box initialization.

First, the process outlined

Achieve this function needs to do the following things:

  • Creating main dialog, multiple sub-dialog.
  • Sub-dialog to set properties:
    Appearance Style to Child, Boarder choose None.
  • Associated tab label control variable (may directly control ID).
  • Initialization, the sub dialog box to add to the tab label.
  • Click response function to switch dialog.

Below are listed first original version, analyze problems, and then solve the problem.
The layout of the instructions in this article omitted the MFC control.

Second, the original version

2.1 Variable declaration

namespace NSONVIF {
    enum PAGE_TYPE {
        PAGE_DISCOVER = 0,
        PAGE_DEVICE,
        PAGE_MEDIA,
        PAGE_IMAGING,
        PAGE_DEBUG,

        PAGE_MAX,
    };
}

    std::vector<CDialog *> m_pvPage;
    NSONVIF::PAGE_TYPE m_nCurTab;
    CDiscover m_cDlgDiscover;
    CDeviceService m_cDlgDevice;
    CMediaService m_cDlgMedia;
    CImagingService m_cDlgImaging;
    CDebugInfo m_cDlgDebug;

    CTabCtrl m_ctrTab;

Use m_pvPage storage sub-dialogs pointer. Variables beginning m_cDlg sub-dialog. m_ctrTab for the Tab associated with the control class.

2.2 Initialization

    m_ctrTab.InsertItem(0, "Discover");
    m_ctrTab.InsertItem(1, "Device");
    m_ctrTab.InsertItem(2, "Media");
    m_ctrTab.InsertItem(3, "Imaging");
    m_ctrTab.InsertItem(4, "Debug");

    m_pvPage.resize(NSONVIF::PAGE_MAX);

    m_cDlgDiscover.Create(IDD_DLG_DISCOVER, &m_ctrTab);
    m_pvPage[NSONVIF::PAGE_DISCOVER] = &m_cDlgDiscover;
    m_cDlgDiscover.SetOnvifProxy(&m_cProxy);

    m_cDlgDevice.Create(IDD_DLG_DEVICE, &m_ctrTab);
    m_pvPage[NSONVIF::PAGE_DEVICE] = &m_cDlgDevice;
    m_cDlgDevice.SetOnvifProxy(&m_cProxy);

    m_cDlgMedia.Create(IDD_DLG_MEDIA, &m_ctrTab);
    m_pvPage[NSONVIF::PAGE_MEDIA] = &m_cDlgMedia;
    m_cDlgMedia.SetOnvifProxy(&m_cProxy);

    m_cDlgImaging.Create(IDD_DLG_IMAGING, &m_ctrTab);
    m_pvPage[NSONVIF::PAGE_IMAGING] = &m_cDlgImaging;
    m_cDlgImaging.SetOnvifProxy(&m_cProxy);

    m_cDlgDebug.Create(IDD_DLG_DEBUG, &m_ctrTab);
    m_pvPage[NSONVIF::PAGE_DEBUG] = &m_cDlgDebug;
    m_cDlgDebug.SetOnvifProxy(&m_cProxy);

    CRect rc;
    m_ctrTab.GetClientRect(rc);
    rc.top += 22;
    rc.bottom -= 1;
    rc.left += 1;
    rc.right -= 1;

    for (unsigned int i = 0; i < m_pvPage.size(); i++)
    {
        m_pvPage[i]->MoveWindow(&rc);
    }

    // first page
    m_nCurTab = NSONVIF::PAGE_DISCOVER;
    m_pvPage[m_nCurTab]->ShowWindow(SW_SHOW);

2.3 respond to click events

Is added OnTcnSelchangeTab event and realize

void COnvifClientDlg::OnTcnSelchangeTab(NMHDR *pNMHDR, LRESULT *pResult)
{
    *pResult = 0;

    m_pvPage[m_nCurTab]->ShowWindow(SW_HIDE);
    m_nCurTab = static_cast<NSONVIF::PAGE_TYPE>(m_ctrTab.GetCurSel());
    if (m_pvPage[m_nCurTab])
        m_pvPage[m_nCurTab]->ShowWindow(SW_SHOW);
}

Third, there is a problem

The original version of the code a bit rigid, less agile:

  • More control sequences macro definition. Namespace can be deleted.
  • Repeat the code but there are many differences. Such as initialization code.

Fourth, improved version

4.1 Variable declaration

    std::vector<CDialog *> m_pvPage;
    int m_nCurTab; // 直接用int即可
    CDiscover m_cDlgDiscover;
    CDeviceService m_cDlgDevice;
    CMediaService m_cDlgMedia;
    CImagingService m_cDlgImaging;
    CDebugInfo m_cDlgDebug;

    CTabCtrl m_ctrTab;

initialization

struct cDlgCtrl_t {
    LPCTSTR name;
    CDialogEx* dlg;
    int id;
};

    LPCTSTR lpName[10]; // make bigger...
    int i = 0;
    lpName[i++] = L"Discover";
    lpName[i++] = L"Device";
    lpName[i++] = L"Media";
    lpName[i++] = L"Imaging";
    lpName[i++] = L"Debug";
    
    i = 0;
    struct cDlgCtrl_t dlgCtrls[10]; // make bigger...
    dlgCtrls[i].name = lpName[i];
    dlgCtrls[i].dlg = &m_cDlgDiscover;
    dlgCtrls[i].id = IDD_DLG_DISCOVER;
    dlgCtrls[++i].name = lpName[i];
    dlgCtrls[i].dlg = &m_cDlgDevice;
    dlgCtrls[i].id = IDD_DLG_DEVICE;
    dlgCtrls[++i].name = lpName[i];
    dlgCtrls[i].dlg = &m_cDlgMedia;
    dlgCtrls[i].id = IDD_DLG_MEDIA;
    dlgCtrls[++i].name = lpName[i];
    dlgCtrls[i].dlg = &m_cDlgImaging;
    dlgCtrls[i].id = IDD_DLG_IMAGING;
    dlgCtrls[++i].name = lpName[i];
    dlgCtrls[i].dlg = &m_cDlgDebug;
    dlgCtrls[i].id = IDD_DLG_DEBUG;
    
    CRect rc;
    m_ctrTab.GetClientRect(rc);
    rc.top += 22;
    rc.bottom -= 1;
    rc.left += 1;
    rc.right -= 1;

    m_pvPage.resize(i+1);
    for (unsigned int i = 0; i < m_pvPage.size(); i++)
    {
        m_ctrTab.InsertItem(i, dlgCtrls[i].name);
        dlgCtrls[i].dlg->Create(dlgCtrls[i].id, &m_ctrTab);
        dlgCtrls[i].dlg->SetOnvifProxy(&m_cProxy);

        m_pvPage[i] = dlgCtrls[i].dlg;      
        m_pvPage[i]->MoveWindow(&rc);
    }

    m_nCurTab = 0;
    m_pvPage[m_nCurTab]->ShowWindow(SW_SHOW);

4.2 respond to click events

void COnvifClientDlg::OnTcnSelchangeTab(NMHDR *pNMHDR, LRESULT *pResult)
{
    *pResult = 0;

    m_pvPage[m_nCurTab]->ShowWindow(SW_HIDE);
    m_nCurTab = m_ctrTab.GetCurSel();
    if (m_pvPage[m_nCurTab])
        m_pvPage[m_nCurTab]->ShowWindow(SW_SHOW);
}

In contrast, the improved and better maintenance of the code.

Five to switch pages

At initialization, through each sub-dialog and call Create to create the window, note that at this time will call to the OnInitDialog function sub-dialog box (even if it did not show up).
When you switch Tab, child dialog box will not initialize again. Therefore, the display function OnTcnSelchangeTab the handover response. Examples are as follows:

void COnvifClientDlg::OnTcnSelchangeTab(NMHDR *pNMHDR, LRESULT *pResult)
{
    *pResult = 0;

    m_pvPage[m_nCurTab]->ShowWindow(SW_HIDE);
    m_nCurTab = m_ctrTab.GetCurSel();
    if (m_pvPage[m_nCurTab])
    {
        m_pvPage[m_nCurTab]->ShowWindow(SW_SHOW);
        if (m_nCurTab == 0) // 当切换到第0个子对话框时
        {
            CDiscover* dlg = (CDiscover*)m_pvPage[m_nCurTab];
            dlg->Reinit(); // 重新初始化
        }
    }
}

Note: if you can directly call the child dialog OnInitDialog function, not tested.

发布了481 篇原创文章 · 获赞 244 · 访问量 110万+

Guess you like

Origin blog.csdn.net/subfate/article/details/103651134