none
vc2008中CMainFrame::GetActiveView()函数获取CTabView的问题 RRS feed

  • 问题

  • 我的程序是SDI结构,
    在CDockablePane子类中封装了一个树形控件,
    程序视图类CMyTabView是由CTabView继承过来的,CMyTabView中tab是Grid表格(目前只有加了一个tab)
    工程设置是UNICODE,静态MFC库
    在Debug、Release模式下都有问题


    【详细描述】
    在我的树形控件中,我发送item改变消息给CMainFrame,由CMainFrame::OnMsgViewTree处理该消息,
    现在有个问题,在CMainFrame::OnMsgViewTree的ASSERT_VALID(pViewGrid); 出错

    后来发现CMainFrame::OnMsgViewTree中,
    GetActiveView()得到CMyTabView指针与我原来创建的CMyTabView指针不一致(我是在CMyTabView::OnCreate看原始指针的),
    不知道CMainFrame::GetActiveView()函数怎么出问题了,获取不到实际的CMyTabView指针?
    以前在VC6中没有遇到过这种事情的


    另外,我也试了MSDN里面的TabbedView例子,结果也是一样的
    通过一个菜单,在CMainFrame也是获取CTabView有问题,指针不一致,无法操作其中的tab


    代码如下:

    //树形控件cpp文件,发送消息
    void CViewTree::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
    {
          LPNMTREEVIEW pNMTreeView = reinterpret_cast <LPNMTREEVIEW>(pNMHDR);
          // TODO: 在此添加控件通知处理程序代码

         CMainFrame *pMainFrm = (CMainFrame *)AfxGetMainWnd();
         CMyTabView *pView = (CMyTabView *)pMainFrm->GetActiveView();  ----------->问题:pView指针地址与创建的时候的CMyTabView指针地址不一致

         HTREEITEM itemSel = GetSelectedItem();
         if (itemSel != NULL)
        {
             int nIndex;
             nIndex = GetItemData(itemSel);

             ::SendMessage(AfxGetMainWnd()->m_hWnd, WM_VIEWTREEITEM, ITEM_CHANGED, nIndex); 
             //::SendMessage(pView->m_hWnd, WM_VIEWTREEITEM, ITEM_CHANGED, nIndex);        ---------->直接发送给CMyTabView也不行,接收不到消息
         }

          *pResult = 0;
    }


    LRESULT CMainFrame::OnMsgViewTree(WPARAM wp, LPARAM lp)
    {
         MSG_TREEITEM msgType = (MSG_TREEITEM)wp;
         int nIndex = (int)lp;
         TREEITEM_DATA *pItemData;
         CMyTabView *pView = (CMyTabView *)GetActiveView();
         ASSERT_VALID(pView);                    -------------------->问题:pView虽然有效,但是其指针地址与创建的时候的CMyTabView指针地址不一致
         CViewGridCtrl *pViewGrid;

         switch(msgType)
        {
         case ITEM_CHANGED:
                 pItemData = m_vectNodeData.at(nIndex);

                 pView->SetActiveView(0);

                //pViewGrid = (CViewGridCtrl *)pView->GetActiveView();
                pViewGrid = dynamic_cast <CViewGridCtrl *>(pView->GetActiveView()); 
                ASSERT_VALID(pViewGrid);        -------------------->出错点:由于pView指针地址不一致,导致pViewGrid地址无效(地址全为0),弹出错误 
                pViewGrid->InitGrid(pItemData->gridType);
                pViewGrid->Invalidate();

                break;

             default:
                 break;
            }


           return 0;
    }


    最后还想请教一下,CTabView如何隐藏某个Tab,以及动态创建Tab呢?
    即改变树形控件的item时候,创建对应的tab,并隐藏或关闭原有的tab
    不知道CTabView能否实现上述功能,看了MSDN好像没有Hide这个功能,只有删除方式
    要是有类似功能的空间,麻烦推荐一下,谢谢!
    2009年6月15日 3:41

答案

  • 拿到的是tab view中选中那个tab对应的view

    可以通过这样的方法拿到 CXXXTabView
    CView * pView = pChildFrm->GetActiveView();
    CMFCTabCtrl * pParent1 = pView->GetParent();
    CXXXTabView * pTabView = pParent1->GetParent();


    这个才是真正的原因,所以用CMFCTabView的要注意这个问题!!!!
    • 已标记为答案 studyweb 2009年7月16日 9:56
    2009年7月16日 9:56

全部回复

  • 刚才又试了一下

    CMyTabView *pView = (CMyTabView *)GetActiveView();
    在上面的语句后添加了
    ASSERT(pView->IsKindOf(RUNTIME_CLASS(CMyTabView)));  -------------------->这里出问题了,弹出错误


    奇怪了,这个问题在什么地方呢?
    以前用VC6都是用CMyTabView *pView = (CMyTabView *)pMainFrm->GetActiveView(); 类似方式获取View的,
    从没有出现问题啊

    另外,我的CMyTabView生成的时候,向导没办法选择CTabView,
    我是先生成CView,然后将所有CView改成CTabView了
    我对照了MSDN的TabbedView sample,和它的CTabView子类差不多

    不知道问题是不是出现在这里了?

    2009年6月15日 7:04
  • 我试了一下MSDNd Visual C++ 2008 Feature Pack的TabbedView sample,
    也有类似问题
    奇怪了


    ////////////////////////////////////////////////////////////////代码
    //随便添加的一个测试菜单
    void CMainFrame::OnTestTaboperate()
    {
    // TODO: 在此添加命令处理程序代码

            //CChildFrame *pChildFrm = (CChildFrame *)MDIGetActive();
          CChildFrame *pChildFrm = (CChildFrame *)GetActiveFrame();
          ASSERT(pChildFrm->IsKindOf(RUNTIME_CLASS(CChildFrame)));
          CTabbedViewView *pViewTab = (CTabbedViewView *)pChildFrm->GetActiveView();
          ASSERT(pViewTab->IsKindOf(RUNTIME_CLASS(CTabbedViewView))); ------------------------->这里出错了

            ASSERT(pViewTab->SetActiveView(1) == FALSE);
          CView2 *pView2 = (CView2 *)pViewTab->GetActiveView();
    }
    2009年6月15日 7:36
  • 没有人调用SetActiveView的话,是没有ActiveView的
    MSMVP VC++
    2009年6月17日 17:14
    版主
  • 拿到的是tab view中选中那个tab对应的view

    可以通过这样的方法拿到 CXXXTabView
    CView * pView = pChildFrm->GetActiveView();
    CMFCTabCtrl * pParent1 = pView->GetParent();
    CXXXTabView * pTabView = pParent1->GetParent();


    这个才是真正的原因,所以用CMFCTabView的要注意这个问题!!!!
    • 已标记为答案 studyweb 2009年7月16日 9:56
    2009年7月16日 9:56