15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Как получить текущий CDocument или CView из любого места программы

В приложениях MFC очень часто бывает необходимо получить указатель на активный документ или Вид из любого места программы. Например, иногда полезно иметь доступ к документу из диалогового окна. В данной статье обсуждаются простейшие методы того, как это сделать используя связи между объектами MFC и основной архитектурой MFC.

Как уже упоминалось, один из случаев, когда может потребоваться указатель на текущий активный Вид или документ, это модальное или немодальное диалоговое окно. Вообще-то, диалоговое окно должно быть создано классом Вида, так Вид имеет прямое отношение к пользовательскому интерфесу приложения.

Так как класс Вид создаёт диалоговое окно, то он может передать диалоговому окну указатель на самого себя либо на активный документ [полученный функцией GetActiveDocument()]. Это можно сделать через конструктор диалога либо через другую функцию-член. Для модальных диалогов, Вид также может помещать данные из диалогового окна в документ когда DoModal() возвращает управление.

Чтобы получить указатель на текущий активный документ из любого места программы, добавьте статическую функцию-член в Ваш класс, наследованный от CDocument как показано ниже:

В заголовочном файле документа, добавляем статическую функцию GetDoc():

   // Заголовочный файл документа
   class CMyDoc : public CDocument
   {
      ...
      public:
      static CMyDoc * GetDoc();
      ...
   }; 

Для однодокументного приложения (SDI), добавляем следующий код функции CMyDoc::GetDoc():

   // файл исходника SDI документа
   CMyDoc * CMyDoc::GetDoc()
   {
      CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
      return (CMyDoc *) pFrame->GetActiveDocument();
   } 

Для многодокументного приложения (MDI), код функции CMyDoc::GetDoc() будет выглядеть следующим образом:

   CMyDoc * CMyDoc::GetDoc()
   {
      CMDIChildWnd * pChild =
          ((CMDIFrameWnd*)(AfxGetApp()->m_pMainWnd))->MDIGetActive();

      if ( !pChild )
          return NULL;

      CDocument * pDoc = pChild->GetActiveDocument();

      if ( !pDoc )
         return NULL;

      // Ошибка, если документ неправильного типа
      if ( ! pDoc->IsKindOf( RUNTIME_CLASS(CMyDoc) ) )
         return NULL;

      return (CMyDoc *) pDoc;
   } 

Чтобы получить указатель на текущий активный Вид из любого места программы, добавьте статическую функцию-член в Ваш класс, наследованный от CView как показано ниже:

В заголовочном файле Вида добавляем статическую функцию GetView():

   // Заголовочный файл Вида
   class CMyView
   {
      ...
      public:
      static CMyView * GetView();
      ...
   }; 

Для SDI приложения тело функции CMyView::GetView() будет выглядеть следующим образом:

   // View implementation file
   CMyView * CMyView::GetView()
   {
      CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);

      CView * pView = pFrame->GetActiveView();

      if ( !pView )
         return NULL;

      // Ошибка, если Вид неправильного типа
      // (это может случиться с окнами разделителями (splitter windows),
      // либо с дополнительными Видами в одном документе
      if ( ! pView->IsKindOf( RUNTIME_CLASS(CMyView) ) )
         return NULL;

      return (CMyView *) pView;
   } 

Для многодокументного приложения (MDI), код функции CMyView::GetView() будет выглядеть следующим образом:

   // MDI view implementation file
   CMyView * CMyView::GetView()
   {
      CMDIChildWnd * pChild =
          ((CMDIFrameWnd*)(AfxGetApp()->m_pMainWnd))->MDIGetActive();

      if ( !pChild )
          return NULL;

      CView * pView = pChild->GetActiveView();

      if ( !pView )
         return NULL;

      // Ошибка, если Вид неправильного типа
      if ( ! pView->IsKindOf( RUNTIME_CLASS(CMyView) ) )
         return NULL;

      return (CMyView *) pView;
   } 

Теперь, из любого места Вашей программы где включён заголовочный файл документа или Вида можно вызвать:

   CMyDoc::GetDoc(); 

- Или -

   CMyView::GetView(); 

чтобы получить указатель на текущий активный документ или Вид соответственно. Если нет ниодного активного документа или Вида, то эти функции вернут NULL. Получив такой указатель, Вы можете обращаться к членам Вашего нового класса.