国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
VC實現(xiàn)窗口的任意分割
一、關(guān)于CSplitterWnd類
我們在使用CuteFtp或者NetAnt等工具的時候,一般都會被其復(fù)雜的界面所吸引,在這些界面中窗口被分割為若干的區(qū)域,真正做到了窗口的任意分割。 那么我們自己如何創(chuàng)建類似的界面,也實現(xiàn)窗口的任意的分割呢 ?在VC6.0中這就需要使用到CSplitterWnd類。CSplitterWnd看上去像是一種特殊的框架窗口,每個窗口都被相同的或者不同的視圖所填充。當(dāng)窗口被切分后用戶可以使用鼠標移動切分條來調(diào)整窗口的相對尺寸。雖然VC6.0支持從AppWizard中創(chuàng)建分割窗口,但是自動加入的分割條總是不能讓我們滿意,因此我們還是通過手工增加代碼來熟悉這個類。
CSplitterWnd的構(gòu)造函數(shù)主要包括下面三個。
BOOL Create(CWnd* pParentWnd,int nMaxRows,int nMaxCols,SIZE sizeMin,CCreateContext* pContext,DWORD dwStyle,UINT nID);功能描述:該函數(shù)用來創(chuàng)建動態(tài)切分窗口。 參數(shù)含義:pParentWnd 切分窗口的父框架窗口。 nMaxRows,nMaxCols是創(chuàng)建的最大的列數(shù)和行數(shù)。 sizeMin是窗格的現(xiàn)實大小。 pContext 大多數(shù)情況下傳給父窗口。 nID是字窗口的ID號.BOOL CreateStatic(CWnd* pParentWnd,int nRows,int nCols,DWORD dwStyle,UINT nID) 功能描述:用來創(chuàng)建切分窗口。 參數(shù)含義同上。BOOL CreateView (int row,int col,CruntimeClass* pViewClass,SIZE sizeinit,CcreateContext* pContext);功能描述:為靜態(tài)切分的窗口的網(wǎng)格填充視圖。在將視圖于切分窗口聯(lián)系在一起的時候必 須先將切分窗口創(chuàng)建好。
參數(shù)含義:同上。
從CSplitterWnd源程序可以看出不管是使用動態(tài)創(chuàng)建Create還是使用靜態(tài)創(chuàng)建CreateStatic,在函數(shù)中都調(diào)用了一個保護函數(shù)CreateCommon,從下面的CreateCommon函數(shù)中的關(guān)鍵代碼可以看出創(chuàng)建CSplitterWnd的實質(zhì)是創(chuàng)建了一系列的MDI子窗口。
DWORD dwCreateStyle = dwStyle & ~(WS_HSCROLL|WS_VSCROLL);if (afxData.bWin4)dwCreateStyle &= ~WS_BORDER; //create with the same wnd-class as MDI-Frame (no erase bkgnd)if (!CreateEx(0, _afxWndMDIFrame, NULL, dwCreateStyle,0, 0, 0, 0,pParentWnd->m_hWnd, (HMENU)nID, NULL))return FALSE; // create invisible
二、創(chuàng)建嵌套分割窗口
2.1創(chuàng)建動態(tài)分割窗口
動態(tài)分割窗口使用Create方法。下面的代碼將創(chuàng)建2x2的窗格。
m_wndSplitter.Create(this,2,2,CSize(100,100),pContext);
但是動態(tài)創(chuàng)建的分割窗口的窗格數(shù)目不能超過2x2,而且對于所有的窗格,都必須共享同一個視圖,所受的限制也比較多,因此我們不將動態(tài)創(chuàng)建作為重點。我們的主要精力放在靜態(tài)分割窗口的創(chuàng)建上。
2.2創(chuàng)建靜態(tài)分割窗口
與動態(tài)創(chuàng)建相比,靜態(tài)創(chuàng)建的代碼要簡單許多,而且可以最多創(chuàng)建16x16的窗格。不同的窗格我們可以使用CreateView填充不同的視圖。
在這里我們將創(chuàng)建CuteFtp的窗口分割。CuteFtp的分割情況如下: CCuteFTPView
CView2
CView3
CView4
創(chuàng)建步驟:
▲ 在創(chuàng)建之前我們必須先用AppWizard生成單文檔CuteFTP,生成的視類為 CCuteFTPView.同時在增加三個視類或者從視類繼承而來的派生類CView2,CView3 CView4.
▲ 增加成員:
在Cmainfrm.h中我們將增加下面的代碼:
CSplitterWnd wndSplitter1;CSplitterWnd wndSplitter2;▲ 重載CMainFrame::OnCreateClient()函數(shù):BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext){ //創(chuàng)建一個靜態(tài)分欄窗口,分為三行一列if(m_wndSplitter1.CreateStatic(this,3,1)==NULL)return FALSE;//將CCuteFTPView連接到0行0列窗格上m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CCuteFTPView),CSize(100,100), pContext);m_wndSplitter1.CreateView(2,0,RUNTIME_CLASS(CView4),CSize(100,100),pContext);//將CView4連接到0行2列if(m_wndSplitter2.CreateStatic(&m_wndSplitter,1,2,WS_CHILD|WS_VISIBLE,m_wndSplitter.IdFromRowCol(1, 0))==NULL)return FALSE; //將第1行0列再分開1行2列//將CView2類連接到第二個分欄對象的0行0列m_wndSplitter2.CreateView(0,0,RUNTIME_CLASS(CView2),CSize(400,300),pContext);//將CView3類連接到第二個分欄對象的0行1列m_wndSplitter2.CreateView(0,1,RUNTIME_CLASS(CView3),CSize(400,300),pContext);return TRUE;} 2.3實現(xiàn)各個分割區(qū)域的通信
■有文檔相連的視圖之間的通信
由AppWizard生成的CCuteFTPView是與文檔相連的,同時我們也讓CView2與文檔相連,因此我們需要修改CCuteFTPApp的InitInstance()函數(shù),我們將增加下面的部分。
AddDocTemplate (new CMultiDocTemplate(IDR_VIEW2TYPE,RUNTIME_CLASS(CMainDoc),RUNTIME_CLASS(CMDIChildWnd),RUNTIME_CLASS(CView2))); 我們現(xiàn)在來實現(xiàn)CCuteFTPView與CView2之間的通信。由于跟文檔類相連的視圖類 是不能安全的與除文檔類之外的其余的視圖類通信的。因此我們只能讓他們都與文檔 類通信。在文檔中我們設(shè)置相應(yīng)的指針以用來獲的各個視圖。我們重載 CCuteFTPView::OnOpenDocument()函數(shù);
CCuteFTPView* pCuteFTPView;
CView2* pView2;POSITION pos;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中調(diào)用CView2中的一個方法DoIt()則代碼如下:
CCuteFTPDoc* pDoc=GetDocument();
CView2* pView2=pDoc->pView3;
pView3.DoIt();
■無文檔視圖與文檔關(guān)聯(lián)視圖之間的通信
CView3和CView4都是不與文檔相關(guān)聯(lián)的。我們現(xiàn)在實現(xiàn)CView3與CView2的通信.正如前面所說,CView2只能安全的與CCuteFTPDoc通信,因此,CView3如果需要跟CView2通信,也必須借助于文檔類。因此程序的關(guān)鍵是如何在CView3中獲得文檔的指針。視圖類中沒有這樣的類成員可以用來直接訪問文檔類。但是我們知道在主窗口類MainFrame中我們可以獲得程序的任意窗口類的指針。因此我們只要獲得程序主窗口了的指針,就可以解決問題了。代碼實現(xiàn)在CView3中訪問CView2中的DoIt()方法。
CView3中的代碼如下:CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();CCuteFTPDoc* Doc=(CCuteFTPDoc*)MainFrame->GetActiveDocument();if(Doc!=NULL) Doc->DoIt();CCuteFTPDoc中的相應(yīng)的處理函數(shù)DoIt()代碼如下:CView2* pView2;POSITION pos;CView* pView;while(pos!=NULL){pView=GetNextView(pos);if(pView->IsKindOf(RUNTIME_CLASS(CView2))==NULL)pView2=(CView2*)pView;}pView2->DoIt(); ■無文檔關(guān)聯(lián)視圖之間的通信
CView3和CView4都是不跟文檔相連的,如何實現(xiàn)他們之間的通信呢。 正如我們在上面所說的那樣,由于在主框架中我們可以訪問任意的視圖,因此我們的主要任 務(wù)還是在程序中獲得主框架的指針。在CView3中訪問CView4中的方法DoIt()。
CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();CView4* View4=(CView4*)MainFrame->m_wndSplitter1.GetPane(2,0);View4->DoIt();
到現(xiàn)在我們已經(jīng)實現(xiàn)了CuteFTP的主窗口的框架并且能夠?qū)崿F(xiàn)他們之間相互通信的框架。 同樣的我們可以實現(xiàn)其他的一些流行界面例如NetAnts,F(xiàn)oxmail的分割。
三、關(guān)于對話框的分割
到目前為止,只有基于文檔/視圖的程序才能使用CSplitterWnd,而基于對話框的應(yīng)用程序卻不支持CSplitterWnd,但是如果我們在繼承類中重載一些虛擬方法,也能使CSplitterWnd 在對話框程序中使用。從MFC的源程序WinSplit.cpp中可以看出,為了獲得父窗口的地方程序都調(diào)用了虛擬方法GetParentFrame(),因此如果在對話框中使用,我們必須將它改為GetParent();因此我們將CSplitterWnd的下面幾個方法重載。
virtual void StartTracking(int ht);virtual CWnd* GetActivePane(int* pRow = NULL, int* pCol = NULL);virtual void SetActivePane( int row, int col, CWnd* pWnd = NULL );virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);virtual BOOL OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult );virtual BOOL OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult ); 具體實現(xiàn)如下,實現(xiàn)中我將給出原有代碼的主要部分以及修改后的代碼以作對比。
在cpp文件中加入下面的枚舉類型。
enum HitTestValue{noHit = 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* pCol){ASSERT_VALID(this);//獲得當(dāng)前的獲得焦點的窗口//下面注釋粗體的是原有的代碼的主要部分。// 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;return pView;}void CxSplitterWnd::SetActivePane( int row, int col, CWnd* pWnd){CWnd* pPane = pWnd == NULL ? GetPane(row, col) : pWnd;//下面加注釋粗體的是原有代碼的主要部分。//FrameWnd* pFrameWnd = GetParentFrame();//ASSERT_VALID(pFrameWnd);//pFrameWnd->SetActiveView((CView*)pPane);pPane->SetFocus();//修改后的語句}void CxSplitterWnd::StartTracking(int ht){ASSERT_VALID(this);if (ht == noHit)return;// GetHitRect will restrict ''''m_rectLimit'''' as appropriateGetInsideRect(m_rectLimit);if (ht >= splitterIntersection1 && ht <= splitterIntersection225){// split two directions (two tracking rectangles)int row = (ht - splitterIntersection1) / 15;int col = (ht - splitterIntersection1) % 15;GetHitRect(row + vSplitterBar1, m_rectTracker);int yTrackOffset = m_ptTrackOffset.y;m_bTracking2 = TRUE;GetHitRect(col + hSplitterBar1, m_rectTracker2);m_ptTrackOffset.y = yTrackOffset;}else if (ht == bothSplitterBox){// hit on splitter boxes (for keyboard)GetHitRect(vSplitterBox, m_rectTracker);int yTrackOffset = m_ptTrackOffset.y;m_bTracking2 = TRUE;GetHitRect(hSplitterBox, m_rectTracker2);m_ptTrackOffset.y = yTrackOffset; // center itm_rectTracker.OffsetRect(0, m_rectLimit.Height()/2); m_rectTracker2.OffsetRect(m_rectLimit.Width()/2,0);}else{// only hit one barGetHitRect(ht, m_rectTracker);}//下面加注釋的將從程序中刪去。//CView* pView = (CView*)GetActivePane();//if (pView != NULL && pView->IsKindOf(RUNTIME_CLASS(CView)))//{// ASSERT_VALID(pView);// CFrameWnd* pFrameWnd = GetParentFrame();//ASSERT_VALID(pFrameWnd);//pView->OnActivateFrame(WA_INACTIVE, pFrameWnd);// }// steal focus and captureSetCapture();SetFocus();// make sure no updates are pendingRedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);// set tracking state and appropriate cursorm_bTracking = TRUE;OnInvertTracker(m_rectTracker);if (m_bTracking2)OnInvertTracker(m_rectTracker2);m_htTrack = ht;SetSplitCursor(ht);}BOOL CxSplitterWnd::OnCommand(WPARAM wParam, LPARAM lParam){if (CWnd::OnCommand(wParam, lParam))return TRUE;//下面粗體的是原程序的語句//return GetParentFrame()->SendMessage(WM_COMMAND, wParam, lParam);return GetParent()->SendMessage(WM_COMMAND, wParam, lParam);}BOOL CxSplitterWnd::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ){if (CWnd::OnNotify(wParam, lParam, pResult))return TRUE;//下面粗體的是源程序的語句//*pResult = GetParentFrame()->SendMessage(WM_NOTIFY,wParam, lParam);*pResult = GetParent()->SendMessage(WM_NOTIFY, wParam, lParam);return TRUE;}BOOL CxSplitterWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult){// The code line below is necessary if using CxSplitterWndin a regular dll// AFX_MANAGE_STATE(AfxGetStaticModuleState());return CWnd::OnWndMsg(message, wParam, lParam, pResult);} 這樣我們就可以在對話框中使用CxSplitterWnd類了。
四、CSplitterWnd的擴展
CSplitterWnd擴展話題是很多的,我們可以通過對原有方法的覆蓋或者增加新的方法來擴展CSplitterWnd。我們在此僅舉兩個方面的例子。
4.1鎖定切分條
當(dāng)用戶創(chuàng)建好分割窗口后,有時并不希望通過拖動切分條來調(diào)節(jié)窗口的大小。這時就必須鎖定切分條。鎖定切分條的最簡單的方法莫過于不讓CSplitterWnd來處理WM_LBUTTONDOWN,WM_MOUSEMOVE,WM_SETCURSOR消息,而是將這些消息交給CWnd窗口進行處理,從而屏蔽掉這些消息。拿WM_LBUTTONDOWN處理過程來說。修改為如下:
void CXXSplitterWnd::OnLButtonDown(UINT nFlags,CPoint point)
{CWnd::OnLButtonDown(nFlags,point);} 其余的處理方法類似。
4.2切分條的定制
由Window自己生成的切分條總是固定的,沒有任何的變化,我們在使用一些軟件比如ACDSee的時候卻能發(fā)現(xiàn)它們的切分條卻是和自動生成的切分條不一樣的。那么如何定制自己的切分條呢?通過重載CSplitterWnd的虛方法OnDrawSplitter和OnInvertTracker可以達到這樣的目的。下面的代碼生成的效果是分割窗口的邊界顏色為紅色,分割條的顏色為綠色.代碼如下:
void CSplitterWndEx::OnDrawSplitter(CDC *pDC, ESplitType nType, const CRect &rectArg){if(pDC==NULL){RedrawWindow(rectArg,NULL,RDW_INVALIDATE|RDW_NOCHILDREN);return;}ASSERT_VALID(pDC);CRect rc=rectArg;switch(nType){case splitBorder://重畫分割窗口邊界,使之為紅色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;case splitBox:pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0));rc.InflateRect(-CX_BORDER,-CY_BORDER);pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0));rc.InflateRect(-CX_BORDER,-CY_BORDER);pDC->FillSolidRect(rc,RGB(0,0,0));pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0));return;case splitBar://重畫分割條,使之為綠色pDC->FillSolidRect(rc,RGB(255,255,255));rc.InflateRect(-5,-5);pDC->Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0));return;default:ASSERT(FALSE);}pDC->FillSolidRect(rc,RGB(0,0,255));}void CSplitterWndEx::OnInvertTracker(CRect &rect){ASSERT_VALID(this);ASSERT(!rect.IsRectEmpty());ASSERT((GetStyle()&WS_CLIPCHILDREN)==0);CRect rc=rect;rc.InflateRect(2,2);CDC* pDC=GetDC();CBrush* pBrush=CDC::GetHalftoneBrush();HBRUSH hOldBrush=NULL;if(pBrush!=NULL) hOldBrush=(HBRUSH)SelectObject(pDC->m_hDC,pBrush->m_hObject);pDC->PatBlt(rc.left,rc.top,rc.Width(),rc.Height(),BLACKNESS);if(hOldBrush!=NULL)SelectObject(pDC->m_hDC,hOldBrush);ReleaseDC(pDC);} 同樣我們只要繼承CSplitterWnd中的其余的一些虛擬方法就可以生成具有自己個性的分割窗口了。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
用VC++實現(xiàn)應(yīng)用程序窗口的任意分割
在Dialog中創(chuàng)建View【文集】
VC 分割窗口效果
如何聯(lián)系CMainFrame和CView各自的成員變量? VC/MFC / 界面
·教程:輕松玩轉(zhuǎn)MFC文檔視圖架構(gòu)編程
MFC多文檔和單文檔視結(jié)構(gòu)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服