

Программирование на языке 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(), то придем к выводу, что пятая и четвертая подстроки хранят соответственно фильтр и название фильтра, используемые при формировании стандартного диалогового окна открытия файла! Выскажем также предположение, что в перечислении DocStringlndex в некотором смысле определены назначения подстрок.
Похожие статьи: CDocTemplate, DoPromptFileName, OnFileOpen
