FolderChangeEvent(char const* folder) : FileChangeEvent(folder, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME) {}
};
class TreeChangeEvent : public FileChangeEvent {
public:
TreeChangeEvent(char const * root) : FileChangeEvent (root, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME) {}
};
Должно быть теперь просто обобщить этот пример, чтобы сделать некоторую действительно полезную работу в ваших программах. Не забудьте посмотреть API, который мы используем в этих обучающих программах, в интерактивной справке, которая идет с вашим компилятором.
Далее: Программирование OLE и использование COM без MFC.
Оболочка из классов для COM
Англоязычный оригинал находится на сервере компании Reliable Software
Программировать с использованием COM настолько трудно, что Вы не должны даже пробовать это без MFC. Правильно или неправильно? Абсолютная чушь! Рекламируемые OLE и его преемник COM имеют элегантность гиппопотама, занимающегося фигурным катанием. Но размещение MFC на вершине COM подобно одеванию гиппопотама в клоунский костюм еще больших размеров.
Загрузите исходник примера, TreeSizer (zip архив 12 кб, любезность Laszlo Radanyi), в котором вычисляется суммарный размер всех файлов в некотором каталоге и всех его подкаталогах. Он, для просмотра каталогов, использует окно просмотра оболочки Windows.
Итак, что делать программисту, когда он столкнется с потребностью использовать возможности оболочки Windows, которые являются доступными только через интерфейсы COM? Читайте …
Для начала, всякий раз, когда Вы планируете использовать COM, Вы должны сообщить системе, чтобы она инициализировала COM подсистему. Точно так же всякий раз, когда вы заканчиваете работу, Вы должны сообщить системе, чтобы она выгрузила COM. Самая простой способ это сделать заключается в определении объекта, конструктор которого инициализирует COM, а деструктор выгрожает ее. Самое лучшее место для внедрения данного механизма — это объект Controller (см. Windows программу Generic), подобный этому.
class Controller {
public:
Controller(HWND hwnd, CREATESTRUCT * pCreate);
~Controller();
// … private:
UseCom _comUser; // i'm a com user
Model _model;
View _view;
HINSTANCE _hInst;
};
Этот способ гарантируют, что COM подсистема будет проинициализирована прежде, чем к ней будут сделаны любые обращения и что она будет освобождена после того, как программа осуществит свои разрушения (то есть, после того, как "Вид" и "Модель" будут разрушены).
Класс UseCom очень прост.
class UseCom {
public:
UseCom() {
HRESULT err = CoInitialize(0);
if (err != S_OK) throw "Couldn't initialize COM";
}
~UseCom() {
CoUninitialize();
}
};
Пока не было слишком трудно, не так ли? Дело в том, что мы не коснулись главной мерзости COM программирования — подсчета ссылок. Вам должно быть известно, что каждый раз, когда что Вы получаете интерфейс, его счетчик ссылок увеличивается. И Вам необходимо явно уменьшать его. И это становится более чем ужастным тогда, когда Вы начинаете запрашивать интерфейсы, копировать их, передавать другим и т.д. Но ловите момент: мы знаем, как управляться с такими проблемами! Это называется управлением ресурсами. Мы никогда не должны касаться интерфейсов COM без инкапсуляции их в интеллектуальных указателях на интерфейсы. Ниже показано, как это работает.
Примечание. В настоящий момент данная тема достаточно широко рассмотрена в литературе, переведенной на русский язык. В частности, можно отметить книги:
Джефф Элджер. "C++: библиотека программиста";
Скотт Мейерс. "Эффективное программирование на С++".
template
class SIfacePtr {
public:
~SIfacePtr() {
Free ();
}
T * operator->() { return _p; }
T const* operator->() const { return _p; }
operator T const * () const { return _p; }
T const& GetAccess () const { return *_p; }