代码之家  ›  专栏  ›  技术社区  ›  Oliver Giesen

如何在COM加载项(Outlook<=2003)内打开WordMail的情况下可靠地确定给定Outlook检查器窗口的窗口句柄?

  •  3
  • Oliver Giesen  · 技术社区  · 17 年前

    [此代码从内部调用 Inspector.Activate 事件处理程序(第一次调用),即在实际显示检查器窗口之前。]

    对于“本地”邮件检查员,我可以简单地QI Inspector 接口连接 IOleWindow 并称之为 GetWindow 方法。但是,这对Word检查器不起作用,因为Word检查器实际上是带有特殊工具栏的Word实例,并且没有实现 IOleWindow .

    (临时)设置 Inspector.Caption 将某个唯一值设置为某个值,然后查找带有该标题的窗口也不能像访问 检查员 使用WordMail选项时,对实际的检查器窗口没有(立即)影响。也不打电话 Activate 然后立即查询 GetForegroundWindow 工作可靠:当有多个检查器已经打开或实际存在Word窗口时,这通常只会返回“最旧”的实例,而不是最近的实例。

    多年来,我尝试了许多其他方法,但最终都以某种方式被证明是有缺陷的。是否有一个相对简单的解决方案,或者我必须采取一种更复杂的方法,比如通过系统挂钩保存我自己的已知窗口句柄列表,并试图以某种方式将它们与已知的检查器相匹配?(帽子尖到 P Daddy 关于使用CBT钩子的提示)

    2 回复  |  直到 9 年前
        1
  •  1
  •   Oliver Giesen    15 年前

    我现在想出了一些我还没能打破的新东西,但它仍然感觉很像巫毒教。通过观察,我发现我想要的窗口似乎总是第一个返回的窗口 EnumWindows (尚未)可见,即。 IsWindowVisible 返回 False (记住,我是在第一次出现 Inspector.Activate 在检查器首次显示之前发生的事件)。

    如果有人知道更好的解决方案,或者有充分的理由解释为什么这是有效的(最好有权威文档的链接),请发布回复。

    更新: 因此,根据请求,这里有一些实际的(Delphi)代码。请注意,这不是我的工作代码,它包含了一些与这个问题无关的其他内容,这些内容在这里被删除了。

    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 -事件,以及Outlook主版本为<12和检查员 IsWordMail -财产是 True .

        2
  •  0
  •   Moox    15 年前

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

    C

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

    您必须在构造函数上执行此操作,之后标题将成为消息的标题(新消息上的“无标题消息”)。我假设如果你已经打开了一条名为Microsoft Word的消息,可能会因为歧义而出现错误,但发生这种情况的可能性有点低。