我有一個C#程序,用於輪詢EnumDesktopWindows集合的更改。如果用戶關閉或打開窗口,則輪詢例程會檢測到該窗口,並將可用窗口的更新列表發送給另一個.Net窗體窗體項目。但是,我不喜歡輪詢方法。我更喜歡EnumDesktopWindows的任何更改都會觸發一個事件,以便對異常做出響應。在桌面窗口集合更改時鎖定異步委派?
我能拿出最好的是你在下面看到。我嘗試了Scott C.的建議,從控制檯窗口執行,但沒有奏效。
當您在Windows窗體加載時(這是一個Windows窗體應用程序),您下面看到的內容捕獲CreateWnd = 3。但是它不會全局捕獲:它只捕獲當前正在運行的可執行文件中的窗口事件。如果有人有老鷹的眼睛,並可以發現如何使這個代碼捕獲全球我會獎勵答案。
嘗試一下;首先創建一個Windows窗體應用程序項目,將下面的代碼添加到Form1.cs中(你將需要一個列表框添加到名爲lstLog形式正確編譯)
using System;
using System.Windows.Forms;
namespace Utilities
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var gwh = new GlobalWindowHook();
gwh.WindowCreated += onWindowCreated;
}
private void onWindowCreated()
{
lstLog.Items.Add("window creation event detected.");
}
}
}
名爲GlobalWindowHook同一項目中創建一個類文件.cs並複製粘貼如下:
using System;
using System.Runtime.InteropServices;
namespace Utilities
{
internal class GlobalWindowHook
{
private delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
public enum HookType
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
public enum HCBT
{
MoveSize = 0,
MinMax = 1,
QueueSync = 2,
CreateWnd = 3,
DestroyWnd = 4,
Activate = 5,
ClickSkipped = 6,
KeySkipped = 7,
SysCommand = 8,
SetFocus = 9
}
private IntPtr hhook = IntPtr.Zero;
public GlobalWindowHook()
{
hook();
}
~GlobalWindowHook()
{
unhook();
}
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(HookType.WH_CBT, hookProc, hInstance, 0);
}
public void unhook()
{
UnhookWindowsHookEx(hhook);
}
public IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code != (int) HCBT.CreateWnd && code != (int) HCBT.DestroyWnd)
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
//Do whatever with the created or destroyed window.
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(HookType code, HookProc func, IntPtr hInstance, int threadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hInstance);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary(string fileName);
}
}
執行上述步驟後,執行windows窗體項目。您應該看到它檢測到正在創建的一個窗口,即您剛剛執行的窗口。
定義的類型,我認爲你可以用做'和SetWindowsHookEx()'用'WH_CBT'鉤型。 – cdhowie 2014-09-04 19:07:02
http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx – 2014-09-04 19:08:44
我剛剛修改我的問題,用我迄今爲止的最佳嘗試更新它(謝謝你斯科特)。我仍在尋求答案。 – sapbucket 2014-09-04 23:57:39