2013-07-14 2 views
0

Je suis actuellement en train de coder une application qui doit capturer chaque action effectuée par l'utilisateur sur son handle de fenêtre.Attraper Réduire, Agrandir, Redimensionner, Changer le focus du clavier, etc

je besoin l'événement suivant à lever:

  • fenêtre redimensionnée, maximisée, minimisée ou déplacé
  • utilisateur a changé la fenêtre active
  • utilisateur a changé le clavier de la poignée de fenêtre centrée

Pour ce faire, j'ai essayé beaucoup de solutions, mais en vain. Tout d'abord, j'ai utilisé un minuteur qui sondage toutes les 100ms de la fenêtre de premier plan (en utilisant GetForegroundWindow()) et la poignée axée sur le clavier en utilisant AttachThreadInput() couplé avec la fonction GetFocus().

Mais cette solution n'était pas très pratique et j'ai préféré une solution plus propre utilisant UIAutomation fournie par .NET Framework. Mais je me suis rendu compte qu'il utilisait beaucoup de CPU et qu'il était trop lent pour mon objectif, et l'événement a été appelé parfois 3 ou 4 fois quand je suis passé à une autre poignée de fenêtre. En ce qui concerne le redimensionnement des fenêtres, maximiser, etc. J'ai aussi fait une minuterie (mais pas très véridique), et j'ai essayé de travailler certaines techniques d'accrochage comme le crochet CBT et le crochet Shell. Malheureusement, j'ai trouvé que ce type de hook (hook global) n'est pas supporté par C#.

Je suis à la recherche d'un code stable et fiable pour cette partie de mon programme. Merci d'avance.

+0

[WND_PROC] (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.wndproc.aspx) - Je ne sais pas ce qu'elle est votre utilisant, mais c'est ce que Windows utilise pour gérer à peu près tous les messages – Sayse

+0

Non, je voudrais éviter Winform pour le moment. Je précise que je veux surveiller la poignée d'une autre fenêtre, pas celle de mon application. Concernant WND_PROC: Je suppose que c'est seulement pour l'application elle-même, n'est-ce pas? J'ai cherché le message passant en utilisant AttachThreadInput() à mon application, mais il a besoin d'un objet Form – Louisbob

+0

Oui c'est pour l'application je crois .. (fenêtre) – Sayse

Répondre

0

BrendanMcK répond à merveille à ma question sur ce post:

Setting up Hook on Windows messages

Je copié sa réponse juste au-dessous. Il est plus pratique que Timer comme je l'ai suggéré, et il est moins gourmand en CPU que UIAutomation. Merci tout le monde!

using System; 
using System.Windows; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

class NameChangeTracker 
{ 
    delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, 
     IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime); 

    [DllImport("user32.dll")] 
    static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr 
     hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, 
     uint idThread, uint dwFlags); 

    [DllImport("user32.dll")] 
    static extern bool UnhookWinEvent(IntPtr hWinEventHook); 

    const uint EVENT_OBJECT_NAMECHANGE = 0x800C; 
    const uint WINEVENT_OUTOFCONTEXT = 0; 

    // Need to ensure delegate is not collected while we're using it, 
    // storing it in a class field is simplest way to do this. 
    static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc); 

    public static void Main() 
    { 
     // Listen for name change changes across all processes/threads on current desktop... 
     IntPtr hhook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE, IntPtr.Zero, 
       procDelegate, 0, 0, WINEVENT_OUTOFCONTEXT); 

     // MessageBox provides the necessary mesage loop that SetWinEventHook requires. 
     // In real-world code, use a regular message loop (GetMessage/TranslateMessage/ 
     // DispatchMessage etc or equivalent.) 
     MessageBox.Show("Tracking name changes on HWNDs, close message box to exit."); 

     UnhookWinEvent(hhook); 
    } 

    static void WinEventProc(IntPtr hWinEventHook, uint eventType, 
     IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) 
    { 
     // filter out non-HWND namechanges... (eg. items within a listbox) 
     if(idObject != 0 || idChild != 0) 
     { 
      return; 
     } 
     Console.WriteLine("Text of hwnd changed {0:x8}", hwnd.ToInt32()); 
    } 
} 
Questions connexes