2010-12-06 8 views
25

olmadan C# kullanarak değiştirdi. CBTProc kullanarak nasıl yapıldığını gördüm. Ancak, global etkinliklerin yönetilen kodla bağlanması kolay değildir. Yoklama gerektirmeyen bir yol bulmakla ilgileniyorum. Olay odaklı bir yaklaşımı tercih ederim.İnsan nasıl ne zaman geçerli etkin pencere değişiklikleri geri arama çağırabilir yoklama

Selamlar

+0

"Değişiklikler" tanımlayabilir misiniz? – Eric

+2

http://support.microsoft.com/kb/318804 göre, .NET küresel kanca yapamaz ve küresel kanca Eğer bu gibi olayların nasıl izlediğimizi olduğundan, bu sadece diğer seçenekleri yoklama vardır benziyor veya C# 'dan erişebileceğiniz bir arabirim sağlayan bazı yönetilmeyen kodlar (örneğin C++) yazabilirsiniz. –

+0

Jim Bence doğru cevaba sahipsiniz. – Joe

cevap

47

Yeni bir pencere formları projesi oluşturun, bir metin kutusu ekleyin, çok satırlı hale getirin ve metin kutusunu Dock özelliğini doldurmak için doldurun, adlandırın ve aşağıdaki kodu yapıştırın (System.Runtime.InteropServices dosyasını eklemeniz gerekir)

WinEventDelegate dele = null; 

    public Form1() 
    { 
     InitializeComponent(); 
     dele = new WinEventDelegate(WinEventProc); 
     IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT); 
    } 

    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); 

    private const uint WINEVENT_OUTOFCONTEXT = 0; 
    private const uint EVENT_SYSTEM_FOREGROUND = 3; 

    [DllImport("user32.dll")] 
    static extern IntPtr GetForegroundWindow(); 

    [DllImport("user32.dll")] 
    static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); 

    private string GetActiveWindowTitle() 
    { 
     const int nChars = 256; 
     IntPtr handle = IntPtr.Zero; 
     StringBuilder Buff = new StringBuilder(nChars); 
     handle = GetForegroundWindow(); 

     if (GetWindowText(handle, Buff, nChars) > 0) 
     { 
      return Buff.ToString(); 
     } 
     return null; 
    } 

    public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) 
    { 
     Log.Text += GetActiveWindowTitle() + "\r\n"; 
    } 
+3

, 'kapsamı dele' olması gerekir Temsilcinin yok edilmesini önlemek için genişletildi. Daha fazla bilgi için [belgeler sayfası] hakkındaki yorumlara bakın (http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640 (v = vs.85) .aspx). –

+0

Bu bir konsol uygulamasıyla çalışmıyor gibi görünüyor, kimse nedenini biliyor mu? InitializeComponent() öğesini kaldırdım. –

+1

@AnthonyRaimondo Görünüşe göre bir Console.ReadLine etkinse 'ateşlemiyor'. Birlikte çalışma aramaları azaltmak ve kodunu biraz temizlemek için http://stackoverflow.com/questions/8840926/asynchronously-getforegroundwindow-via-sendmessage-or-something/11943387#11943387 –

7

Sen SetWinEventHook kullanabilir ve EVENT_SYSTEM_FOREGROUND etkinliğini dinleyebiliriz. Genel kanca sorununu önlemek için WINEVENT_OUTOFCONTEXT bayrağını kullanın.

+0

Bazı örnekler verebilir misiniz, lütfen. –

+4

[Sen stackoverflow arama yapabilirsiniz] (http://stackoverflow.com/questions/4407631/is-there-windows-system-event-on-active-window-changed). –

+1

Ek bilgi: Bağlam dışı işleviniz hızlı olmalıdır. (Https://msdn.microsoft.com/en-us/library/windows/desktop/dd373611%28v=vs.85%29.aspx) Savvas Sopiadis' yanıt uyarınca –

16

senin usings) ... Bu iş parçacığı eski olduğunu biliyorum ama ileride kullanmak uğruna: kodunu çalıştırırken bir süre sonra bir kilitlenme göreceksiniz. Bu Form kurucusuna satırından kaynaklanır:

yerine yukarıda aşağıdaki değişikliği yapın ait
public Form1() 
    { 
     InitializeComponent(); 
     WinEventDelegate dele = new WinEventDelegate(WinEventProc);//<-causing ERROR 
     IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT); 
    } 

: şimdi beklendiği gibi

public Form1() 
     { 
      InitializeComponent(); 
      dele = new WinEventDelegate(WinEventProc); 
      IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT); 
     } 
WinEventDelegate dele = null; 

..works!

İlgili konular