MFC单文档添加CTabCtrl(二)
之前说了在单文档中建立一个Tab标签控件的方法,但是我一直觉得那个方法比较绕,没那么直接,最直接的方法是什么?那就是直接在C***View中Create一个CTabCtrl控件变量,然后给他添加一些对话框和消息响应什么的,这样就可以少用一个CFormView类,改来改去什么的最烦了~ 下面就是这个方法: 首先第一步还是建立你想要的几个最后作为标签页的对话框,我们这里还是用两个标签页来做例子,假设新建了两个对话框,生成相应的类,最重要的是,要将他们的Style设置成Child。假设ID为IDD_DIALLOG_TAB1,IDD_DIALLOG_TAB2。而且将它们的Boarder设置成None,以免影响美观效果。 然后回到我们的C***View类,假设建立的是CTabCtrlTestView,我们在里面添加两个变量:
CTabCtrl* m_TabCtrl; CTypedPtrArray<CObArray, CDialog*> m_DlgArray;
一个就是Tab控件,另一个是存储对话框的数组。 接下来写好View类的构造函数的析构函数:
CTabCtrlTestView::CTabCtrlTestView() { m_TabCtrl = NULL; } CTabCtrlTestView::~CTabCtrlTestView() { if (m_TabCtrl) delete m_TabCtrl; int num = m_DlgArray.GetSize(); for (int i = 0; i < num; i++) { if (m_DlgArray[i]) delete m_DlgArray[i]; } }
然后给View类添加OnCreate,OnSize和OnSetFocus三个消息函数:(这里我们要自己定义ID_TABCTRL这个宏这不用我说了吧。。)
int CTabCtrlTestView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; m_TabCtrl = new CTabCtrl; if (m_TabCtrl->Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, CRect(0, 0, 0, 0), this, ID_TABCTRL) == FALSE) return -1; CreatePages(); return 0; } void CTabCtrlTestView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); m_TabCtrl->MoveWindow(0, 0, cx, cy); } void CTabCtrlTestView::OnSetFocus(CWnd* pOldWnd) { CView::OnSetFocus(pOldWnd); OnTabSelChange(NULL, NULL); }
这里遇到的还没定义的函数自然先别急,下文都会提到的。 接下来就是给TabCtrl添加两个消息响应函数OnTabSelChange和OnTabSelChanging,方法我也再说一下吧,在View类的DECLARE_MESSAGE_MAP()下面添加:
afx_msg void OnTabSelChanging(NMHDR* pnmhdr, LRESULT* pResult); afx_msg void OnTabSelChange(NMHDR* pnmhdr, LRESULT* pResult);
然后在View的CPP源文件中BEGIN_MESSAGE_MAP(CTabCtrlTestView, CView)和END_MESSAGE_MAP()之间消息映射,如下面所示:
BEGIN_MESSAGE_MAP(CTabCtrlTestView, CView) // 标准打印命令 ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview) ON_WM_CREATE() ON_WM_SIZE() ON_WM_SETFOCUS() ON_NOTIFY(TCN_SELCHANGE, ID_TABCTRL, OnTabSelChange) ON_NOTIFY(TCN_SELCHANGING, ID_TABCTRL, OnTabSelChanging) ON_COMMAND(ID_TEST, &CTabCtrlTestView::OnTest) ON_WM_KEYDOWN() END_MESSAGE_MAP()
下面是这两个函数的本体:
void CTabCtrlTestView::OnTabSelChanging(NMHDR* pnmhdr, LRESULT* pResult) { int sel_index = m_TabCtrl->GetCurSel(); m_DlgArray[sel_index]->ShowWindow(SW_HIDE); *pResult = FALSE; } void CTabCtrlTestView::OnTabSelChange(NMHDR* pnmhdr, LRESULT* pResult) { RECT rc; m_TabCtrl->GetItemRect (0, &rc); int sel_index = m_TabCtrl->GetCurSel(); m_DlgArray[sel_index]->SetWindowPos ( NULL, rc.left + 5, rc.bottom + 5, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); m_DlgArray[sel_index]->SetFocus(); }
最后就是OnCreate里面用到的CreatePage这个函数了:
void CTabCtrlTestView::CreatePages() { CDialog* dlg; dlg = new CTab1; m_DlgArray.Add(dlg); dlg->Create(IDD_DIALOG_TAB1, m_TabCtrl); dlg = new CTab2; m_DlgArray.Add(dlg); dlg->Create(IDD_DIALOG_TAB2, m_TabCtrl); CString str; for (int i = 0; i < NUM_PAGES; i++) { dlg = m_DlgArray[i]; str.Format("Tab%d",i); m_TabCtrl->InsertItem(i, str); } }
如果要在View类中访问对话框的内容,自然就是:
((CStatic*)m_DlgArray[1]->GetDlgItem(IDC_STATIC))->SetWindowText("aaaa");
最后假设要添加一个Ctrl+Tab的快捷键切换页面,那就在View类中添加一个BOOL HandleKeyDownMsg(MSG* pMsg)函数,如下:
BOOL CTabCtrlTestView::HandleKeyDownMsg( MSG* pMsg ) { if (pMsg->wParam == VK_TAB && GetKeyState(VK_CONTROL) < 0) { BOOL shift_down = GetKeyState(VK_SHIFT) < 0; int old_sel = m_TabCtrl->GetCurSel(); int num = m_TabCtrl->GetItemCount() ; int new_sel = shift_down ? (old_sel + (num -1)) % num : (old_sel + 1) % num; RECT r; m_TabCtrl->GetItemRect(new_sel, &r); m_TabCtrl->SendMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(r.left, r.top)); return TRUE; } if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) return TRUE; }
但是这显然没完,还要在APP类中重写PreTranslateMessage函数,本体如下:
BOOL CTabCtrlTestApp::PreTranslateMessage(MSG* pMsg) { // TODO: 在此添加专用代码和/或调用基类 if (pMsg->message == WM_KEYDOWN) { CView* view = ((CFrameWnd *) AfxGetMainWnd())->GetActiveView(); if (((CTabCtrlTestView *) view)->HandleKeyDownMsg(pMsg)) return TRUE; } return CWinApp::PreTranslateMessage(pMsg); }
【完】
本文内容遵从CC版权协议,转载请注明出自http://www.kylen314.com