我正在使用第一個代碼塊在單獨的線程上執行低級別的鼠標掛鉤。它實際上是這樣工作的(不管你信不信),因爲訂閱行爲會初始化鉤子。並且,我需要能夠阻止調用事件的方法,以便我可以設置一個值來改變其執行過程。這就是爲什麼我不能簡單地將事件處理程序卸載到另一個線程的原因。這是否正確使用DoEvents? - 包含示例項目
我的問題是,即使這有效,是否有另一種方法可以避免DoEvents
?
是否有可能DoEvents
僅適用於其自己的線程上的事件,或者這個調用是否會影響我的GUI線程?據我所知,它似乎沒有影響我的GUI。
注意:如果不調用Sleep
,CPU將顯着增加。
注意:沒有DoEvents
掛鉤消息建立並強制操作系統斷開掛鉤。
編輯:我創建了一個示例項目,讓你們可以測試這個。該應用程序將在單獨的線程上啓動鼠標鉤,並捕獲鼠標右鍵單擊,並通過消息框讓您知道它是否已經這樣做。您可以使用下面的鏈接獲取該項目。
該示例顯示您可以阻止GUI線程並仍然處理掛鉤而不會確認掛鉤位於其自己的線程上。
https://github.com/mzomparelli/Threaded-Low-Level-Mouse-Hook-Example
我現在開始覺得,這是一個有效的使用DoEvents
儘管許多聲稱DoEvents
是總是壞。
private static bool blnStopMouseHook = false;
public static void StartMouseHook()
{
if (MouseHook == null)
{
blnStopMouseHook = false;
MouseHook = new Thread(new ThreadStart(() => { MouseHookThread(); }));
MouseHook.SetApartmentState(ApartmentState.STA);
MouseHook.Start();
}
}
public static void StopMouseHook()
{
blnStopMouseHook = true;
MouseHook.Join();
MouseHook = null;
}
private static void MouseHookThread()
{
HookManager.MouseWheel += HookHandlers.HookManagerOnMouseWheel;
HookManager.MouseClickExt += HookHandlers.HookManagerOnMouseClickExt;
do
{
System.Threading.Thread.Sleep(1);
Application.DoEvents();
} while (blnStopMouseHook == false);
HookManager.MouseWheel -= HookHandlers.HookManagerOnMouseWheel;
HookManager.MouseClickExt -= HookHandlers.HookManagerOnMouseClickExt;
}
下面是我的HOOKPROC的片段,其創建事件HookManagerOnMouseWheel
private static int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
//Marshall the data from callback.
MouseLLHookStruct mouseHookStruct = (MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseLLHookStruct));
switch (wParam)
{
case WM_MOUSEWHEEL:
mouseDelta = (short)((mouseHookStruct.MouseData >> 16) & 0xffff);
break;
}
//generate event
MouseEventExtArgs e = new MouseEventExtArgs(
button,
clickCount,
mouseHookStruct.Point.X,
mouseHookStruct.Point.Y,
mouseDelta);
//Wheel was moved
if (s_MouseWheel!=null && mouseDelta!=0)
{
s_MouseWheel.Invoke(null, e);
}
//If someone listens to move and there was a change in coordinates raise move event
if (e.Handled)
{
return -1;
}
}
//call next hook
return CallNextHookEx(s_MouseHookHandle, nCode, wParam, lParam);
}
這是我的事件處理程序。
public static void HookManagerOnMouseWheel(object sender, MouseEventExtArgs mouseEventArgs)
{
int iHotkey;
int iHotkey2;
string keyCombination = CurrentModifiers();
string keyCombination2 = CurrentModifiers();
if (Window.Taskbar().IsMouseOver() || Window.Taskbar2().IsMouseOver())
{
//Create combination string
if (mouseEventArgs.Delta < 0)
{
keyCombination = keyCombination + "+MOUSE-TASKBAR-SCROLL-DOWN";
keyCombination2 = keyCombination2 + "+MOUSE-ANYWHERE-SCROLL-DOWN";
}
else
{
keyCombination = keyCombination + "+MOUSE-TASKBAR-SCROLL-UP";
keyCombination2 = keyCombination2 + "+MOUSE-ANYWHERE-SCROLL-UP";
}
iHotkey = GLOBALS.hotkeys.FindIndex(l => l.HotkeyString() == keyCombination);
iHotkey2 = GLOBALS.hotkeys.FindIndex(l => l.HotkeyString() == keyCombination2);
if (iHotkey >= 0)
{
ExecuteAction(iHotkey);
mouseEventArgs.Handled = true;
return;
}
else if (iHotkey2 >= 0)
{
ExecuteAction(iHotkey2);
mouseEventArgs.Handled = true;
return;
}
}
if (mouseEventArgs.Delta < 0)
{
keyCombination = keyCombination + "+MOUSE-ANYWHERE-SCROLL-DOWN";
}
else
{
keyCombination = keyCombination + "+MOUSE-ANYWHERE-SCROLL-UP";
}
iHotkey = GLOBALS.hotkeys.FindIndex(l => l.HotkeyString() == keyCombination);
if (iHotkey >= 0)
{
ExecuteAction(iHotkey);
mouseEventArgs.Handled = true;
return;
}
}
爲什麼在循環內睡眠? –
因爲沒有它,DoEvents執行得太多,需要休息或重要CPU會增加。這是我關心的領域。 –
請永遠不要使用Application.DoEvents()。它只是在與VB6向後兼容的框架中。它最終會導致更多的錯誤,而不是解決問題。 – Enigmativity