代码之家  ›  专栏  ›  技术社区  ›  Just Me

MFC SDI GetActiveView()始终返回NULL

  •  1
  • Just Me  · 技术社区  · 7 年前

    我需要帮助切换 CFormViews 在我的MFC SDI C++项目中。我已经挖掘了很长时间,不知道为什么我的代码不能工作。通过搜索互联网(包括这个网站),我找到了几个通过在MainFrm中添加两个函数来切换表单的教程。cpp(a CMainFrame 继承自的对象 CFrameWnd ). 其中一个被传递了一个我想要切换到的表单id,然后获得一个指向活动视图的指针,并从那里运行一些其他代码。然而 GetActiveView() 始终返回 NULL 指针值。我知道有一个活动视图,因为我正在单击活动窗体中的按钮。我的代码如下。这正是我所指的函数。它位于MainFrm中。cpp(启动新MFC项目时创建的默认窗口文件)。

    到目前为止,我已经尝试了来自Microsoft知识库的代码,其中讨论了如何获取最新信息 CDocument CView 从任何地方,我都尝试先获取活动帧,然后调用 GetActiveView 从…起 主框架 ,我尝试了下面的代码。都没有用。很明显,我对MFC的了解还不够,无法解决任何问题。如果您需要我提供更多信息,请咨询。我可能没有提及我应该拥有的一切。我选择为一个学校项目进行MFC,在我知道可以使用这些表单之前,我无法继续创建UML或编写任何其他代码。

    void CMainFrame::SelectView(UINT ViewID)
    {
        // If the view the user selected is already displaying, do nothing
        if (ViewID == m_CurrentView)
            return;
    
        // Get a pointer to the current view
        CView* pCurrentView = GetActiveView();
    
        // We are about to change the view, so we need a pointer to the runtime class
        CRuntimeClass* pNewView = NULL; // Added = NULL because it wouldn't allow program to be run without initialization of pNewView
    
        // We will process a form
        // First, let's change the identifier of the current view to our integer
        ::SetWindowLong(pCurrentView->m_hWnd, GWL_ID, m_CurrentView);
    
        // Now we will identify what form the user selected
        switch (ViewID)
        {
        case IDD_CHOOSE_ITEM:
            pNewView = RUNTIME_CLASS(CChooseItemView);
            break;
    
        case IDD_ITEM_INFORMATION:
            pNewView = RUNTIME_CLASS(CItemInformationView);
            break;
        }
    
        // We will deal with the frame
        CCreateContext crtContext;
    
        // We have a new view now. So we initialize the context
        crtContext.m_pNewViewClass = pNewView;
        // No need to change the document. We keep the current document
        crtContext.m_pCurrentDoc = GetActiveDocument();
    
        CView* pNewViewer = STATIC_DOWNCAST(CView, CreateView(&crtContext));
    
        // Now we can create a new view and get rid of the previous one
        if (pNewViewer != NULL)
        {
            pNewViewer->ShowWindow(SW_SHOW);
            pNewViewer->OnInitialUpdate();
            SetActiveView(pNewViewer);
            RecalcLayout();
            m_CurrentView = ViewID;
            pCurrentView->DestroyWindow();
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  0
  •   Tom Tom    7 年前

    要从CDocument获取非活动视图但关联的CView,可以在Doc中实现此模式

    // ----- GetCChooseItemView() -- -Search the first associated CView in  INACTIVE Views too ! ------ 
    CView* CMyDoc::GetCChooseItemView(void)
    {
      CRuntimeClass* prt = RUNTIME_CLASS(CChooseItemView);
      CView* pView = NULL;
    
      // Continue search in inactive View by T(o)m
    
      POSITION pos = GetFirstViewPosition();
      while (pos != NULL)
      {
        pView = GetNextView(pos);
        if (pView->GetRuntimeClass() == prt)
        {
            if (pView->IsKindOf(RUNTIME_CLASS(CChooseItemView)))
                break;
        }
        pView = NULL;       // not valid vie
      }
    
      return static_cast<CChooseItemView*>(pView);
    }
    

    然后添加SelectView代码

    void CMainFrame::SelectView(UINT ViewID)
    {
      : (code as before)
      :      
      // Get a pointer to the current view
      CView* pCurrentView = GetActiveView();
    
      // Get a pointer to the current view
      CView* pCurrentView = GetActiveView();
      if (pCurrentView == NULL
      { 
        CMyDoc* pDoc = static_cast<CMyDoc*>(GetActiveDocument());
        if (pDoc)
        {
          pCurrentView = pDoc->GetChhoseItemView(); 
          if (pCurrentView == NULL)
             mpCurrentView = pDoc->GetCItemInformationView()  // let as exercise for the OP
    
          if (pCurrentView == NULL
          {
              DebugBreak();     // Errror No View found..
          }
        } 
    
      :  (code as befeore)
      :   
    }
    
        2
  •  0
  •   Flaviu_    7 年前

    以下代码适用于我:

    virtual CView* SwitchToView(CView* pNewView);

    在cpp中:

    CView* CMyDoc::SwitchToView(CView* pNewView)
    {
    	CMDIFrameWndEx* pMainWnd = (CMDIFrameWndEx*)AfxGetMainWnd();
    	// Get the active MDI child window
    	CMDIChildWndEx* pChild = (CMDIChildWndEx*)pMainWnd->MDIGetActive();
    	// Get the active view attached to the active MDI child window.
    	CView* pOldActiveView = pChild->GetActiveView();
    	// Exchange control ID of old view
    	// note: if you have more than two view you have to remember which view you switched to
    	// so you can set it's old control ID correctly
    	if(pNewView == m_pMyView)
    		pOldActiveView->SetDlgCtrlID(CTRLID_MYVIEW2);
    	if(pNewView == m_pMyView2)
    		pOldActiveView->SetDlgCtrlID(CTRLID_MYVIEW);
    	// Exchange control ID of new new
    	// note: the control ID of the active view must always be AFX_IDW_PANE_FIRST
    	pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
    	// Set flag so that document will not be deleted when view is dettached.
    	BOOL bAutoDelete = m_bAutoDelete;
    	m_bAutoDelete = FALSE;
    	// Dettach existing view
    	RemoveView(pOldActiveView);
    	// restore flag
    	m_bAutoDelete = bAutoDelete;
    	// Show the newly active view and hide the inactive view.
    	pNewView->ShowWindow(SW_SHOW);
    	pOldActiveView->ShowWindow(SW_HIDE);
    	// Attach new view
    	AddView(pNewView);
    	pChild->RecalcLayout();
    	pNewView->UpdateWindow();
    	pChild->SetActiveView(pNewView);
    
    	return pOldActiveView;
    }

    我希望它能帮助你。