Как получить текущий 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. Получив такой указатель, Вы можете обращаться к членам Вашего нового класса.