Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиСП - методички / OS&SP_Lab_2.6(shell).doc
Скачиваний:
95
Добавлен:
18.05.2015
Размер:
1.12 Mб
Скачать

Выполнение выбора пользователя

Когда пользователь щелкает на одном из пунктов меню, проводник вызывает метод InvokeCommand(). Он в первую очередь проверяет старшее слово в значении lpVerb. Если оно не нулевое, то это имя "действия", которое можно извлечь. Поскольку мы уже знаем, что "действия" работают некорректно (по крайней мере в Windows 98), не будем обращать на них внимание. Рассмотрим младшее слово. Если оно 0 или 1, можно быть уверенным, что выбран один из наших пунктов меню.

HRESULT CDllRegShlExt::InvokeCommand ( LPCMINVOKECOMMANDINFO pCmdInfo )

{

// If lpVerb really points to a string, ignore this function call and bail out.

if ( 0 != HIWORD( pInfo->lpVerb ))

return E_INVALIDARG;

// Check that lpVerb is one of our commands (0 or 1)

switch ( LOWORD( pInfo->lpVerb ))

{

case 0:

case 1:

{

CProgressDlg dlg ( &m_lsFiles, pInfo );

dlg.DoModal();

return S_OK;

}

break;

default:

return E_INVALIDARG;

break;

}

}

Если младшее слово lpVerb принимает значение 0 или 1, мы создаем диалог (производный от класса ATL CDialogImpl) для отображения процесса регистрации/разрегистрации и передаем ему список имен файлов.

Вся реальная работа производится в классе CProgressDlg. Функция этого класса OnInitDialog() инициализирует элемент управления "список" (list control) и затем вызывает CProgressDlg::DoWork(). Эта функция просматривает список, который был построен в CDllRegShlExt::Initialize() и вызывает соответствующую функцию в каждом файле. Основной код приведен ниже, но он не является полным, поскольку я не привел код проверки ошибок и части по заполнению списка. Этого вполне достаточно, чтобы продемонстрировать, как просматривается список имен файлов и показать действия с каждым файлом.

void CProgressDlg::DoWork()

{

HRESULT (STDAPICALLTYPE* pfn)();

string_list::const_iterator it, itEnd;

HINSTANCE hinst;

LPCSTR pszFnName;

HRESULT hr;

WORD wCmd;

wCmd = LOWORD ( m_pCmdInfo->lpVerb );

// We only support 2 commands, so check the value passed in lpVerb.

if ( wCmd > 1 )

return;

// Determine which function we'll be calling. Note that these strings are

// not enclosed in the _T macro, since GetProcAddress() only takes an

// ANSI string for the function name.

pszFnName = wCmd ? "DllUnregisterServer" : "DllRegisterServer";

for ( it = m_pFileList->begin(), itEnd = m_pFileList->end();

it != itEnd;

it++ )

{

// Try to load the next file.

hinst = LoadLibrary ( it->c_str() );

if ( NULL == hinst )

continue;

// Get the address of the register/unregister function.

(FARPROC&) pfn = GetProcAddress ( hinst, pszFnName );

// If it wasn't found, go on to the next file.

if ( NULL == pfn )

continue;

// Call the function!

hr = pfn();

Нужно дать некоторые объяснения относительно цикла "for", поскольку, если вы не в курсе, коллекция классов STL несколько "странновата". m_pFileList - указатель списка m_lsFiles в классе CDllRegShlExt. (Этот указатель был передан конструктору класса CProgressDlg). Коллекция списков STL имеет тип, называемый const_iterator, сущность которого аналогична типу POSITION в MFC. А переменная типа const_iterator действует как указатель на const объект в списке, поэтому этот итератор может применяться с "->" для получения доступа к этому объекту. Он также может быть увеличен с помощью оператора "++" для продвижения вперед по списку.

Итак, в выражении инициализации цикла "for" вызывается list::begin() для получения итератора, "указывающего" на первую строку списка и, затем, вызывается list::end() для получения итератора, который "указывает" на "конец" списка, то есть на следующую позицию после последней строки. (Я поместил термины в кавычки, чтобы подчеркнуть, что понятия указывания, начала и конца списка очень абстрактны для типа const_iterator и могут быть материализованы через методы const_iterator [типа begin()] или операторы [типа "++"]. Итераторы начала и конца обозначены it и itEnd соответственно. Цикл продолжается, пока it не станет равным itEnd, то есть пока it не достигнет "конца" списка. Итератор it, проходя через цикл, каждый раз увеличивается, и таким образом, в одном витке цикла обрабатывается одна строка списка.

Выражение it->c_str() использует оператор "" для итератора. Поскольку it выполняет функцию указателя на строку (помните, m_pFileList является списком строк STL), то it->c_str() вызывает функцию c_str() для строки, на которую в данный момент указывает it. c_str() возвращает указатель на C-style строку символов, в данном случае эквивалент LPCTSTR.

Остальное в DoWork() - это освобождение ресурсов и обработка ошибок.

(Я только сейчас осознал, как странно звучит разговор о переменной, названной "it" (это). Sorry.) :-)

Соседние файлы в папке ОСиСП - методички