| imho.ws |
![]() |
|
|
|
# 1 |
|
Newbie
Регистрация: 17.05.2007
Сообщения: 14
![]() |
C# и MAPI
Пишу програмку для работы с Outook 2003/2007
Как можно из С# используя MAPI получить объект Inspector? Обычный метод это: Outlook.Application oApp = new Outlook.Application(); Outlook.NameSpace oNS = oApp.GetNamespace("mapi"); Outlook.MAPIFolder oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); Microsoft.Office.Interop.Outlook.Items oItems = oInbox.Items; Microsoft.Office.Interop.Outlook.MailItem oMsg = null; oMsg = (Microsoft.Office.Interop.Outlook.MailItem)oItems[1]; Inspector oInsp = oMsg.GetInspector; mshtml.IHTMLDocument2 htDoc = (mshtml.IHTMLDocument2)oInsp.HTMLEditor; Вот на этой строке включается Outlook security. Читал что обойти Outlook security можно, если использовать MAPI. А как его использовать в C# незнаю
|
|
|
|
|
# 2 |
|
Member
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245
![]() ![]() |
Не совсем понимаю что вы называете "объект Inspector".
Если вам , судя по приведенному коду, нужно получить IHTMLDocument2 то это можно сделать и без MAPI, достаточно иметь хендл окна ActiveX-а (его СlassName - ""Internet Explorer_Server"). Код примерно такой : Код:
BOOL CWebConnectivity::GetHTMLDocFromWnd(HWND hWnd, MSHTML::IHTMLDocument2Ptr& spOutDoc2) const
{
if(!hWnd)
return FALSE;
spOutDoc2=NULL;
static UINT MSG = RegisterWindowMessage(TEXT("WM_HTML_GETOBJECT"));
wstring ClassName("");
TCHAR buf[MAX_LEN];
::GetClassName(hWnd,buf,sizeof(buf)/sizeof(TCHAR)-2);
ClassName=buf;
if(ClassName != TEXT("Internet Explorer_Server"))
{
if (ClassName == TEXT("Internet Explorer_TridentCmboBx") ||
ClassName == TEXT("Internet Explorer_TridentLstBox"))
{
hWnd = ::GetParent(hWnd);
::GetClassName(hWnd,buf,sizeof(buf)-2);
ClassName=buf;
if(ClassName != TEXT("Internet Explorer_Server") )
return FALSE;
}
}
DWORD lRes = 0;
LRESULT res = ::SendMessageTimeout(hWnd, MSG, 0, 0, SMTO_ABORTIFHUNG, 1000, &lRes);
if (!res)
return FALSE;
if(::ObjectFromLresult(lRes,MSHTML::IID_IHTMLDocument2,0,(void**)&spOutDoc2) == S_OK)
{
return TRUE;
}
return FALSE;
}
Есть некоторые тонкости. Например IHTMLDocument-ы могут быть вложенными, придеться делать энумирацию доков чтоб-бы добраться до нужного, и т.д. Если будет интересно - спрашивайте.
__________________
Best Regards |
|
|
|
|
# 3 |
|
Newbie
Регистрация: 17.05.2007
Сообщения: 14
![]() |
Спасибо.
Microsoft.Office.Interop.Outlook.Inspector - это окно просмотра email сообщения (которое, в зависимости от формата письма, содержит вложенное окно одного из ActiveX-ов : Microsoft.Office.Interop.Outlook.OlEditorType.olEditorHTML Microsoft.Office.Interop.Outlook.OlEditorType.olEditorRTF Microsoft.Office.Interop.Outlook.OlEditorType.olEditorWord Microsoft.Office.Interop.Outlook.OlEditorType.olEditorText ) Аналогичную функцию GetHTMLDocFromWnd я использую. Но этот код работает только в том случае если у нас письмо в HTML формате. А во если в формате Word то получить WordDocument через hWnd не получается. Поэтому получаю его через Microsoft.Office.Interop.Outlook.Inspector (в данном случае WordEditor). На что выскакивает окно security. Для обхода security ищу информацию по использованию oMsg.MAPIOBJECT из C#? |
|
|
|
|
# 4 |
|
Member
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245
![]() ![]() |
Можно попытаться и Word получить через AccessibleObject. Я правда никогда не пробовал, но есть большая вероятность что будет работать.
Порядок действий должен быть следующий : Получить AccessibleObject из окна или точки (функция AccessibleObjectFromPoint). Потом из AccessibleObject-а получить IServiceProvider, примерно так : Код:
IServiceProviderPtr pSP;
IAccessiblePtr pAcc;
if(AccessibleObjectFromPoint(pt, &pAcc, &varId)==S_OK)
{
if(pAcc->QueryInterface(IID_IServiceProvider, (void **)&pSP)==S_OK)
{
//Тут сделать QueryService на соответствущий СОМ интерфейс Ворда
Word::_DocumentPtr spDoc;;
if(pSP->QueryService(Word::IID_Document,Word::IID_Document, (void **)&spDoc)==S_OK)
{
....
}
}
Но сам принцип должен работать. Я в своих прогах таким образом получаю HTML елементы из экранной точки.
__________________
Best Regards |
|
|
|
|
# 5 |
|
Newbie
Регистрация: 17.05.2007
Сообщения: 14
![]() |
Инересный метод. Попробую обязательно.
И еще один впрос касательно Outlook 2007. В 2007 окно просмотра email сообщения не содержит "Internet Explorer_Server", при любых форматах принимаемых писем они выводятся в Word (activex-е). Допустим я обошел проблему получения этого Word-ctrl. Мне необходимо скопировать содержание этого Word окна в BMP. C IHTMLDocument проблем не было там делал Scroll и PrintWindow. А с Word-ом не удается получить размеры всего она сообщения, следовательно scroll не получается нормально делать. Кроме того не получилось скопировать содержимое окна через PrintWindow. Пробовал использовать BitBlt - но это самый худший вариант ![]() Может есть методы работы с Word-ctrl? |
|
|
|
|
# 6 |
|
Member
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245
![]() ![]() |
Я, к сожалению, не очень хорошо знаком с офисным COM. Но он хорошо задокументирован в MSDN.
Думаю что последовательность действий примерно такая : Сначала надо добраться до поинтера на _Application (Наверное будет работать GetActiveObject c соответствующим class id). Потом получить указатель на интерфейс Window ( скорее всего так app->GetActiveWindow()). А у Window есть методы GetVerticalPercentScrolled и PutVerticalPercentScrolled. Более точно нужно спрашивать у людей которые пишут на VBA для Word, они обычно хорошо знают все эти замороки. P.S. Typelibrary ворда можно просмотреть с помощью утилитки оleview ( она помоему входит в поставку VS и Platform SDK). Typelibrary ворда находится в файле MSWORD.OLB. ( У меня на компьютере C:\Program Files\Microsoft Office\Office12\MSWORD.OLB).
__________________
Best Regards |
|
|
|
|
# 7 |
|
Newbie
Регистрация: 17.05.2007
Сообщения: 14
![]() |
Пробовал GetActiveWindow(), GetVerticalPercentScrolled и PutVerticalPercentScrolled. И они не совсем подходят для определения реальных размеров документа. А в версии Outlook 2007 функция GetActiveWindow() запрещена. (видимо для повышения секретности)
Словом каждая новая версия хуже предыдущей. Попробую напрямую посылать WM_KEYDOWN (VK_DOWN) на hWnd Word окна. Может и получится. |
|
|
|
|
# 8 |
|
Newbie
Регистрация: 17.05.2007
Сообщения: 14
![]() |
Решение найдено!
У Word Typelibrary есть понятие Range и Slection, которые имеют замечательную функцию Copy() и CopyAsPicture(). Кроме того можно получить данные текущего Range в формате Enhanced Meta File используя member variable EnhMetaFileBits.
|
|
|