Обратите внимание, что это — только один пример того, как Вы получаете доступ к OLE объектам. Вы можете захотеть поиграть с некоторыми из параметров. Например, я передаю CLSCTX_SERVER как параметр в CoCreateInstance. Это даст мне уверенность, что объект будет жить в отдельном от клиента процессе. Во многих случаях вам лучше иметь объект как сервер в процессе на основе DLL, которая загружается в адресное пространство клиента. Для больших подробностей ищите описание CoCreateInstance в вашей справке.
SObject::SObject(CLSID cons & classId, bool running) :_iUnk (0) {
HRESULT hr = S_OK;
if (running) {
:: GetActiveObject(class i d, 0, &_iunk);
}
if (_iUnk == 0) {
hr = :: CoCreateInstance(classId, 0, CLSCTX_SERVER, IID_IUnknown, (void**)&_iUnk);
}
if (FAILED(hr)) throw HEx(hr, "Couldn't create instance");
}
Через мгновение я объясню странный тип исключения HEx.
В нашей реализации AcquireInterface просто вызывает метод QueryInterface из IUnknown (или, как я говорю, неудачный QueryInterface из неудачного IUnknown).
void* SObject::AcquireInterface(IID const& iid) {
void * p = 0;
HRESULT hr = _iUnk-> QueryInterface(iid, &p);
if (FAILED(hr)) {
if (hr == E_NOINTERFACE) throw "No such interface";
else throw HEx(hr, "Couldn't acquire interface");
}
return p;
}
Метод AcquireInterface — один из этих исключительных, Получающих методов Управления ресурсами, которые освобождают ресурсы. Мы не вызываем его иначе, как внутри конструктора интеллектуального указателя интерфейса. (Между прочим, параметр шаблона — это IID указатель, потому что компилятор не будет принимать ссылки как параметры шаблона. Я не уверен почему.)
Итак, имеется шаблон для интеллектуального указателя интерфейса.
template
class SFace {
public:
~SFace() {
if (_i) _i-> Release();
}
I* operator->() { return _i; }
protected:
SFace() : _i(0) {}
SFace(void * i) {
_i = static_cast(i);
}
protected:
I * _i;
};
Как видите, этот специфический шаблон не может порождать экземпляры. Дело в том, что все его конструкторы защищены. Но не волнуйтесь, мы создадим другие классы, которые обеспечим их собственными специализированными конструкторами.
Вот один из них, который использует наш CoObject (или любой другой объект, полученный от него) как источник интерфейса.
template
class SObjFace: public SFace {
public:
SObjFace(CoObject& obj) : SFace(obj.AcquireInterface(*iid)) {}
};
В заключение позвольте мне представить класс HEx (HRESULT Exception). Это — класс исключения, который является способным к отображению значимых сообщений об ошибках. Для достижения моих ограниченных целей, я просто отображаю сообщения непосредственно на холсте основного экрана. Не бойтесь реализовать ваш собственный метод с использованием окна сообщений или еще чего-нибудь.
class HEx {
public:
HEx(HRESULT hr, char const * str = 0) : _hr (hr), _str (str) {}
void Display(int x, int y, Canvas& canvas) {
if (_str != 0) {
canvas.Text (x, y, _str);
y += 20;
}
if (FAILED (_hr)) {
char * msg;
:: FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, _hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&msg), 0, 0);
canvas.Text(x, y, msg);
:: LocalFree(msg);
}
}
private:
HRESULT _hr;
char const * _str;
};
Далее:Будет представлен типичный код. Я только должен объяснить, что такое Автоматизация.
Обертка для автоматизации
Автоматизация
Перевод А. И. Легалова
Англоязычный оригинал находится на сервере компании Reliable Software
Мне бы хотелось получить море информации из запущенной копии Microsoft Developers Studio. Это должно быть простой задачей, т.к. DevStudio, подобно многим другим приложениям MS, предоставляет его интерфейсы через OLE Автоматизацию. Не столь просто! Как Вы увидите, Microsoft решил, что клиенты интерфейсов автоматизации VC ++ будет или использовать Visual Basic, или внутренних умных мастеров DevStudio. Я, с другой стороны, люблю программировать на C++ (Вам не кажется, что Microsoft Visual C++ должен быть переименован в Microsoft Visual MFC Wizard? Это принизило C++ до роли языка сценариев для MFC.)
В любом случае, когда я выяснил, как надо делать, остальное оказалось не быть слишком трудным. Вы только должны выяснить, где вся необходимая информация сохраняется в реестре. В частности IID всех интерфейсов. Совет: используйте OLE-COM Object Viewer, который поставляется с VC ++, чтобы просмотреть библиотеки типов. Было бы вообще великолепно, если бы Microsoft предоставлял исходные файлы или obj файлы с определениями идентификаторов интерфейсов. В существующей же ситуации я должен копировать их из Object Viewer'а и вставлять их в нужное место. Ниже приводится пример.
Читать дальше