程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 在MDI程序中實現類似WPS2000的文件切換標簽

在MDI程序中實現類似WPS2000的文件切換標簽

編輯:關於VC++

用過WPS2000的朋友,肯定對其文件切換功能有很深的印象。當打開多個文件時,他可以使我們快速的切換到指定的文件。本文將詳細地說明如何在自己的MDI程序中加入這樣一個標簽。 圖一是本文例子程序運行畫面。

圖一 例子程序運行畫面

開始之前,我們先對WPS2000中的文件切換標簽做簡單分析,這是一個Tab標簽,該標簽具有以下功能:

1、當鼠標移到Tab標簽上時,對應的文字將變為藍色;

2、新建或打開一個文件時,Tab標簽會以文件標題為標簽文本自動加入一項;

3、切換Tab標簽時,對應的文件窗口會跟著切換;

4、當我們激活不同的文件窗口時,Tab標簽會自動切換;

5、關閉一個文件窗口時,Tab標簽中對應的項會自動消失。

在本文的例子中,除實現上述功能外,還作如下修改:

1、增加雙擊Tab標簽時最大化、恢復子窗口功能;

2、修改Tab標簽為按鈕風格。

具體思路:

在MDI程序中加入一個包含Tab標簽的對話框條,並加入類CViewManager,該類用一個指針數組存放所有打開子窗口的視指針,用一個字符串數組存放文檔標題。在視類的初始化函數OnInitUpdate() 裡取得視指針及文檔標題,存放到CViewManager的數組中,並在Tab標簽中加入一項。在視類的析構函數裡從Tab標簽和CViewManager的數組中刪除對應的項。切換Tab標簽時,取得對應子窗口的指針,並以該指針為參數調用CMDIFrameWnd::MDIActivate()激活這個子窗口。下面請看具體的實現步驟: 

一、在VC6.0中,用向導創建一個MDI工程TabMDIDemo。在向導各步中均采用默認項

二、為工程加入Tab標簽對話框條

1、在工作區的ResourceView中加入一個對話框模板IDD_TAB_DLG_BAR,按如下設置:

Style: Child
Border: Thin
去掉標題條和系統菜單選項;
字體:宋體,字號:10

在模板中加入一個Tab標簽控件IDC_TAB,按如下設置:

選中按鈕選項。//這使的Tab標簽呈現按鈕風格
選中Hot Track選項。//這使得鼠標移上時文字變藍

仔細調整對話框條及Tab控件的位置、尺寸。創建主框架時,將以該模板創建出Tab標簽對話框條。

2、利用類向導加入類CMyTab,派生於CTabCtrl。

3、利用類向導為類CMyTab添加TCN_SELCHANGE通知消息映射函數,實現文件切換,編輯如下:

void CMyTab::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
int idx = GetCurSel();
TC_ITEM ti;
ti.mask = TCIF_PARAM;
GetItem(idx, &ti);
CView * pView = (CView *) ti.lParam;
((CMDIFrameWnd *)AfxGetMainWnd())->MDIActivate((pView->GetParent())->GetParent());
*pResult = 0;
*pResult = 0;
}

4、利用類向導為類CMyTab添加WM_LBUTTONDBLCLK消息映射函數,實現雙擊時最大化或恢復子窗口,編輯如下:

void CMyTab::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
int idx = GetCurSel();
TC_ITEM ti;
ti.mask = TCIF_PARAM;
GetItem(idx, &ti);
CView * pView = (CView *) ti.lParam;
((CMDIFrameWnd *)AfxGetMainWnd())->MDIActivate((pView->GetParent())->GetParent());
// maximize or restore MDIChild window based on its current state
BOOL bMaximize=FALSE;
CWnd* pActiveWnd=((CMDIFrameWnd *)AfxGetMainWnd())->MDIGetActive(&bMaximize);
if(bMaximize)
((CMDIFrameWnd *)AfxGetMainWnd())->MDIRestore(pActiveWnd);
else
((CMDIFrameWnd *)AfxGetMainWnd())->MDIMaximize(pActiveWnd);
}

5、在MainFrm.h中加入:#include "MyTab.h"

