天天看點

如何使用CTabCtrl來實作多頁面屬性對話框?

關于在VC中如何使用這個控件,大體思路可以這樣:

1)在資料總管中建立幾個Dialog, 分别生成相應的類(基于CDialog),注意,要設定Dialog的Style為"Child", Border為"None";

2)在CDialog::OnInitDialog中,調用CTabCtrl::InsertItem(...)方法添加幾個頁面

3)調用CDialog的Create方法建立幾個對話框變量;

3)在主視窗中,捕獲Tab Control的頁選擇事件,在其中對索引值進行分類,然後就顯示你的對話框,注意顯示一個的同時,要隐藏其他的對話框。

下面是個測試程式:

如何使用CTabCtrl來實作多頁面屬性對話框?

主對話框:

// TmpTstDlg.h : header file

//

#if !defined(AFX_TMPTSTDLG_H__881692D3_4A86_42CD_89F6_1FCB692A13F9__INCLUDED_)

#define AFX_TMPTSTDLG_H__881692D3_4A86_42CD_89F6_1FCB692A13F9__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include "TreeDlg.h"

#include "TstDlg.h"

#include "OtherDlg.h"

/

// CTmpTstDlg dialog

class CTmpTstDlg : public CDialog

{

// Construction

public:

 CTmpTstDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data

 //{{AFX_DATA(CTmpTstDlg)

 enum { IDD = IDD_TMPTST_DIALOG };

 CTabCtrl m_ctrlTab;

 //}}AFX_DATA

 // ClassWizard generated virtual function overrides

 //{{AFX_VIRTUAL(CTmpTstDlg)

 public:

 virtual BOOL PreTranslateMessage(MSG* pMsg);

 protected:

 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

 //}}AFX_VIRTUAL

// Implementation

protected:

 HICON m_hIcon;

 CMenu m_menuMain;

 void AdjustCtrl();

 // Generated message map functions

 //{{AFX_MSG(CTmpTstDlg)

 virtual BOOL OnInitDialog();

 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

 afx_msg void OnPaint();

 afx_msg HCURSOR OnQueryDragIcon(); 

 afx_msg void OnDestroy();

 afx_msg void OnSize(UINT nType, int cx, int cy);

 afx_msg void OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult);

 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

 afx_msg void OnAbout();

 //}}AFX_MSG

 DECLARE_MESSAGE_MAP()

private:

 CTreeDlg m_dlgTree;

 CTstDlg m_dlgTst;

 COtherDlg m_dlgOther;

};

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_TMPTSTDLG_H__881692D3_4A86_42CD_89F6_1FCB692A13F9__INCLUDED_)

// TmpTstDlg.cpp : implementation file

//

#include "stdafx.h"

#include "TmpTst.h"

#include "TmpTstDlg.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

#pragma comment(lib, "vfw32.lib")

#pragma comment(lib, "User32.lib")

/

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog

