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

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

Вызов метода CMDIChildWnd::LoadFrame


Для только что созданного объекта осуществляется вызов метода CMDIChildWnd::LoadFrame(). При этом в качестве аргументов ме­тоду передаются пресловутый идентификатор ресурсов, набор сти­лей окна (не объекта, а окна!), которое будет создано, указатель на родительское окно и, наконец, указатель на структуру типа Ccreate-Context, которую мы рассмотрели чуть раньше. Здесь стоит заме­тить, что по умолчанию стилями окна являются WSJDVERLAPPED-WINDOW и FWS_ADDTOTITLE. Исходный текст этого метода на­ходится в файле winmdi.cpp:

Пример

BOOL CMDIChildWnd::LoadFrame(UINT nIDResource,

DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)

{

// only do this once

ASSERT_VALID_IDR(nIDResource) ;

ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
ASSERT(m_hMenuShared == NULL);
// only do once
m_nIDHelp = nIDResource;

// ID for help context (+HID_BASE_RESOURCE)

// parent must be MDI Frame (or NULL for default)

ASSERT(pParentWnd == NULL ||

pParentWnd->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // will be a child of MDIClient

ASSERT(!(dwDefaultStyle & WS_POPUP));

dwDefaultStyle |= WS_CHILD;

// if available – get MDI child menus from doc template
ASSERT(m_hMenuShared == NULL);
// only do once

CMultiDocTemplate* pTemplate; if (pContext != NULL &&

(pTemplate = (CMultiDocTemplate*)pContext->

m_pNewDocTemplate) != NULL)

{

ASSERT_KINDOF(CMultiDocTemplate, pTemplate); // get shared menu from doc template

m_hMenuShared = pTemplate->m_hMenuShared; m_hAccelTable = pTemplate->m_hAccelTable;

}

else {

TRACEO(“Warning: no shared menu/acceltable for MDI Child

window.\n”);

// if this happens, programmer must load these manually }

CString strFullString, strTitle;

if (strFullString.LoadString(nIDResource))

AfxExtractSubString(strTitle, strFullString, 0); // first sub-string

ASSERT(m_hWnd == NULL);

if (!Create(GetlconWndClass(dwDefaultStyle, nIDResource), strTitle, dwDefaultStyle, rectDefault,

(CMDIFrameWnd*)pParentWnd, pContext))

{

return FALSE; // will self destruct on failure normally

// it worked ! return TRUE;

}

Что мы можем увидеть в тексте этого модуля? Многое. Здесь даны ответы на еще несколько вопросов, которые мы напрямую не задавали, но которые, как говорится, висели в воздухе. Например, что еще, кроме меню, акселераторов и строки, может входить в состав передаваемых шаблону документа ресурсов? Каково назна­чение оставшихся подстрок строкового ресурса? Из текста модуля очевидно, что, во-первых, то, что в состав ресурсов, переданных шаблону документа, могут входить не только меню, акселераторы и строка, но и ресурсы помощи. Во-вторых, меню, которое мы соз­дали, является меню окна фрейма! Для нас это очень важно, ибо, наконец, мы поняли, что за меню мы должны создавать при созда­нии шаблона документа. Именно к окну фрейма и относятся аксе­лераторы, которые мы можем создать одновременно с меню.

Этот метод непосредственно создает окно фрей­ма. Но до того момента, пока окно фрейма будет создано, проис­ходит еще несколько интересных вещей. Например, перед вызо­вом метода Create() вызывается метод CFrameWnd::GetlconWnd-Class(). В качестве аргументов этому методу передаются стиль окна и опять-таки идентификатор ресурсов. Текст этой функции нахо­дится в файле winfrm.cpp:

LPCTSTR CFrameWnd::GetlconWndClass(DWORD dwDefaultStyle,

UINT nIDResource)

{

ASSERT_VALID_IDR(nIDResource); HINSTANCE hlnst =

AfxFindResourceHandle(MAKEINTRESOURCE(nIDResource),

RT_GROUP_ICON); HICON hlcon = ::LoadIcon(hlnst,

MAKEINTRESOURCE(nIDResource));

if (hlcon != NULL) {

CREATESTRUCT cs;

memset(&cs, 0, sizeof(CREATESTRUCT));

cs.style = dwDefaultStyle;

PreCreateWindow(cs); // will fill IpszClassName with default WNDCLASS name // ignore instance handle from PreCreateWindow.

WNDCLASS wndcls;

if (cs.IpszClass != NULL &&

GetClassInfo(AfxGetlnstanceHandle(), cs.IpszClass,

&wndcls) && wndcls.hlcon != hlcon)

{

// register a very similar WNDCLASS

return AfxRegisterWndClass(wndcls.style,

wndcls.hCursor, wndcls.hbrBackground, hlcon);

}

}

return NULL; // just use the default

}

Так… Оказывается, в состав ресурсов, передаваемых шаблону документа, может входить и иконка, которая будет использоваться при отображении окна фрейма! Функция пытается загрузить икон­ку из ресурсов, и, если иконка не загрузилась, то ничего не проис­ходит и метод Create() использует данные, принятые по умолча­нию, загрузилась, Если же иконка загрузилась нормально, то MFC, естественно, регистрирует класс окна, которому принадлежит икон­ка. После этого вызывается метод PreCreateWindow(), который мы можем использовать для того, чтобы произвести какие-то дейст­вия ДО создания окна.

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