怎样在一个一般窗口或是Dialog上面使用分割窗口.

    技术2022-05-11  150

        小弟初次贴文,水平不高,希望不要丢东西.呵呵.

        大家都知道可以在一个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_FILEstatic 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_MAPEND_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了.

     

     

     

     

     


    最新回复(0)