{

public:

 CAboutDlg();

// Dialog Data

 //{{AFX_DATA(CAboutDlg)

 enum { IDD = IDD_ABOUTBOX };

 //}}AFX_DATA

 // ClassWizard generated virtual function overrides

 //{{AFX_VIRTUAL(CAboutDlg)

 protected:

 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

 //}}AFX_VIRTUAL

// Implementation

protected:

 //{{AFX_MSG(CAboutDlg)

 //}}AFX_MSG

 DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

 //{{AFX_DATA_INIT(CAboutDlg)

 //}}AFX_DATA_INIT

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

 CDialog::DoDataExchange(pDX);

 //{{AFX_DATA_MAP(CAboutDlg)

 //}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

 //{{AFX_MSG_MAP(CAboutDlg)

  // No message handlers

 //}}AFX_MSG_MAP

END_MESSAGE_MAP()

/

// CTmpTstDlg dialog

CTmpTstDlg::CTmpTstDlg(CWnd* pParent )

 : CDialog(CTmpTstDlg::IDD, pParent)

{

 //{{AFX_DATA_INIT(CTmpTstDlg)

  // NOTE: the ClassWizard will add member initialization here

 //}}AFX_DATA_INIT

 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32

 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void CTmpTstDlg::DoDataExchange(CDataExchange* pDX)

{

 CDialog::DoDataExchange(pDX);

 //{{AFX_DATA_MAP(CTmpTstDlg)

 DDX_Control(pDX, IDC_TAB1, m_ctrlTab);

 //}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CTmpTstDlg, CDialog)

 //{{AFX_MSG_MAP(CTmpTstDlg)

 ON_WM_SYSCOMMAND()

 ON_WM_PAINT()

 ON_WM_QUERYDRAGICON() 

 ON_WM_DESTROY()

 ON_WM_SIZE()

 ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnSelchangeTab1)

 ON_WM_CREATE()

 ON_COMMAND(ID_ABOUT, OnAbout)

 //}}AFX_MSG_MAP

END_MESSAGE_MAP()

/

// CTmpTstDlg message handlers

BOOL CTmpTstDlg::OnInitDialog()

{

 CDialog::OnInitDialog();

 // Add "About..." menu item to system menu.

 // IDM_ABOUTBOX must be in the system command range.

 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);

 if (pSysMenu != NULL)

 {

  CString strAboutMenu;

  strAboutMenu.LoadString(IDS_ABOUTBOX);

  if (!strAboutMenu.IsEmpty())

  {

   pSysMenu->AppendMenu(MF_SEPARATOR);

   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

  }

 }

 // Set the icon for this dialog.  The framework does this automatically

 //  when the application's main window is not a dialog

 SetIcon(m_hIcon, TRUE);   // Set big icon

 SetIcon(m_hIcon, FALSE);  // Set small icon

 // TODO: Add extra initialization here

 WORD wVersion = 0;

 WSAData sttWsa;

 CString m_strErrMsg;

 memset(&sttWsa, 0, sizeof(WSAData));

 wVersion = MAKEWORD(2, 0); 

 if (0 != WSAStartup(wVersion, &sttWsa))

 {

  m_strErrMsg.Format("Fail to initialize socket of version [%u], and error no is [%ld]",

   wVersion, WSAGetLastError());

  MessageBox(m_strErrMsg,  "Initialization Error", MB_OK + MB_ICONSTOP);

  WSACleanup();

  return -1;

 }

 ASSERT(m_menuMain.LoadMenu(IDR_MENU1));

 ASSERT(SetMenu(&m_menuMain));

 this->AdjustCtrl();

 //add pages for tab

 BOOL bRet = FALSE;

 bRet = m_ctrlTab.InsertItem(0, _T("樹操作測試"));

 bRet = m_ctrlTab.InsertItem(1, _T("臨時測試"));

 bRet = m_ctrlTab.InsertItem(2, "其他測試");

 ASSERT(bRet);

 return TRUE;  // return TRUE  unless you set the focus to a control

}

void CTmpTstDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

 if ((nID & 0xFFF0) == IDM_ABOUTBOX)

 {

  CAboutDlg dlgAbout;

  dlgAbout.DoModal();

 }

 else

 {

  CDialog::OnSysCommand(nID, lParam);

 }

}

// If you add a minimize button to your dialog, you will need the code below

//  to draw the icon.  For MFC applications using the document/view model,

//  this is automatically done for you by the framework.

void CTmpTstDlg::OnPaint()

{

 if (IsIconic())

 {

  CPaintDC dc(this); // device context for painting

  SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

  // Center icon in client rectangle

  int cxIcon = GetSystemMetrics(SM_CXICON);

  int cyIcon = GetSystemMetrics(SM_CYICON);

  CRect rect;

  GetClientRect(&rect);

  int x = (rect.Width() - cxIcon + 1) / 2;

  int y = (rect.Height() - cyIcon + 1) / 2;

  // Draw the icon

  dc.DrawIcon(x, y, m_hIcon);

 }

 else

 {

  CDialog::OnPaint();

  //this->AdjustCtrl();

 }

}

// The system calls this to obtain the cursor to display while the user drags

//  the minimized window.

HCURSOR CTmpTstDlg::OnQueryDragIcon()

{

 return (HCURSOR) m_hIcon;

}

int CTmpTstDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

 if (CDialog::OnCreate(lpCreateStruct) == -1)

  return -1;

 // TODO: Add your specialized creation code here

 ASSERT(m_dlgTree.Create(IDD_DIALOG1, GetDlgItem(IDC_TAB1)));

 ASSERT(m_dlgTst.Create(IDD_DIALOG2, GetDlgItem(IDC_TAB1)));

 ASSERT(m_dlgOther.Create(IDD_DIALOG3, GetDlgItem(IDC_TAB1)));

 return 0;

}

void CTmpTstDlg::OnDestroy()

{

 CDialog::OnDestroy();

 // TODO: Add your message handler code here

 m_menuMain.DestroyMenu();

 m_dlgTree.DestroyWindow();

 m_dlgTst.DestroyWindow();

 m_dlgOther.DestroyWindow();

}

void CTmpTstDlg::AdjustCtrl()

