首页/技术开发/内容

运用VC6.0完成窗口的任意分割

技术开发2023-12-19 阅读()
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实现各个分割区域的通信
■有文档相连的视图之间的通信
由AppWizard生成的CCuteFTPView是与文档相连的,同时我们也让CView2与文档相连,因此我们需要修改CCuteFTPApp的InitInstance()函数,我们将增加下面的部分。
AddDocTemplate (new CMultiDocTemplate(IDR_VIEW2TYPE,
RUNTIME_CLASS(CMainDoc),
RUNTIME_CLASS(CMDIChildWnd),
RUNTIME_CLASS(CView2)));
我们现在来实现CCuteFTPView与CView2之间的通信。由于跟文档类相连的视图类 是不能安全的与除文档类之外的其余的视图类通信的。因此我们只能让他们都与文档 类通信。在文档中我们设置相应的指针以用来获的各个视图。我们重载 CCuteFTPView::OnOpenDocument()函数;
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中调用CView2中的一个方法DoIt()则代码如下:
CCuteFTPDoc* pDoc=GetDocument();
CView2* pView2=pDoc->pView3;
pView3.DoIt();
■无文档视图与文档关联视图之间的通信
CView3和CView4都是不与文档相关联的。我们现在实现CView3与CView2的通信.正如前面所说,CView2只能安全的与CCuteFTPDoc通信,因此,CView3如果需要跟CView2通信,也必须借助于文档类。因此程序的关键是如何在CView3中获得文档的指针。视图类中没有这样的类成员可以用来直接访问文档类。但是我们知道在主窗口类MainFrame中我们可以获得程序的任意窗口类的指针。因此我们只要获得程序主窗口了的指针,就可以解决问题了。代码实现在CView3中访问CView2中的DoIt()方法。

CView3中的代码如下:

CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();
CCuteFTPDoc* Doc=(CCuteFTPDoc*)MainFrame->GetActiveDocument();
if(Doc!=NULL) Doc->DoIt();

CCuteFTPDoc中的相应的处理函数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();
■无文档关联视图之间的通信
CView3和CView4都是不跟文档相连的,如何实现他们之间的通信呢。 正如我们在上面所说的那样,由于在主框架中我们可以访问任意的视图,因此我们的主要任 务还是在程序中获得主框架的指针。在CView3中访问CView4中的方法DoIt()。
CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();
CView4* View4=(CView4*)MainFrame->m_wndSplitter1.GetPane(2,0);
View4->DoIt();

到现在我们已经实现了CuteFTP的主窗口的框架并且能够实现他们之间相互通信的框架。 同样的我们可以实现其他的一些流行界面例如NetAnts,Foxmail的分割。

三、关于对话框的分割
到目前为止,只有基于文档/视图的程序才能使用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 (北联网教程,专业提供视频软件下载)

第1页  第2页  第3页  第4页  第5页 

……

相关阅读