2010-06-19 16 views
3

AxAcroPDF avale tous les événements liés aux touches dès qu'ils sont activés, y compris les raccourcis, les touches, etc. J'ai ajouté un filtre de message et aucun message relatif à la clé. C'est un composant COM, cela pourrait-il être pertinent?AxAcroPDF avaler des clés, comment l'arrêter?

Y at-il un moyen de les attraper avant que le contrôle commence à les avaler?

Répondre

4

Hans a raison, Acrobat Reader génère deux processus enfants AcroRd32 auxquels vous n'avez aucun accès direct depuis votre code managé.

Je l'ai expérimenté avec cela et vous avez trois options viables:

  1. Vous pouvez créer un crochet système global , puis rechercher et filtrer les/répondre à WM_SETFOCUS les messages envoyés à votre enfant Acrord32 les fenêtres. Vous pouvez accomplir une partie de ceci à partir de C# en utilisant une bibliothèque wrapper, comme celle-ci: http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx

    Vous devez également identifier les processus corrects, car il peut y avoir plusieurs instances de votre application ou d'autres instances de AcroRd32. C'est la solution la plus déterministe, mais comme votre application va maintenant filtrer les messages envoyés à chaque fenêtre existante, je ne recommande généralement pas cette approche car votre programme pourrait affecter négativement la stabilité du système.

  2. Rechercher Autre commande de visualisation de PDF. Voir cette réponse pour quelques composants commerciaux: .net PDF Viewer control, ou rouler votre propre: http://www.codeproject.com/KB/applications/PDFViewerControl.aspx

  3. Trouver un bidouille acceptable. En fonction de la robustesse de votre application doit être, le code tel que le suivant peut convenir (il a été adapté pour mon cas):

    DateTime _lastRenav = DateTime.MinValue; 
    
    public Form1() 
    { 
        InitializeComponent(); 
    
        listBox1.LostFocus += new EventHandler(listBox1_LostFocus); 
    } 
    
    private void listBox1_SelectedIndexChanged(object sender, EventArgs e) 
    { 
        axAcroPDF1.src = "sample.pdf"; //this will cause adobe to take away the focus 
        _lastRenav = DateTime.Now; 
    } 
    
    void listBox1_LostFocus(object sender, EventArgs e) 
    { 
        //restores focus if it were the result of a listbox navigation 
        if ((DateTime.Now - _lastRenav).TotalSeconds < 1) 
         listBox1.Focus(); 
    } 
    
+0

+1 pour une réponse concise, bien que le hack acceptable particulier ne fonctionne pas pour moi (Laisser l'événement + TextBox au lieu de l'événement LostFocus d'un ListBox) - j'ai essayé l'autre solution proposée qui figure beaucoup dans les réponses à axAcroPDF + autour du Web - en utilisant Timer et en l'activant juste après avoir appelé AxAcroPDF.LoadFile, en réglant le focus sur le formulaire dans le gestionnaire d'événements Tick et en désactivant le timer juste après –

2

Il s'agit d'un composant COM hors processus, c'est le problème. Complètement en violation des exigences de Windows SDK telles que définies dans SetParent(). Une fois que sa fenêtre obtient le focus, la boucle de message dans le processus acroread.exe reçoit tous les messages, votre filtre de message ne peut plus voir aucun message.

Techniquement, il est réparable en utilisant SetWindowsHookEx() pour injecter une DLL dans le processus et surveiller les messages avec WH_GETMESSAGE. Mais vous ne pouvez pas écrire une telle DLL dans le langage C#.

Major sucer, je sais. Il ne semble jamais y avoir de manque avec ce programme.

+0

Adobe enfreignant les exigences du SDK? Dites que ce n'est pas le cas! Le correctif semble être un peu plus d'effort que ce que je peux justifier pour mes besoins en ce moment, mais bon à savoir au cas où cela changerait dans le futur. –

4

je pourrais enfin avoir une réponse ridiculement simple. Jusqu'à présent, dans les tests, cela fonctionne. Ayant souffert de ce problème pendant un certain temps et ayant construit un système complexe de chaque enregistrement de contrôle personnalisé qui d'entre eux avait le focus et en utilisant une minuterie pour revenir en arrière (quand acropdf l'a attrapé) j'ai revisité ce problème et lu un grand nombre de réponses (à la recherche de solutions récentes). L'information glanée m'a aidé avec l'idée.

L'idée est de désactiver le (AcroPDF) contrôle alors qu'il est en cours de chargement comme dans l'exemple suivant (le code réduit pour plus de clarté)

AxAcroPDF_this.Activé = Faux AxAcroPDF_this.src = m_src

Puis sur une minuterie, par exemple 1 seconde.

AxAcroPDF_this.Enabled = False

Fondamentalement, l'idée est de dire à Windows de ne pas laisser les utilisateurs utilisent le contrôle AcroPDF jusqu'à ce permis, afin de demander Windows pour l'empêcher de se focus (parce que les utilisateurs ne sont pas autorisés là-bas) .

Jusqu'à présent, cela se passe, je vais l'éditer si quelque chose change. Si cela ne fonctionne pas complètement pour vous alors peut-être l'idée pointe dans une direction utile.

+0

J'ai créé une méthode d'extension pour cela (Windows Forms uniquement): https: //gist.github.com/bertvansteen/ec180b645fd6bcfd179e – bvs

1

Pour une raison quelconque, la réponse de Tim, désactivant directement le contrôle AxAcroPDF, ne fonctionnait pas dans mon cas. L'événement Leave sur la zone de texte précédemment sélectionnée ne se déclenchera jamais non plus. Ce qui fonctionne est l'imbrication du contrôle AxAcroPDF à l'intérieur d'une GroupBox désactivée. Étant donné que les utilisateurs de mon application doivent uniquement voir le PDF, ne pas interagir avec elle, la propriété Enabled de GroupBox est définie sur False dans le concepteur.