How to get Inspector or MailItem from wordEditor

  • Thread starter Thread starter Tom
  • Start date Start date
T

Tom

Hi,

I am pretty new on Office Development with VBA/script. I appriciate any
suggestions and/or advices.

We have a project. The project is to check the URLs in the content of
emails. When user select a mail item in Outlook we grab all the URLs. If any
of them is dangerous then we will put notes to tell the user that this URL is
dangerous.

The project has 2 parts. The first part in C++ code. It gets the IDispatch
object from email inspector window. If the email editor is wordEditor then
let's just assume that the IDispatch object is a wordEditor object. The C++
code invoke javaScript function with wordEditor as parameter.

Another part is in javaScript. One of the function in javaScript take
wordEditor as parameter. This function will check the URLs in the wordEditor.
If any of any URL is dangerous then insert warning text around the URL.

The logic is from wordEditor we get myDocument =
wordEditor.Application.ActiveDocument. From myDocument we can get myRange =
myDocument.Range(0, 0); From myRange we call myEditor = myRange.Add(-1);

========================================
function CheckURLs(wordEditor)
{
var myDocument = wordEditor.Application.ActiveDocument;
var myRange = myDocument.Range(0, 0);
var myEditor = myRange.Add(-1); // it works fine on Outlook 2007 but not
2010
....
// unrelated code omited
....
}
========================================

Previously with Outlook 2007 there is no problem with the javaScript code
operated upon wordEditor. However in Outlook 2010 the problem line to Add(-1)
raise exception from javaScript. The exception does not give me much meaning.
So I wrote testing code in C++ with IDispatch::GetIDsOfNames(...) and
IDispatch::Invoke(...) to simulate the logic on javaScript. The exception now
gave me some hints - "This method is not available for the document is
read-only, can not check-in". I've tried some other ways to change content
with VBA/javaScript, finally I find a way to change it. Thanks Sue for
helping me solve the problem on "Can not change email body content on Outlook
2010". The VBA code is like:

=============================================
Sub test()
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim Item As Object

Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)

Set Item = Inbox.Items.Item(1)

Item.Body = "Test" & Item.Body
Item.Save
End Sub
=============================================

Now the problem is that the way I found to change the content using an obect
as MailItem. However the parameter passing to the javaScript is wordEdit. So
the question is that how to get the MailItem object from wordEditor?

Thanks in advance!

Tom
 
WordEditor is actually a Word.Document object you know, so
WordEditor.Application.ActiveDocument is redundant. It equates to
Document.Application.ActiveDocument.

If you have an Inspector, which you do to get WordEditor, why not just use
Inspector.CurrentItem to get the item in the Inspector, in this case a
MailItem? You can then use that object in your other code.
 
Hi Ken,

Thank you for the help. I may not state the situation clearly before.

When user select a mail in Outlook, our C++ code get called first. In C++
code we call AccessibleObjectFromWindow(m_hWnd, (DWORD)OBJID_NATIVEOM,
IID_IDispatch, (void**)&pDispWindow);

Where m_hWnd has class "_WwG" which is Word window. The IDispatch object
returned is wordEditor. Then we pass the wordEditor as the parameter to
javaScript code. From MSDN help document I am not able to get Outlook
Inspector object by calling API AccessibleObjectFromWindow(...).

So now I assume that the possible solutions are that:
1. Get Inspector object as IDispatch* in C++ and create new javaScript code
funtion which takes Inspector as parameter.
2. Get Inspector object from wordEditor object in the javaScript code.

Any other suggestions?
Thanks

Tom
 
A WordMail window has a class of "OpusApp", the same as any Word window. If
you have the caption of the WordMail window and that class name you should
be able to use FindWindow() to find the Inspector window and to get its
hWnd.

You're starting out backwards from where I usually work from.

I would handle all NewInspector() events on the Outlook.Inspectors
collection and as part of my instantiating a wrapper class for the new
Inspector I'd be getting the hWnd of the Inspector window that was opening.
I'd do that in the first Activate() event for the Inspector, when all the
properties are filled out (striong object reference).

