静态切分窗口的替换与更新

 今天在我的项目中遇到这样的需求,我想在点击工具栏某个自定义的视图切换按钮时,静态切分窗口中的某个视图被一个新视图替换(例如:CFormView被CEditView替换)。我开始的想法是:在那个视图按钮被点击的消息响应函数中发送WM_CREATE消息,引发OnCreate,然后是如下的调用次序:OnCreateHelper——OnCreateClient——CreateView,经过实践发现只有第一次切换时,WM_CREATE消息被发送并得到响应,后来切换就不灵了!

最初的想法往往是最不成熟的,后来又在CodeProject上面找到别人重写的CSplitterWnd类,可以replace某个视图,于是乎直接拿来用了,代码如下:
BOOL CUsefulSplitterWnd::ReplaceView(int row, int col,CRuntimeClass * pViewClass,SIZE size)
{
  CCreateContext context;
  BOOL bSetActive;
       
  
  if ((GetPane(row,col)->IsKindOf(pViewClass))==TRUE)
       return FALSE;
       
  
   // Get pointer to CDocument object so that it can be used in the creation
   // process of the new view
   CDocument * pDoc= ((CView *)GetPane(row,col))->GetDocument();
   CView * pActiveView=GetParentFrame()->GetActiveView();
   if (pActiveView==NULL || pActiveView==GetPane(row,col))
      bSetActive=TRUE;
   else
      bSetActive=FALSE;

    // set flag so that document will not be deleted when view is destroyed
 pDoc->m_bAutoDelete=FALSE;   
    // Delete existing view
   ((CView *) GetPane(row,col))->DestroyWindow();
    // set flag back to default
    pDoc->m_bAutoDelete=TRUE;
 
    // Create new view                      
   
  context.m_pNewViewClass=pViewClass;
   context.m_pCurrentDoc=pDoc;
   context.m_pNewDocTemplate=NULL;
   context.m_pLastView=NULL;
   context.m_pCurrentFrame=NULL;
   
   CreateView(row,col,pViewClass,size,&context);
  
   CView * pNewView= (CView *)GetPane(row,col);
  
   if (bSetActive==TRUE)
      GetParentFrame()->SetActiveView(pNewView);
  
   RecalcLayout();
   GetPane(row,col)->SendMessage(WM_PAINT);
  
   return TRUE;
}
但是又出现了新的问题,视图切换后不能被初始化,即OnInitialUpdate函数没有被执行。调试运行,进入了CSplitterWnd::CreateView(int row, int col,CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext)发现如下代码:
 BOOL bSendInitialUpdate = FALSE;

 CCreateContext contextT;
 if (pContext == NULL)
 {
  // if no context specified, generate one from the currently selected
  //  client if possible
  CView* pOldView = (CView*)GetActivePane();
  if (pOldView != NULL && pOldView->IsKindOf(RUNTIME_CLASS(CView)))
  {
   // set info about last pane
   ASSERT(contextT.m_pCurrentFrame == NULL);
   contextT.m_pLastView = pOldView;
   contextT.m_pCurrentDoc = pOldView->GetDocument();
   if (contextT.m_pCurrentDoc != NULL)
    contextT.m_pNewDocTemplate =
      contextT.m_pCurrentDoc->GetDocTemplate();
  }
  pContext = &contextT;
  bSendInitialUpdate = TRUE;
 }
........
 if (bSendInitialUpdate)
  pWnd->SendMessage(WM_INITIALUPDATE);
如果pContext 为空则发送WM_INITIALUPDATE初始化,反之则不发送。下面是摘自MSDN中的一段:
When passed as an argument for window creation, as in CWnd::Create, CFrameWnd::Create, and CFrameWnd::LoadFrame, the create context specifies what the new window should be connected to. For most windows, the entire structure is optional and a NULL pointer can be passed.
也就是说MFC通过pContext 来判断是否是第一次创建该视图,如果是则初始化,不是则不初始化。所以我们可以把上面ReplaceView函数代码稍微改一下,把CreateView(row,col,pViewClass,size,&context);改为CreateView(row,col,pViewClass,size,NULL);即可。再次运行程序,通过!o(∩_∩)o...哈哈

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值