Здравствуйте. Я сейчас пишу Addin для MSWord. Мне необходимо реализовать запрет печати. Я использую IDispEventSimpleImpl интерфейс. Наследуюсь от него таким образом:
public IDispEventSimpleImpl<1,CAddin, &__uuidof(MSWord::ApplicationEvents2)>
С помощью OLE/COM Object Viewer нахожу ApplicationEvents2 и нужный мне метод DocumentBeforePrint:
Пока не могу найти решения. Где-то прочитал, что подобная проблема была при использовании .NET, но она, как пишет Microsoft, исправлена в Офисе 2003. У меня .Net установлен, но этот проект я пишу на VC++6.
Может у кого-то были подобные проблемы. Подскажите что делать.
И еще, как правильно заполнять _ATL_FUNC_INFO, в часности, когда указывать VT_BYREF в зависимости от [in] [out]. Я видел несколько примеров и везде по-разному, у меня ПОКА работает и так, и так.
19.03.05 17:57: Перенесено модератором из 'C/C++. Прикладные вопросы' — Odi$$ey
Re: Обработка событий MSOffice, IDispEventSimpleImpl
Здравствуйте, BorysB, Вы писали:
BB>Я сейчас пишу Addin для MSWord. Мне необходимо реализовать запрет печати. Я использую IDispEventSimpleImpl интерфейс. BB>Ф-я обработчик выглядит так: BB>
BB>void __stdcall CAddin::DocumentBeforePrint(IDispatch* /*_Document**/ Doc, VARIANT_BOOL *Cancel)
BB>{
BB> VARIANT_BOOL *myCancel = new VARIANT_BOOL(VARIANT_TRUE);
BB> Cancel = myCancel;
BB> MessageBox(NULL, "Document is going to be printed", "Message", MB_OK);
BB>}
BB>
BB>Дело в том, что все работает, только VARIANT_BOOL *Cancel игнорируется.
А если просто
*Cancel = VARIANT_TRUE;
тогда что?
Пользователь — друг программиста!
Re[2]: Обработка событий MSOffice, IDispEventSimpleImpl
Здравствуйте, Elena_, Вы писали:
E_>А если просто E_>
E_>*Cancel = VARIANT_TRUE;
E_>
E_>тогда что?
На сколько я помню таком случае Ворд падает, т.к. Cancel указывает на "плохую" область памяти. Именно поэтому я выделяю память под новую переменную. Но я попробуюю еще раз и скажу точно.
Re[3]: Обработка событий MSOffice, IDispEventSimpleImpl
Вы вообще ничего не передаете для вызывающей программы, кроме того выделяете память, которая не будет освобождена, так что в любом случае вряд ли этот код подходит
Пользователь — друг программиста!
Re[2]: Обработка событий MSOffice, IDispEventSimpleImpl
E_>Вы вообще ничего не передаете для вызывающей программы, кроме того выделяете память, которая не будет освобождена, так что в любом случае вряд ли этот код подходит
Почему таким образом я ничего не передаю? Я эту кашу понимаю следующим образом:
Ворд, судя по всему, — вызывает мою функцию. Я используюю _ATL_FUNC_INFO DocumentBeforePrintInfo = {CC_STDCALL... т.е. stdcall CallingConvention. Следовательно Ворд должен чистить память (The callee cleans the stack. This is the default convention for calling unmanaged functions with platform invoke. MSDN).
Если все правильно то параметры должны передаваться по ссылке:
Но я не уверен. И вообще я не могу четко понять относительно кого по ссылке. Моя функция выполняет роль call-back функции и вызывается вместо соответствующей функции этого интерфейса.
BB>Тогда параметры должны передаваться мне,..по ссылке?........? Почти ничего не понимаю.
Правила просты: если есть *, то к типу добавляешь |VT_BYREF, но если тип — интерфейс, то добавлять не надо, т.к. интерфейс сам имеет одну *. Чтобы интерфейс имел |VT_BYREF, нужно чтобы было две *, т.е. [in] Document** Doc.
Здравствуйте, Vi2, Вы писали:
Vi2>Правила просты: если есть *, то к типу добавляешь |VT_BYREF, но если тип — интерфейс, то добавлять не надо, т.к. интерфейс сам имеет одну *. Чтобы интерфейс имел |VT_BYREF, нужно чтобы было две *, т.е. [in] Document** Doc.
Спасибо, все так и сделал, но, увы, не помогло.
Получается, что способ передачи параметров по большому счету не зависит от [in] [out].
А если у нас [optional], то можно ли передавать просто NULL, или нужно какие-то VT_EMPTY обязательно?
Re[3]: Обработка событий MSOffice, IDispEventSimpleImpl
Здравствуйте, BorysB, Вы писали:
BB>Попробовал сделать то же самое для BeforeSave. Никакого эфекта. Параметры не играют никакой роли. Что это можеть быть даже и не знаю.
Вот есть такое описание ошибки, хотя у Вас вроде все кроме Cancel работает, вряд ли это то самое, но там и пример есть, может пригодиться
BUG: ATL COM Event Handler May Receive Arguments in Reverse Order Q288724
Пользователь — друг программиста!
Re[7]: Обработка событий MSOffice, IDispEventSimpleImpl
и не работает?
BB>Получается, что способ передачи параметров по большому счету не зависит от [in] [out].
Почему не зависит? Очень даже зависит. Если параметр не [out], то его невозможно изменить или передать вовне сервера. Если он не [in], то бесполезно проверять его входное значение.
BB>А если у нас [optional], то можно ли передавать просто NULL, или нужно какие-то VT_EMPTY обязательно?
Как правило, optional параметр передается специальным Variant-ом с vt:=VT_ERROR и scode:=DISP_E_PARAMNOTFOUND.
Здравствуйте, Elena_, Вы писали:
E_>Вот есть такое описание ошибки, хотя у Вас вроде все кроме Cancel работает, вряд ли это то самое, но там и пример есть, может пригодиться
E_>BUG: ATL COM Event Handler May Receive Arguments in Reverse Order Q288724
Спасибо за совет. Буду пробовать...
Re[5]: Обработка событий MSOffice, IDispEventSimpleImpl
Здравствуйте, Elena_, Вы писали:
E_>Вот есть такое описание ошибки, хотя у Вас вроде все кроме Cancel работает, вряд ли это то самое, но там и пример есть, может пригодиться
E_>BUG: ATL COM Event Handler May Receive Arguments in Reverse Order Q288724
Спасибо огромное! Сделал как написано в Q288724, сначала не помогло. Но потом изменил void __stdcall на STDMETHOD и все вместе заработало. Но эта статья, реально, очень важная вещь.
Всем огромное спасибо за помощь!!!