




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、一、關于 CSplitterWnd 類我們在使用 CuteFtp 或者 NetAnt 等工具的時候,一般都會被其復雜的界面所吸引,在這些界面中窗口被分割為若干的區域,真正做到了窗口的任意分割。那么我們自己如何創建類似的界面,也實現窗口的任意的分割呢?在 VC6.0 中這就需要使用到 CSplitterWnd類。CSplitterWnd 看上去像是一種特殊的框架窗口,每個窗口都被相同的或者不同的視圖所填充。當窗口被切分后用戶可以使用鼠標移動切分條來調整窗口的相對尺寸。雖然 VC6.0支持從 AppWizard 中創建分割窗口,但是自動加入的分割條總是不能讓我們滿意,因此我們還是通過手工增加代碼來
2、熟悉這個類。CSplitterWnd 的構造函數主要包括下面三個。BOOLCreate(CWnd*pParentWnd,intnMaxRows,intnMaxCols,SIZEsizeMin,CCreateContext*pContext,DWORDdwStyle,UINTnID);功能描述:該函數用來創建動態切分窗口。參數含義:pParentWnd 切分窗口的父框架窗口。nMaxRows,nMaxCols 是創建的最大的列數和行數。sizeMin 是窗格的現實大小。pContext 大多數情況下傳給父窗口。nID 是字窗口的 ID 號.BOOLCreateStatic(CWnd*pParen
3、tWnd,intnRows,intnCols,DWORDdwStyle,UINTnID)功能描述:用來創建切分窗口。參數含義同上。BOOLCreateView(introw,intcol,CruntimeClass*pViewClass,SIZEsizeinit,CcreateContext*pContext);功能描述:為靜態切分的窗口的網格填充視圖。在將視圖于切分窗口聯系在一起的時候必須先將切分窗口創建好。參數含義:同上。從 CSplitterWnd 源程序可以看出不管是使用動態創建 Create 還是使用靜態創建 CreateStatic,在函數中都調用了一個保護函數 CreateCom
4、mon,從下面的 CreateCommon 函數中的關鍵代碼可以看出創建 CSplitterWnd 的實質是創建了一系列的 MDI 子窗口。DWORDdwCreateStyle=dwStyle&(WS_HSCROLL|WS_VSCROLL);if(afxData.bWin4)dwCreateStyle&=WS_BORDER;/createwiththesamewnd-classasMDI-Frame(noerasebkgnd)if(!CreateEx(0,_afxWndMDIFrame,NULL,dwCreateStyle,0,0,0,0,pParentWnd-m_hWnd,(
5、HMENU)nID,NULL)returnFALSE;/createinvisible二、創建嵌套分割窗口2.12.1 創建動態分割窗口動態分割窗口使用 Create 方法。下面的代碼將創建 2x2 的窗格。m_wndSplitter.Create(this,2,2,CSize(100,100),pContext);但是動態創建的分割窗口的窗格數目不能超過 2x2,而且對于所有的窗格,都必須共享同一個視圖,所受的限制也比較多,因此我們不將動態創建作為重點。我們的主要精力放在靜態分割窗口的創建上。2.22.2 創建靜態分割窗口與動態創建相比,靜態創建的代碼要簡單許多,而且可以最多創建 16x16
6、 的窗格。不同的窗格我們可以使用 CreateView 填充不同的視圖。在這里我們將創建 CuteFtp 的窗口分割。CuteFtp 的分割情況如下:CCuteFTPViewCView2CView3CView4創建步驟:在創建之前我彳門必須先用 AppWizard 生成單文檔 CuteFTP,生成的視類為 CCuteFTPView.同時在增加三個視類或者從視類繼承而來的派生類 CView2,CView3CView4.增加成員:在 Cmainfrm.h 中我們將增加下面的代碼:CSplitterWndwndSplitter1;CSplitterWndwndSplitte重載 CMainFrame
7、:OnCreateClient()CMainFrame:OnCreateClient()函數:BOOLCMainFrame:OnCreateClient(LPCREATESTRUCT/*lpcs*/,CCreateContext*pContext)/創建一個靜態分欄窗口,分為三行一列if(m_wndSplitter1.CreateStatic(this,3,1)=NULL)returnFALSE;/將CCuteFTPView接到0行0列窗格上m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CCuteFTPView),CSize(100,100),pCon
8、text);m_wndSplitter1.CreateView(2,0,RUNTIME_CLASS(CView4),CSize(100,100),pContext);/將CView4連接至ij0行2列if(m_wndSplitter2.CreateStatic(&m_wndSplitter,1,2,WS_CHILD|WS_VISIBLE,m_wndSplitter.IdFromRowCol(1,0)=NULL)returnFALSE;/將第1行0列再分開1行2列/將CView2類連接到第二個分欄對象的0行0列m_wndSplitter2.CreateView(0,0,RUNTIME_C
9、LASS(CView2),CSize(400,300),pContext);/將CView3類連接到第二個分欄對象的0行1列m_wndSplitter2.CreateView(0,1,RUNTIME_CLASS(CView3),CSize(400,300),pContext);returnTRUE;2.32.3 實現各個分割區域的通信有文檔相連的視圖之間的通信由 AppWizard 生成的 CCuteFTPView 是與文檔相連的,同時我們也讓 CView2 與文檔相連,因此我們需要修改 CCuteFTPApp 的 InitInstance()函數,我們將增加下面的部分。AddDocTempl
10、ate(newCMultiDocTemplate(IDR_VIEW2TYPE,RUNTIME_CLASS(CMainDoc),RUNTIME_CLASS(CMDIChildWnd),RUNTIME_CLASS(CView2);我們現在來實現 CCuteFTPView 與 CView2 之間的通信。由于跟文檔類相連的視圖類是不能安全的與除文檔類之外的其余的視圖類通信的。因此我們只能讓他們都與文檔類通信。在文檔中我們設置相應的指針以用來獲的各個視圖。我們重載 CCuteFTPView:OnOpenDocument()函數。CCuteFTPView*pCuteFTPView;CView2*pView
11、2;POSITIONpos;CView*pView;while(pos!=NULL)pView=GetNextView(pos);if(pView-IsKindOf(RUNTIME_CLASS(CCuteFTPView)=NULL)pCuteFTPView=(CCuteFTPView*)pView;else(pView-IsKindOf(RUNTIME_CLASS(CCuteFTPView)=NULL)pView2=(CView2*)pView;這樣我們在文檔類中就獲的了跟它相連的所有的視圖的指針。如果需要在 CCuteFTPView 中調用 CView2 中的一個方法 DoIt()則代碼如下
12、:CCuteFTPDoc*pDoc=GetDocument();CView2*pView2=pDoc-pView3;pView3.DoIt();疣文檔視圖與文檔關聯視圖之間的通信 CView3 和 CView4 都是不與文檔相關聯的。我們現在實現 CView3 與 CView2 的通信.正如前面所說,CView2 只能安全的與 CCuteFTPDoc 通信,因此,CView3 如果需要跟 CView2 通信,也必須借助于文檔類。因此程序的關鍵是如何在 CView3中獲得文檔的指針。視圖類中沒有這樣的類成員可以用來直接訪問文檔類。但是我們知道在主窗口類 MainFrame 中我們可以獲得程序的任
13、意窗口類的指針。因此我們只要獲得程序主窗口了的指針,就可以解決問題了。代碼實現在 CView3 中訪問 CView2 中的 DoIt()方法。CView3 中的代碼如下:CMainFrame*MainFrame=(CMainFrame*)this-GetParent()-GetParent();CCuteFTPDoc*Doc=(CCuteFTPDoc*)MainFrame-GetActiveDocument();if(Doc!=NULL)Doc-DoIt();CCuteFTPDoc中的相應的處理函數DoIt()代碼如下:CView2*pView2;POSITIONpos;CView*pView
14、;while(pos!=NULL)pView=GetNextView(pos);if(pView-IsKindOf(RUNTIME_CLASS(CView2)=NULL)pView2=(CView2*)pView;pView2-DoIt();無文檔關聯視圖之間的通信 CView3 和 CView4 都是不跟文檔相連的,如何實現他們之間的通信呢。正如我們在上面所說的那樣,由于在主框架中我們可以訪問任意的視圖,因此我們的主要任務還是在程序中獲得主框架的指針。在 CView3 中訪問 CView4 中的方法DoIt()。CMainFrame*MainFrame=(CMainFrame*)this-G
15、etParent()-GetParent();CView4*View4=(CView4*)MainFrame-m_wndSplitter1.GetPane(2,0);View4-DoIt();到現在我們已經實現了 CuteFTP 的主窗口的框架并且能夠實現他們之間相互通信的框架。同樣的我們可以實現其他的一些流行界面例如 NetAnts,Foxmail 的分割。三、關于對話框的分割到目前為止,只有基于文檔/視圖的程序才能使用 CSplitterWnd,而基于對話框的應用程序卻不支持CSplitterWnd,但是如果我們在繼承類中重載一些虛擬方法,也能使 CSplitterWnd 在對話框程序中使
16、用。從 MFC 勺源程序 WinSplit.cpp 中可以看出,為了獲得父窗口的地方程序都調用了虛擬方法 GetParentFrame(),因此如果在對話框中使用,我們必須將它改為 GetParent();因此我們將 CSplitterWnd 的下面幾個方法重載。virtualvoidStartTracking(intht);virtualCWnd*GetActivePane(int*pRow=NULL,int*pCol=NULL);virtualvoidSetActivePane(introw,intcol,CWnd*pWnd=NULL);virtualBOOLOnCommand(WPARA
17、MwParam,LPARAMlParam);/CWnd*pView=NULL;/CFrameWnd*pFrameWnd=GetParentFrame();/ASSERT_VALID(pFrameWnd);/pView=pFrameWnd-GetActiveView();/if(pView=NULL)/pView=GetFocus();CWnd*pView=GetFocus();if(pView!=NULL&!IsChildPane(pView,pRow,pCol)pView=NULL;returnpView;voidCxSplitterWnd:SetActivePane(introw,
18、intcol,CWnd*pWnd)CWnd*pPane=pWnd=NULL?GetPane(row,col):pWnd;/下面加注釋粗體的是原有代碼的主要部分/FrameWnd*pFrameWnd=GetParentFrame();virtualBOOLOnNotify(WPARAMwParam,LPARAMIParam,LRESULT*pResult);virtualBOOLOnWndMsg(UINTmessage,WPARAMwParam,LPARAMlParam,LRESULT*pResult);具體實現如下,實現中我將給出原有代碼的主要部分以及修改后的代碼以作對比。在 cpp 文件中加
19、入下面的枚舉類型。enumHitTestValuenoHit=0,/vSplitterBox=1,hSplitterBox=2,表示沒有選中任何對象;bothSplitterBox=3,vSplitterBar1=101,/vSplitterBar15=115,hSplitterBar1=201,/hSplitterBar15=215,代表各個方向的水平分割條代表垂直方向的各個分割條splitterIntersection1=301,/splitterIntersection225=525代表各個交叉點CWnd*CxSplitterWnd:GetActivePane(int*pRow,int*
20、pCol)ASSERT_VALID(this);/卜面注釋粗體的是原有的代碼的主要部分/ASSERT_VALID(pFrameWnd);/pFrameWnd-SetActiveView(CView*)pPane);pPane-SetFocus();/修改后的語句voidCxSplitterWnd:StartTracking(intht)ASSERT_VALID(this);if(ht=noHit)return;/GetHitRectwillrestrictHm_rectLimitHasappropriateGetInsideRect(m_rectLimit);if(ht=splitterInt
21、ersection1&htIsKindOf(RUNTIME_CLASS(CView)/ASSERT_VALID(pView);/CFrameWnd*pFrameWnd=GetParentFrame();/ASSERT_VALID(pFrameWnd);/pView-OnActivateFrame(WA_INACTIVE,pFrameWnd);/stealfocusandcaptureSetCapture();SetFocus();/makesurenoupdatesarependingRedrawWindow(NULL,NULL,RDW_ALLCHILDREN|RDW_UPDATENO
22、W);/settrackingstateandappropriatecursorm_bTracking=TRUE;OnInvertTracker(m_rectTracker);if(m_bTracking2)OnInvertTracker(m_rectTracker2);m_htTrack=ht;SetSplitCursor(ht);BOOLCxSplitterWnd:OnCommand(WPARAMwParam,LPARAMlParam)if(CWnd:OnCommand(wParam,lParam)returnTRUE;/下面粗體的是原程序的語句/returnGetParentFrame(
23、)-SendMessage(WM_COMMAND,wParam,lParam);returnGetParent()-SendMessage(WM_COMMAND,wParam,lParam);BOOLCxSplitterWnd:OnNotify(WPARAMwParam,LPARAMlParam,LRESULT*pResult)if(CWnd二OnNotify(wParam,lParam,pResult)returnTRUE;/下面粗體的是源程序的語句/*pResult=GetParentFrame()-SendMessage(WM_NOTIFY,wParam,lParam);*pResult
24、=GetParent()-SendMessage(WM_NOTIFY,wParam,lParam);returnTRUE;)BOOLCxSplitterWnd:OnWndMsg(UINTmessage,WPARAMwParam,LPARAMIParam,LRESULT*pResult)/ThecodelinebelowisnecessaryifusingCxSplitterWndinaregulardll/AFX_MANAGE_STATE(AfxGetStaticModuleState();returnCWnd:OnWndMsg(message,wParam,lParam,pResult);)
25、這樣我們就可以在對話框中使用 CxSplitterWnd 類了。四、CSplitterWnd 的擴展CSplitterWnd 擴展話題是很多的,我們可以通過對原有方法的覆蓋或者增加新的方法來擴展CSplitterWnd。我們在此僅舉兩個方面的例子。鎖定切分條當用戶創建好分割窗口后,有時并不希望通過拖動切分條來調節窗口的大小。這時就必須鎖定切分條。鎖定切分條的最簡單的方法莫過于不讓 CSplitterWnd來處理 WM_LBUTTONDOWN,WM_MOUSEMOVE,WM_SETCURSOR這些消息交給 CWnd1口進行處理,從而屏蔽掉這些消息。拿 WM_LBUTTONDOWN 過程來說。修改
26、為如下:voidCXXSplitterWnd二OnLButtonDown(UINTnFlags,CPointpoint)CWnd:OnLButtonDown(nFlags,point);)其余的處理方法類似。切分條的定制由 Window 自己生成的切分條總是固定的,沒有任何的變化,我們在使用一些軟件比如 ACDSee勺時候卻能發現它們的切分條卻是和自動生成的切分條不一樣的。那么如何定制自己的切分條呢?通過重載 CSplitterWnd 的虛方法 OnDrawSplitter 和 OnInvertTracker 可以達到這樣的目的。下面的代碼生成的效果是分割窗口的邊界顏色為紅色,分割條的顏色為綠
27、色.代碼如下:voidCSplitterWndEx二OnDrawSplitter(CDC*pDC,ESplitTypenType,constCRect&rectArg)if(pDC=NULL)RedrawWindow(rectArg,NULL,RDW_INVALIDATE|RDW_NOCHILDREN);return;)ASSERT_VALID(pDC);CRectrc=rectArg;switch(nType)(casesplitBorder:/重畫分割窗口邊界,使之為紅色pDC-Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0);rc.InflateRect(-CX_BORDER,-CY_BORDER);pDC-Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0);return;casesplitBox:pDC-Draw3dRect(rc
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 證券從業資格證考試的疑難解析與答疑試題及答案
- 樣本處理中的常見問題試題及答案
- 2025年證券從業資格證考試中重要詞匯分析試題及答案
- 理財師的投資理念與實踐試題及答案
- 注會考試復習策略探討試題及答案
- 2024-2025學年高中歷史專題三近代中國的民主革命三新民主主義革命學案含解析人民版必修1
- 注冊會計師考試復習注意事項試題及答案
- 注冊會計師智力測試的相關試題與答案
- 行政管理師必考內容及答案
- 微生物導致的疾病傳播途徑試題及答案
- 第3節 第2課時 理想氣體狀態方程和氣體實驗定律的微觀解釋 教學課件
- 人教版初中數學《等腰三角形》-課件-
- 【必刷題型07】機械能守恒與能量守恒問題(原卷版)
- 2024年大學生信息素養大賽(省賽)練習考試題庫(含答案)
- 新人教版一年級數學下冊全冊教案(表格式)
- 2024年全國(保衛管理員安全及理論)知識考試題庫與答案
- 基礎模塊2 Unit5 Ancient Civilization單元測試-2025年中職高考英語一輪復習講練測(高教版2023修訂版·全國用)
- 《中國心力衰竭診斷和治療指南2024》解讀
- 月考分析與總結 課件高二下學期家長會
- DL∕T 1245-2013 水輪機調節系統并網運行技術導則
- 2024版父子房屋買賣合同協議書
評論
0/150
提交評論