如何可靠地确定从COM-Addin(Outlook <= 2003)内打开WordMail的给定Outlook检查器窗口的窗口句柄?

问题描述:

如何可靠地确定从COM-Addin(Outlook <= 2003)内打开WordMail的给定Outlook检查器窗口的窗口句柄?

对于“本土”的邮件检查员[这个代码是从Inspector.Activate事件处理(第一次调用),即权之前实际显示Inspector窗口。中调用]我可以简单地齐Inspector接口IOleWindow和呼叫它的方法是GetWindow。但是,这不适用于Word检查器,它实际上是具有特殊工具栏的Word实例,并且不执行IOleWindow

(暂时)将Inspector.Caption设置为某个唯一值,然后查找带有该标题的窗口也不起作用,因为在使用WordMail选项时,访问Inspector的大多数属性对实际的检查器窗口没有(立即)影响。既不调用Activate,然后立即查询GetForegroundWindow工作可靠:当有多个检查员已经打开或当实际的Word窗口存在时,这往往会返回“最古老”的实例,而不是最新的实例。

多年来,我尝试了许多其他方法,但它们最终都以某种方式出现了缺陷。有没有一个适度简单的解决方案呢?或者我需要采取一种更加精细的方法,比如通过系统挂钩保存我自己的已知窗口句柄列表,并试图将它们与已知的检查器进行匹配? (关于使用CBT挂钩的提示,请致电P Daddy

我现在想出了一些新的东西,我还没有打破,但它仍然感觉很像伏都教。通过观察,我发现我想要的窗口总是看起来是EnumWindows返回的第一个不是(还)可见的,也就是说IsWindowVisible返回False(记得我之前从Inspector.Activate事件的第一次出现中调用该代码检查员首次显示)。

如果有人知道一个更好的解决方案或有一个有原因的解释为什么这个作品(最好与权威文档的链接),请发表回复。

更新:所以,通过请求,这里有一些实际的(德尔福)代码。请注意,这不是我的工作代码,其中包含一些与此问题无关的其他内容,这些内容已在此处修剪。

function GetWindowClassName(const AHandle: HWND): String; 
var 
    lClass: array[0..255] of Char; 
begin 
    if GetClassName(AHandle, lClass, SizeOf(lClass)) > 0 then 
    Result := lClass 
    else 
    Result := ''; 
end; 

type 
    TWordSearchInfo = record 
    Result: HWND; 
    end; 
    PWordSearchInfo = ^TWordSearchInfo; 

function CheckWnd(AWnd: HWND; ASearchInfo: PWordSearchInfo): Boolean; stdcall; 
begin 
    Result := True; 
    try 
    if GetWindowClassName(AWnd) = 'OpusApp' then 
     if not IsWindowVisible(AWnd) then 
     begin 
      ASearchInfo.Result := AWnd; 
      Exit(False); 
     end; 
    except 
    //plop! 
    end; 
end; 

function GetNewestWordHandle: Cardinal; 
var 
    lSearchInfo: TWordSearchInfo; 
begin 
    lSearchInfo.Result := 0; 
    EnumWindows(@CheckWnd, Integer(@lSearchInfo)); 
    Result := lSearchInfo.Result; 
end; 

注:我只能用这个函数从检查的Activate -event内,当观主要版本< 12和检查员的IsWordMail - 属性是True

+0

我试过这种方法,但EnumWindows根本没有返回wordmail窗口(OpusApp)。你有没有找到更好的解决方案?如果不是,你是如何实现代码来获得窗口的? – Moox 2011-03-10 17:46:49

+0

@Moox:你什么时候调用`EnumWindows`?我在那里没有做任何特别的事情。我稍后会发布一些片段。 – 2011-03-11 10:27:58

我发现在自定义检查器的构造函数中,可以使用以下方法来查找新构造的检查器。

C#

inspectorWindow = Win32.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "OpusApp", "Microsoft Word");

你必须这样做,在构造函数中,事后的标题成为消息(“无标题消息”上的新邮件)的称号。我假设如果您有一条名为Microsoft Word的消息已经打开,由于含糊不清,可能会有错误,但发生的机会有点低。