简体   繁体   中英

Outlook Interop add body text

Updated to try and make the question more readable, following comments below

Scenario: user clicks reply in outlook 365 this opens a mailItem within the main window of outlook. we are attempting to add text to the body of this mailItem.

Currently my method can add text to the to and cc field of the imbedded mailItem but not the body. It will add text to the body, To, Cc, and Subject of a modal mailItem, with this modal open it will even add text to the mailItem's body that it would not work with previously.

When only the main window is open, the focusedClass is not present, so it hits the SendMessage method.

Question: How do you add text to the body of this mailItem? When only the main Outlook window is open and the MailItem is imbedded in the main window.

So far I have looked at Spy++ and the Z order always changes so I cannot find a logical way to get a child window to work with, plus the structure for the mailItem is different while in the main window and modal.

My current solution uses GetWindowThreadProcessId and GetCurrentThreadId to get the focused window, then the GetFocusClass to find the class, with this class obtained we finally call the below to insert the text:

 if (focusedClass.ToLower() == "_wwg")
                InsertTextToEmailBody(text);
            else
                SendMessage(focused, EM_REPLACESEL, 0, newText);
private void InsertTextToEmailBody(string text)
        {
            var outlookApplication = GetOulookApplication();
            var activityInspector = outlookApplication.ActiveInspector();
            var currentItem = activityInspector?.CurrentItem;

            if (currentItem == null)
            {
                _log.Error("InsertTextToEmailBody could not find CurrentItem and cannot inject into email body");
                return;
            }

            var myInspector = ((MailItem) currentItem).GetInspector;
            var wdDoc = (Document) myInspector.WordEditor;
            var currentSelection = wdDoc.Application.Selection;

            if (currentSelection.Range?.Text?.Length > 0)
            {
                //The user has a selected range of text, replace that with transcription
                currentSelection.Range.Text = text;
                return;
            }

            // Store the user's current Overtype selection
            var userOvertype = wdDoc.Application.Options.Overtype;

            // Make sure Overtype is turned off.
            if (wdDoc.Application.Options.Overtype) wdDoc.Application.Options.Overtype = false;

            // Test to see if selection is an insertion point.
            if (currentSelection.Type == WdSelectionType.wdSelectionIP)
                currentSelection.TypeText(text);
            else if (currentSelection.Type == WdSelectionType.wdSelectionNormal)
            {
                // Move to start of selection.
                if (wdDoc.Application.Options.ReplaceSelection)
                {
                    object direction = WdCollapseDirection.wdCollapseStart;
                    currentSelection.Collapse(ref direction);
                }

                currentSelection.TypeText(text);
            }

            // Restore the user's Overtype selection
            wdDoc.Application.Options.Overtype = userOvertype;
        }

Not sure why you'd want to use GetFocus() etc. to find the HWND of the Word editor - the focus can be anywhere in the Inspector (eg Subject or To edit box), plus clicking on the ribbon can take the focus away from the Word editor even if it was there to begin with.

What works for me is the following:

  1. QI/cast your Inspector object (eg retrieved from from Application.ActiveInspector ) to IOleWindow . Call IOleWindows.GetWindow() to get the top level HWND of the inspector.
  2. Call EnumChildWindows with a callback that calls GetClassName and compares it with "_WwG" . Note that in Office 12 and older the class name is "_WwF" .

I also not sure what is wrong with your code that uses Word Object Model to insert text. It looks perfectly fine to me (without actually debugging it), and it would be the preferable solution since it would work out-of-proc since SendMessage(EM_REPLACESEL) requires that both the caller and the target window are in the same process (since it takes a pointer to a text buffer).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM