2008-11-18 7 views
3

[Ce code est appelé à partir du gestionnaire d'événements Inspector.Activate (premier appel), soit juste avant la fenêtre de l'inspecteur est effectivement montré.]Comment déterminer de manière fiable le handle de fenêtre d'une fenêtre d'inspecteur Outlook donnée avec WordMail activé à partir d'un COM-Addin (Outlook <= 2003)?

Pour les inspecteurs de courrier « natifs » Je peux simplement QI l'interface Inspector-IOleWindow et appel sa méthode GetWindow. Toutefois, cela ne fonctionnera pas pour les inspecteurs Word qui sont en fait des instances de Word avec une barre d'outils spéciale et n'implémentent pas IOleWindow.

(temporairement) Inspector.Caption définir une valeur unique et puis la recherche d'une fenêtre avec cette légende ne fonctionne pas non plus car l'accès à la plupart des propriétés du Inspector n'a aucun effet (immédiat) sur la fenêtre inspecteur réelle lors de l'utilisation de l'option WordMail . Le fait d'appeler Activate et d'interroger immédiatement le GetForegroundWindow ne fonctionne pas de manière fiable: lorsque plusieurs inspecteurs sont déjà ouverts ou lorsque des fenêtres Word sont présentes, cela renvoie souvent l'instance «la plus ancienne» au lieu de la plus récente.

J'ai essayé un certain nombre d'autres approches au cours des années, mais elles se sont toutes révélées être défectueuses d'une manière ou d'une autre. Y a-t-il une solution modérément simple ou devrais-je adopter une approche beaucoup plus élaborée comme garder ma propre liste de poignées de fenêtres connues via un hook système et essayer de les faire correspondre aux inspecteurs connus? (P Daddy pour l'indice sur l'utilisation de crochets CBT)

Répondre

1

J'ai maintenant trouvé quelque chose de nouveau que je n'ai pas encore réussi à casser mais cela ressemble toujours beaucoup au vaudou. Par observation j'ai trouvé que la fenêtre que je veux toujours semble être la première retournée par EnumWindows qui n'est pas (encore) visible, ie IsWindowVisible renvoie False (rappelez-vous que j'appelle ce code depuis la première occurrence de l'événement Inspector.Activate juste avant l'inspecteur est affiché pour la première fois).

Si quelqu'un connaît une meilleure solution ou a une explication bien fondée de pourquoi cela fonctionne (de préférence avec des liens vers des documents faisant autorité), s'il vous plaît poster une réponse.

Mise à jour: Donc, sur demande, voici un code (Delphi) réel. Notez que ce n'est pas mon code de travail, qui contient quelques autres choses, qui ne sont pas pertinentes pour cette question, qui ont été supprimées ici.

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; 

Note: Je n'utiliser cette fonction à l'intérieur Activate -event et lorsque la version majeure Outlook est < 12 et l'inspecteur de IsWordMail -property est True de l'inspecteur.

+0

J'ai essayé cette approche, mais EnumWindows n'a pas du tout retourné la fenêtre de messagerie (OpusApp). Avez-vous déjà trouvé une meilleure solution? Si non, comment avez-vous implémenté le code pour obtenir la fenêtre? – Moox

+0

@Moox: Quand appelez-vous 'EnumWindows'? Je ne fais rien de spécial ici. Je posterai des extraits plus tard. –

+0

@Moox: J'ai ajouté un extrait de code à ma réponse, maintenant. S'il vous plaît prendre note de la note ci-dessous l'extrait concernant les circonstances très restreintes dans lesquelles je m'en sers. –

0

J'ai trouvé que sur le constructeur de l'inspecteur personnalisé, vous pouvez utiliser la méthode suivante pour trouver l'inspecteur nouvellement construit.

C#

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

Vous devez le faire sur le constructeur, après la légende devient le titre du message ("Message sans titre" sur les nouveaux messages). Je suppose que si vous avez un message nommé Microsoft Word déjà ouvert, il peut y avoir une erreur en raison de l'ambiguïté, mais les chances que cela arrive sont assez faibles.

+0

Je suis également assez sûr que cela trouverait également des fenêtres de Word réelles qui ont également un nom de classe de "OpusApp". En dehors de cela, je n'ai pas d'inspecteur personnalisé: je suis en train d'accrocher ceux qui existent déjà via les gestionnaires d'événements. –

Questions connexes