天天看點

怎樣在一個一般視窗或是Dialog上面使用分割視窗.

    小弟初次貼文,水準不高,希望不要丢東西.呵呵.

    大家都知道可以在一個CFrameWnd上面使用CSplitterWnd以做出分割視窗的效果(呵呵,順便,分割視窗可是MFC程式的一大特色.原來(Delphi沒有加上這個的支援之前),你隻要看到了分割視窗,幾乎可以肯定是MFC的.(哈哈,當然,也有人用SDK做一個出來,有這種閑的家夥麼?呵呵,好象廢話太多了點).

    可是現實中的情況是,有的時候我們要在一個一般的CWnd上面做一個SplitterWnd的效果.怎麼辦呢?MS的SplitterWnd隻可以用于CFrameWnd(好像也可以用于CView類,MS的文檔裡說的).之是以有這個限制是因為TMD狗屎MS在SplitterWnd裡面把所有要取Parent視窗的地方都設為CFrameWnd了.但實際上,它又沒有用到CFrameWnd的任何特性.是以我們應該怎麼做,好像是很明顯的了.就是去翻MS的SplitterWnd的源碼,把所有的用到了Parent的地方都改掉.啊!!!不是的,這還叫狗屁OOP?應該是重載一個我們自己的.

頭檔案:

// SplitWnd.h : implementation file

//

class CxSplitterWnd : public CSplitterWnd

{

 // Construction

 public:

 CxSplitterWnd() {};

 virtual ~CxSplitterWnd() {};

 // Operations

 public:

 // Overrides

 // ClassWizard generated virtual function overrides

 //{{AFX_VIRTUAL(CxSplitterWnd)

 //}}AFX_VIRTUAL

 // Implementation

 public:

 // These are the methods to be overridden

 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 );

 // Generated message map functions

 protected:

 //}}AFX_MSG(CxSplitterWnd)

 // NOTE - the ClassWizard will add and remove member functions here.

 //}}AFX_MSG

 DECLARE_MESSAGE_MAP()

};

還有實作檔案:

// SplitWnd.cpp : implementation file

//

#include "stdafx.h"

#include "SplitWnd.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

// HitTest return values (values and spacing between values is important)

// Had to adopt this because it has module scope

enum HitTestValue

{

 noHit = 0,

 vSplitterBox = 1,

 hSplitterBox = 2,

 bothSplitterBox = 3, // just for keyboard

 vSplitterBar1 = 101,

 vSplitterBar15 = 115,

 hSplitterBar1 = 201,

 hSplitterBar15 = 215,

 splitterIntersection1 = 301,

 splitterIntersection225 = 525

};

/

// CxSplitterWnd

BEGIN_MESSAGE_MAP(CxSplitterWnd, CSplitterWnd)

//{{AFX_MSG_MAP(CxSplitterWnd)

// NOTE - the ClassWizard will add and remove mapping macros here.

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

CWnd* CxSplitterWnd::GetActivePane(int* pRow, int* pCol)

{

 ASSERT_VALID(this);

 CWnd* pView = GetFocus();

 // make sure the pane is a child pane of the splitter

 if (pView != NULL && !IsChildPane(pView, pRow, pCol))

 pView = NULL;

 return pView;

}

void CxSplitterWnd::SetActivePane( int row, int col, CWnd* pWnd)

{

 // set the focus to the pane

 CWnd* pPane = pWnd == NULL ? GetPane(row, col) : pWnd;

 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);

 }

 // 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);

}

/

// CSplitterWnd command routing

BOOL CxSplitterWnd::OnCommand(WPARAM wParam, LPARAM lParam)

{

 if (CWnd::OnCommand(wParam, lParam))

 return TRUE;

 // route commands to the splitter to the parent frame window

 return GetParent()->SendMessage(WM_COMMAND, wParam, lParam);

}

BOOL CxSplitterWnd::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult )

{

 if (CWnd::OnNotify(wParam, lParam, pResult))

 return TRUE;

 // route commands to the splitter to the parent frame window

 *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了.

繼續閱讀