From there I sometimes work down from that parent window (Inspector) to get
to "_WwG" using AccessibleObjectFromWindow(), if I need that hWnd or
something else from that OpusApp window.
 
Hi Ken,

Thanks for pointing out the new direction for it. But I still get problem on
this one.

I can get the window handle by FindWindow with class name "OpusApp". And
both Outlook main window and this window have the same process id & thread
id. Also there is only one window has "OpusApp" class name. I've verified
these 2 conditions by Spy++ (just make things simple).

Then I call hr = AccessibleObjectFromWindow( hWnd, (DWORD)OBJID_NATIVEOM,
IID_IDispatch, (void**)&pDispWindow); But hr = E_FAIL and pDispWindow = NULL.

If I call hr = AccessibleObjectFromWindow( hWnd, (DWORD)OBJID_WINDOW,
IID_IDispatch, (void**)&pDispWindow); Then hr = S_OK. But pDispWindow is not
Inspector object. Because I call IDispatch::GetIDsOfNames for "Application"
failed - "Unknown name".

OLECHAR * szApplication = L"Application";
DISPID dspid;
....
hr = pDispWindow->GetIDsOfNames(IID_NULL, &szApplication, 1,
LOCALE_SYSTEM_DEFAULT, &dspid);

I've tested both with Outlook 2007 & 2010.


Tom
 
The results you are seeing are inconsistent with what normally is seen with
Outlook and WordMail.

In Outlook 2003 you would have 2 windows as seen in Spy++ that have a class
of "OpusApp". One is a behind the scenes Word window with a caption of a
null string. That remains no matter how many WordMail windows are open.

Then there's another window per open WordMail Inspector that also has a
class of "OpusApp", but it has the same caption as the mail item subject,
and that's the parent window that has a child window "_WwG".

In Outlook 2007 due to the changes in WordMail, and how Word isn't now
subclassed but instead a Word dll is used, you don't look for "OpusApp". The
Inspector window has a caption that includes the subject plus a class of
"rctrl_renwnd32". If the subject is "foobar" the caption usually will be
something like this "foobar - Message (HTML)".

Looking for an Inspector window with a class of "rctrl_renwnd32" is how you
find windows using the Outlook editor in Outlook 2003 and earlier.

The main Outlook window (Explorer) will have a class of "rctrl_renwnd32",
and the caption will be whatever folder name is current, something like
"Inbox - Microsoft Outlook". That applies to all versions of Outlook.

There shouldn't be any confusion between Explorer windows and WordMail
windows in any version of Outlook, the class names are always different.

Where I use AccessibleObjectFromWindow() is in VB6 code to get a safe
Word.Document object (WordEditor) from an Inspector window if I cannot use
Redemption to avoid security prompts for Outlook 2002 and 2003. I get the
Inspector window handle as I indicated above. Then I enumerate child windows
until I get the one I want, say "_WwG".

I do use a OBJID_NATIVEOM argument to AccessibleObjectFromWindow(), to get
the WordMail child window ultimately from the Inspector window where I
start. The UID I use with AccessibleObjectFromWindow() is for IDispatch.

Usually as part of finding my window I'll compare the rect of whatever
windows I'm getting to the rect of the Inspector to verify they are the same
windows.

If I need to start from scratch to try to find the Inspector window I'll
usually try GetForegroundWindow() first if the window is active and is
ActiveInspector. I'll also use FindWindow(), FindWindowEx(), GetClassName(),
GetWindowText(), GetWindowTextLength(), and GetWindowRect(). I also use
EnumWindows() and EnumChildWindows() with callbacks to get down to the
WordMail window from the top level Inspector window. There's a lot of Win32
API heavy lifting in cases like that.
 
Thanks Ken. The further discusion will go out of the scope of Outlook & VBA.
I am going to ask on Outlook general another one.

Tom
 
Back
Top