C#Outlook - 如何在MailItem的主题字段中获取光标位置?

时间:2016-07-18 10:04:22

标签: c# outlook com-interop

我想在C#AddIn中的MailItem的主题字段中的当前光标位置插入一个文本。

我还必须知道光标是否在主题字段中。

有谁知道如何解决它?

修改

要清除我想要做的事情: 使用Message我的AddIn打开一个WPF窗口,用户可以在其中选择一个标签中的一个(例如“{stuff}”)。 如果用户点击WPF窗口中的插入按钮,则AddIn必须在当前光标位置插入标记。实际上我可以将它插入邮件正文中。

如果光标位于主题字段中,则必须在光标位置的主题字段中添加标记。

1 个答案:

答案 0 :(得分:1)

这不是一件容易的事,但我认为可能。

理论上应该可以按照以下步骤进行:

您可以致电GetGUIThreadInfo获取有效用户界面线索的Carret-Position(参阅:pInvoke: GetGuiThreadInfo

评估的结构包含public System.Drawing.Rectangle rcCaret 这是客户坐标中相对于窗口的插入符号边界矩形。“(参见:MSD GuiThreadInfoStructure

跟进MSDN文章中描述的步骤:GetGUIThreadInfo function

MSDN说:
要在 rcCaret 矩形中获取实际插入点,请执行以下步骤:

  1. 致电GetKeyboardLayout以检索当前的输入语言。

  2. 根据当前输入语言确定用于光标的字符。

  3. 使用Sans Serif for the font调用CreateFont rcCaret 指定的高度,宽度为零。对于 fnWeight ,请致电SystemParametersInfo(SPI_GETCARETWIDTH, 0, pvParam, 0)。如果pvParam大于1,则将fnWeight设置为700,否则将fnWeight设置为400。

  4. 在设备上下文(DC)中选择字体,并使用GetCharABCWidths获取相应光标字符的B宽度。

  5. 将B宽度添加到 rcCaret.left 以获取实际插入点。

  6. 提示:当调用前端线程的信息时,该函数可能无法返回GUITHREADINFO结构中的有效窗口句柄,例如当窗口失去激活时。

    还有一个CodeProject-Article (Getting Caret Position Inside Any Application),有人通过评估carret的屏幕位置(坐标)来显示第三方应用程序中的工具提示。

    长话短说...我不知道你的明确任务,但感觉就像是'Hack' - 你能不能以更好的'formally'方式解决它?喜欢附加到事件(PropertyChnaged)或其他东西来解决主题变化?

    <强>更新
    最后,我能够从另一个应用程序中读取Subject-Field中的值。 Microsoft Outlook电子邮件窗口中的主题字段是RichEdit-Control(ClassName:RichEdit20WPT) 使用ControlID“4101”。 我无法挂钩这个控件的消息(它不可能来自不同的应用程序/线程,我没有构建一个AddIn - 我认为如果你为这个任务构建一个add,它可以附加:(附加到{ {3}}并过滤WM_NOTIFY以获取键盘事件EN_MSGFILTER

    但您可以通过以下方式阅读当前值:

     [DllImport("user32.dll")]
     static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
    
     const int WM_GETTEXT = 0x000D;
     const int WM_GETTEXTLENGTH = 0x000E;
    
     public static string GetControlText(IntPtr hWndOfControl)
      {    
        StringBuilder title = new StringBuilder();
    
        // Get the size of the string 
        Int32 size = SendMessage((int)hWndOfControl, WM_GETTEXTLENGTH, 0, 0).ToInt32();
    
         // If Size > 0 ? -> Text available...
         if (size > 0)
          {
           title = new StringBuilder(size + 1);    
           SendMessage(hWndOfControl, (int)WM_GETTEXT, title.Capacity, title);
          }
    
         return title.ToString();
       }
    

    如果你无法获得carret位置,也许你可以将Focus设置回控件并使用SendKeys将文本插入当前位置。 使用SendMessage WM_SETTEXT也可以设置文本。 也许这会对你有帮助......