{

 int iCapHgh = ::GetSystemMetrics(SM_CYCAPTION);//caption height:19(default)

 TRACE("Caption height is %ld in pixels/n", iCapHgh);

 int iBordWid = ::GetSystemMetrics(SM_CXBORDER);//border width:1(default)

 int iBordHgh = ::GetSystemMetrics(SM_CYBORDER);//border height:1(default)

 TRACE("Horizonal border width is %ld in pixels/n", iBordWid);

 TRACE("Vertical border height is %ld in pixels/n", iBordHgh);

 CRect rcClient(0, 0, 0, 0);

 GetClientRect(rcClient);

 CWnd* pWndOk = GetDlgItem(IDOK);

 CWnd* pWndCancel = GetDlgItem(IDCANCEL);

 ASSERT_VALID(pWndOk);

 ASSERT_VALID(pWndCancel);

 CRect rcBtnOk(0, 0, 0, 0);

 CRect rcBtnCancel(0, 0, 0, 0);

 pWndOk->GetWindowRect(rcBtnOk);

 ScreenToClient(rcBtnOk);

 pWndOk->GetWindowRect(rcBtnCancel);

 ScreenToClient(rcBtnCancel);

 //calculate coordinates of 'IDOK' button

 int iBtnWid = rcBtnOk.Width();

 int iBtnHgh = rcBtnOk.Height();

 rcBtnOk.left = rcClient.right - 2*iBtnWid - 1;

 rcBtnOk.top = rcClient.bottom - iBtnHgh;

 rcBtnOk.right = rcBtnOk.left + iBtnWid;

 rcBtnOk.bottom = rcBtnOk.top + iBtnHgh;

 //calculate coordinates of 'IDCANCEL' button

 rcBtnCancel.left = rcBtnOk.right + 1;

 rcBtnCancel.top = rcBtnOk.top;

 rcBtnCancel.right = rcBtnCancel.left + iBtnWid;

 rcBtnCancel.bottom = rcBtnOk.bottom;

 BOOL bRet = pWndOk->SetWindowPos(NULL, rcBtnOk.left, rcBtnOk.top,

  rcBtnOk.Width(), rcBtnOk.Height(), SWP_NOSIZE | SWP_NOZORDER); 

 ASSERT(bRet);

 bRet = pWndCancel->SetWindowPos(NULL, rcBtnCancel.left, rcBtnCancel.top,

  rcBtnCancel.Width(), rcBtnCancel.Height(), SWP_NOSIZE | SWP_NOZORDER);

 ASSERT(bRet);

 CRect rcTab(rcClient);

 rcTab.bottom = rcBtnOk.top - 1;

 m_ctrlTab.MoveWindow(rcTab);

 //ajust coordinates

 CRect rc;

 m_ctrlTab.GetClientRect(rc); 

 rc.top+=20;

 rc.bottom-=4;

 rc.left+=4;

 rc.right-=4;

 //adjust per page size

 m_dlgTree.MoveWindow(rc);

 m_dlgTst.MoveWindow(rc);

 m_dlgOther.MoveWindow(rc);

 //show first page at first

 m_dlgTree.ShowWindow(SW_SHOW);

 m_ctrlTab.SetCurSel(0);//set focus on first page

}

void CTmpTstDlg::OnSize(UINT nType, int cx, int cy)

{  

 // TODO: Add your message handler code here

 CDialog::OnSize(nType, cx, cy);

 if (SIZE_MAXIMIZED == nType)

 {

  this->AdjustCtrl();

 }

 if (NULL != GetDlgItem(IDOK))//very mild, modified

 {

  if (SIZE_RESTORED == nType)

  {

   this->AdjustCtrl();

  } 

 }

}

void CTmpTstDlg::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)

{

 // TODO: Add your control notification handler code here

 int iIndex = m_ctrlTab.GetCurSel();

 switch (iIndex)

 {

  case -1:

  {

   break;

  }

  case 0:

  {          

   m_dlgTree.ShowWindow(SW_SHOW);

   m_dlgTst.ShowWindow(SW_HIDE);

   m_dlgOther.ShowWindow(SW_HIDE);

   break;

  }

  case 1:

  {  

   m_dlgTree.ShowWindow(SW_HIDE);

   m_dlgTst.ShowWindow(SW_SHOW);

   m_dlgOther.ShowWindow(SW_HIDE);

   break;

  }

  case 2:

  { 

   m_dlgTree.ShowWindow(SW_HIDE);

   m_dlgTst.ShowWindow(SW_HIDE);

   m_dlgOther.ShowWindow(SW_SHOW);

   break;

  }

  default:

  {

   break;

  }

 }

 *pResult = 0;

}

void CTmpTstDlg::OnAbout()

{

 // TODO: Add your command handler code here

 CAboutDlg dlgAbout;

 dlgAbout.DoModal();

}

BOOL CTmpTstDlg::PreTranslateMessage(MSG* pMsg)

{

 // TODO: Add your specialized code here and/or call the base class

 if (pMsg->message == WM_KEYDOWN)

 {

  if (VK_ESCAPE == pMsg->wParam)

  {

   return FALSE;

  }

 }

 return CDialog::PreTranslateMessage(pMsg);

}