更新,以使问题更易于阅读,以下评论
场景:用户在outlook 365中点击回复,这将在outlook的主窗口中打开一个邮件项。我们正在尝试向这个mailItem的正文中添加文本。
目前,我的方法可以将文本添加到嵌入的mailItem的to和cc字段,但不能添加正文。它将添加文本到body, to, Cc和Subject的模态mailItem,随着这个模态打开,它甚至会添加文本到mailItem的body,它以前不能工作。
当只打开主窗口时,focusedClass不存在,因此它击中SendMessage方法。
问题:如何将文本添加到此mailItem的正文中?当只打开Outlook主窗口并且MailItem嵌入在主窗口中时。
到目前为止,我已经看了spy++和Z顺序总是变化,所以我找不到一个合乎逻辑的方式来获得一个子窗口的工作,加上mailItem的结构是不同的,而在主窗口和模态。
我目前的解决方案使用GetWindowThreadProcessId和getcurrentthreaddid来获得焦点窗口,然后使用GetFocusClass来查找类,获得这个类后,我们最终调用下面的方法来插入文本:
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;
}
不确定为什么你要使用GetFocus()
等来找到Word编辑器的HWND
-焦点可以在检查器中的任何地方(例如主题或编辑框),加上点击ribbon可以将焦点从Word编辑器中带走,即使它一开始就在那里。
对我有用的是:
- QI/cast你的
Inspector
对象(例如从Application.ActiveInspector
检索)到IOleWindow
。调用IOleWindows.GetWindow()
,获取督察的最高级别HWND
。 - 调用
EnumChildWindows
,调用GetClassName
并与"_WwG"
进行比较。请注意,在Office 12及更早的版本中,类名是"_WwF"
。
我也不确定你的代码有什么问题,使用Word对象模型插入文本。对我来说,它看起来非常好(没有实际调试它),这将是一个更好的解决方案,因为它将在进程外工作,因为SendMessage(EM_REPLACESEL)
要求调用者和目标窗口都在同一个进程中(因为它需要一个指向文本缓冲区的指针)。