AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > VC编程

使用VC6.0实现窗口的任意分割

51自学网 2015-08-30 http://www.wanshiok.com

  三、关于对话框的分割

  到目前为止,只有基于文档/视图的程序才能使用CSplitterWnd,而基于对话框的应用程序却不支持CSplitterWnd,但是如果我们在继承类中重载一些虚拟方法,也能使CSplitterWnd 在对话框程序中使用。从MFC的源程序WinSplit.cpp中可以看出,为了获得父窗口的地方程序都调用了虚拟方法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 ); 

  具体实现如下,实现中我将给出原有代码的主要部分以及修改后的代码以作对比。

  在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); //获得当前的获得焦点的窗口 //下面注释粗体的是原有的代码的主要部分。 // 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 appropriate GetInsideRect(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 it m_rectTracker.OffsetRect(0, m_rectLimit.Height()/2);
m_rectTracker2.OffsetRect(m_rectLimit.Width()/2, 0); } else { // only hit one bar GetHitRect(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 capture SetCapture(); SetFocus(); // make sure no updates are pending RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW); // set tracking state and appropriate cursor m_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 CxSplitterWnd in a regular dll // AFX_MANAGE_STATE(AfxGetStaticModuleState()); return CWnd::OnWndMsg(message, wParam, lParam, pResult); }

  这样我们就可以在对话框中使用CxSplitterWnd类了。

  四、CSplitterWnd的扩展

  CSplitterWnd扩展话题是很多的,我们可以通过对原有方法的覆盖或者增加新的方法来扩展CSplitterWnd。我们在此仅举两个方面的例子。

  4.1锁定切分条

  当用户创建好分割窗口后,有时并不希望通过拖动切分条来调节窗口的大小。这时就必须锁定切分条。锁定切分条的最简单的方法莫过于不让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的时候却能发现它们的切分条却是和自动生成的切分条不一样的。那么如何定制自己的切分条呢?通过重载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中的其余的一些虚拟方法就可以生成具有自己个性的分割窗口了。

 
 
说明
:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。

上一篇:摆脱DLL&quot;地狱&quot;的困扰之获取进程的命令行  下一篇:VC中利用原始套接字实现网络监听