6、為主框架類CMainFrame加入如下成員變量:

protected:
CDialogBar m_wndTabBar;
public:
CMyTab m_MyTab;

7、在菜單資源"查看"中加入菜單項"文件切換",ID值為ID_VIEW_TAB_BAR。在MainFrm.cpp中消息映射部分加入以下兩行:

ON_COMMAND_EX(ID_VIEW_TAB_BAR, OnBarCheck)
ON_UPDATE_COMMAND_UI(ID_VIEW_TAB_BAR, OnUpdateControlBarMenu)

8、在CMainFrame::OnCreate()加入以下代碼:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{  
//向導生成代碼略去
//創建TAB條
if (!m_wndTabBar.Create(this, IDD_TAB_DLG_BAR,
CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_HIDE_INPLACE,
ID_VIEW_TAB_BAR)) //ID_VIEW_TAB_BAR是菜單命令ID,用於顯示或隱藏對話框條
{
TRACE0("Failed to create dialog bar m_wndDialogbar\n");
return -1; // fail to create
}
//m_wndTabBar.EnableDocking(CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT);
//EnableDocking(CBRS_ALIGN_ANY);
//DockControlBar(&m_wndTabBar);
//將m_MyTab與控件IDC_TAB綁定
m_MyTab.SubclassDlgItem(IDC_TAB, &m_wndTabBar);
return 0;
}

9、為類CMainFrame添加WM_SIZE消息映射函數,如下:

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CMDIFrameWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
CRect rcClient;
GetClientRect(&rcClient);
int left,top,right,bottom;
left=rcClient.left;
top=rcClient.top;
right=rcClient.right;
bottom=rcClient.bottom;
m_wndTabBar.MoveWindow(left,top+24,right-left,24,TRUE);
CRect rcTab;
m_wndTabBar.GetClientRect(&rcTab);
CTabCtrl *pMyTab=(CTabCtrl *)(m_wndTabBar.GetDlgItem(IDC_TAB));
pMyTab->MoveWindow(rcTab,TRUE);
}

三、手工創建類CViewManager

新建兩個文件ViewManager.h、ViewManager.cpp ,並添加到當前工程。類的源碼參見本文所附例子。下面對其成員作簡單說明:

OnActivateView(); //當一個視被激活時,該函數被調用,刷新Tab控件

GetWindowNum(); //返回打開的子窗口數

RemoveAll(); //清空數組arViews、arViewTitles

RemoveView(); //用於在數組及Tab控件中刪除一項

AddView(); //用於在數組及Tab控件中加入一項

CViewManager(); //構造函數

~CViewManager(); //析構函數,清空數組arViews、arViewTitles

CPtrArray arViews; //用來存放子窗口的視指針

CstringArray arViewTitles; //用來存放文檔標題

bool bClosing; //用於表示程序是否正在關閉

四、實現文件切換。

1、在MainFrm.h文件加入:#include "ViewManager.h"

2、為類CMainFrame加入公有成員變量: public:
CViewManager m_ViewManager;

3、在視類TabMDIDemoView.cpp文件中加入:#include "MainFrm.h"

4、重載視類的OnInitialUpdate()函數,編輯如下:

void CTabMDIDemoView::OnInitialUpdate()
{
CView::OnInitialUpdate();

//取得文檔標題及視指針並加入到視管理器數組及tab控件中
CMDIDialogbarDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CString cs=pDoc->GetTitle();
((CMainFrame*)AfxGetMainWnd())->m_ViewManager.AddView(cs,this);
}

5、在視類的析構函數中加入以下代碼:

CTabMDIDemoView::~CTabMDIDemoView()
{
((CMainFrame*)AfxGetMainWnd())->m_ViewManager.RemoveView(this);
}

6、重載視類的OnActivateView()函數,編輯如下:

void CTabMDIDemoView::OnActivateView(BOOL bActivate,
CView* pActivateView,
CView* pDeactiveView)
{
// TODO: Add your specialized code here and/or call the base class
((CMainFrame*)AfxGetMainWnd())->m_ViewManager.OnActivateView(bActivate, this);
CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}

五、編譯

本文配套源碼

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved