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

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

Шаблон документа


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

Обратите внимание, ува­жаемый читатель, что поэтому наш путь лежит к исходному тексту этой функции, кото­рый находится в файле docmgr.cpp:

AFX_STATIC void AFXAPI _AfxAppendFilterSuffix (

CStringS filter, OPENFILENAME& ofn, CDocTemplate*pTemplate, CString* pstrDefaultExt)

{

ASSERT_VALID(pTemplate);

ASSERT_KINDOF(CDocTemplate, pTemplate);

CString strFilterExt, strFilterName;

if (pTemplate->GetDocString(strFilterExt,

CDocTemplate::filterExt) && !strFilterExt.IsEmpty() && pTemplate->GetDocString(strFilterName, CDocTemplate::filterName)&& !strFilterName.IsEmpty())

{

// a file based document template – add to filter list ASSERT(strFilterExt[0] == Л.’); if (pstrDefaultExt != NULL) {

// set the default extension

*pstrDefaultExt = ((LPCTSTR)strFilterExt) + 1;

// skip the Л.’

ofn.lpstrDefExt = (LPTSTR)(LPCTSTR)(*pstrDefaultExt); ofn.nFilterlndex = ofn.nMaxCustFilter + 1;

// 1 based number

// add to filter

filter += strFilterName; ASSERT (! filter. IsEmpty ());// must have a file type name filter += (TCHAR)’\0′; // next string please filter += (TCHAR)’*'; filter += strFilterExt;

filter += (TCHAR)’\0′; // next string please ofn.nMaxCustFilter++;

(CDocManager::OnFileOpen ) Сердцем этого метода яв-

I _____ ляются, в свою очередь, вы-

|{ CDocManager::DoPromptFileName J зовы методов CDocTem-

I—{^AfxAppendFilterSuffix ) plate::GetDocString():

L-[CDocTemplate::GetDocString]

BOOL CDocTemplate::GetDocString(CStrirvg& rString,

enum DocStringlndex i) const

{

return AfxExtractSubString(rString, m_strDocStrings, (int)i); }

Несмотря на кажущуюся простоту вызова, здесь можно заме­тить кое-что интересное. Во-первых, в классе CDocTemplate есть перечисление DocStringlndex:

enum DocStringlndex {

windowTitle, // default window title

docName, // user visible name for default document

fileNewName, // user visible name for FileNew

// for file based documents:

filterName, // user visible name for FileOpen filterExt, // user visible extension for FileOpen // for file based documents with Shell open support: regFileTypeld, // REGEDIT visible registered

// file type identifier regFileTypeName, // Shell visible registered

// file type name

};

(CDocManager::OnFileOpen ] Об этом перечислении мы

I r —————— v достоточно скоро вспомним.

4CDocManager::DoPromptFileNameJ Во-вторых, наконец-то о се-

L-T_AfxAppendFilterSuffix Л бе напоминает та строка,

[ ( —----------------------- которую мы загрузили из ре-

L{CDocTemplate::GetDocStringj Сурс0в при создании шабло-

L_f AfxExtractSubstring] на Документа! Интересно

также, что в совокупности

именно с этой строкой индекс из перечисления передается функ­ции AfxExtractSubString(). Значит, этот индекс является либо номе­ром символа в строке, либо номером какой-то подстроки? Для того чтобы получить ответ и на этот вопрос, нам нужно лезть еще даль­ше в дебри MFC. Ниже я привожу определение (файл afxwin.h) и тек­ст (файл winstr.cpp) функции AfxExtractSubString():

BOOL AFXAPI AfxExtractSubString(CString& rString, LPCTSTR IpszFullString, int iSubString, TCHAR chSep = Лп‘);

BOOL AFXAPI AfxExtractSubString(CString& rString,

LPCTSTR IpszFullString, int iSubString, TCHAR chSep)

{

if (IpszFullString == NULL) return FALSE;

while (iSubString—) {

IpszFullString = _tcschr(IpszFullString, chSep);

if (IpszFullString == NULL)

{

rString.Empty(); // return empty string as well

return FALSE;

}

lpszFullString++; // point past the separator

}

LPCTSTR lpchEnd = _tcschr(IpszFullString, chSep); int nLen = (lpchEnd == NULL) ?

lstrlen(IpszFullString) : (int)(lpchEnd -

IpszFullString);

ASSERT(nLen >= 0);

memcpy(rString.GetBufferSetLength(nLen),

IpszFullString,

nLen*sizedf" (TCHAR) ) ; return TRUE;

}

Так вот оно что! Оказывается, строка, индекс ресурса которой мы указали при создании шаблона документа, состоит из подстрок! Каждая подстрока отделена от предыдущей символом-разделите­лем! Функции передается указатель на строку, состоящую из под­строк (второй аргумент), индекс подстроки (третий аргумент) и зна­чение символа-разделителя (по умолчанию это VT). Первый аргу­мент – это указатель на подстроку с соответствующим индексом. Если мы посмотрим на тексты DoPromptFileName() и __AfxAppend-FilterSuffix(), то придем к выводу, что пятая и четвертая подстроки хранят соответственно фильтр и название фильтра, используемые при формировании стандартного диалогового окна открытия фай­ла! Выскажем также предположение, что в перечислении DocString­lndex в некотором смысле определены назначения подстрок.

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