Программирование на языке MFC

Мой второй блог в серии программирования

Структура типа CCreateContext


Обратите внимание, читатель, что указатель на структуру типа CCreateContext (в нее чуть раньше мы записали наши указатели на документ,шаблон документа, а также указатели на фрейм и на окно представления документа) записывается сначала в поле lpCreateParams структуры cs типа CREATESTRUCT, а потом в поле IParam структу­ры mcs типа MDICREATESTRUCT Указатель на структуру mcs по­сылается окну типа MDICLIENT посредством сообщения WM_MDICREATE. Что же происходит дальше? После получения этого сообщения создается дочернее окно MDI, которое будет иг­рать роль окна фрейма. Естественно, при своем создании оно по­лучает сообщение WM_CREATE, на что реагирует вызовом мето­да CMDIChildWnd::OnCreate():

int CMDIChildWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {

// call base class with IParam context (not MDI one) MDICREATESTRUCT* lpmcs;

lpmcs = (MDICREATESTRUCT*)lpCreateStruct->lpCreateParams; CCreateContext* pContext = (CCreateContext*)lpmcs->lParam;

return OnCreateHelper(lpCreateStruct, pContext);

Из переданной окну структуры типа CREATESTRUCT выбирает­ся указатель на CCreateContext, после чего указатели на структуры типов CREATESTRUCT и CCreateStruct передаются методу CFrameWnd::OnCreateHelper:

int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs.

CCreateContext* pContext)

if (CWnd::OnCreate(lpcs) == -1) return -1;

// create special children first

if (!OnCreateClie*nt (lpcs, pContext) ) {

TRACEO("Failed to create client pane/view for frame.\n") ; return -1;

}

// post message for initial message string

PostMessage(WM_SETMESSAGESTRING, AFX__IDS_IDLEMESSAGE);

// make sure the child windows have been properly sized RecalcLayout();

return 0; // create ok

}

BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT,

CCreateContext* pContext)

{

// default create client will create a view if asked for it if (pContext != NULL && pContext->m_pNewViewClass != NULL) {

if (CreateView (pContext, AFX_IDW_PANE_FIRST) == NULL) return FALSE;

}

return TRUE;

}

CWnd* CFrameWnd::CreateView(CCreateContext* pContext,

UINT nID)

{

ASSERT(m_hWnd != NULL); ASSERT(::IsWindow(m_hWnd)); ASSERT(pContext != NULL);

ASSERT(pContext->m_pNewViewClass != NULL);

// Note: can be a CWnd with PostNcDestroy self cleanup CWnd* pView =

(CWnd*)pContext->m_pNewViewClass->CreateObject() ; if (pView == NULL) {

TRACE1("Warning: Dynamic create of view type

%hs failed.\n",

pContext->m_pNewViewClass->m_lpszClassName) ; return NULL;

ASSERT_KINDOF(CWnd, pView);

// views are always created with a border! if (!pView->Create(NULL, NULL,

AFX_WS_DEFAULT_VIEW, CRect(0,0,0, 0), this, nID,

pContext))

{

TRACEO("Warning: could not create view for frame.\n");
return NULL;
// can’t continue without a view

}

if (afxData.bWin4 && (pView->GetExStyle () &

WS_EX_CLIENTEDGE))

{

// remove the 3d style from the frame, since the view is // providing it.

// make sure to recalc the non-client area

ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);

}

return pView;

}

Смотрите внимательно, читатель! Сначала создается объект (представление) того класса, который мы указали при создании шаблона документа. После этого создается непосредственно окно представления. При этом видно, родительским окном объ­является окно фрейма! Так что же получается? MFC решило за программиста одну из достаточно часто встречавшихся задач -расположение дочернего окна поверх клиентской области роди­тельского окна. Теперь программисту нет необходимости само­му создавать дочернее окно и отслеживать изменения размеров родительского окна – эти задачи решает за него MFC. Единст­венное, что в этом случае требуется от программиста, так это написать приложение в соответствии с требованиями архитек­туры «документ/представление»!

Осталось понять одну «мелочь» – как осуществляется отобра­жение данных документа в окне представления.

Я опять старался рассуждать логически.

Похожие статьи: