public KeyEvent() { scanCode = 0; virtualCode=0; hookMessage=HookMessage.HM_None; extendedKey=false; injectedKey = false; altKeyPressed = false; keyPress = false; sentFromLibrary = false; }
public KeyEvent() { scanCode = 0; virtualCode = 0; hookMessage = HookMessage.HM_None; extendedKey = false; injectedKey = false; altKeyPressed = false; keyPress = false; sentFromLibrary = false; }
public static int hook(int scanCode, int virtualCode, HookMessage message, HookFlags flags, IntPtr param) { KeyEvent keyEvent = new KeyEvent(); keyEvent.scanCode = scanCode; keyEvent.virtualCode = virtualCode; keyEvent.hookMessage = message; int nFlags = (int)flags; if ((nFlags & (int)HookFlags.HF_ExtendedKey) > 0) { keyEvent.extendedKey = true; } if ((nFlags & (int)HookFlags.HF_AltKeyPressed) > 0) { keyEvent.altKeyPressed = true; } if ((nFlags & (int)HookFlags.HF_InjectedKey) > 0) { keyEvent.injectedKey = true; } if ((nFlags & (int)HookFlags.HF_KeyPress) > 0) { keyEvent.keyPress = true; } if ((nFlags & (int)HookFlags.HF_SentFromLibrary) > 0) { keyEvent.sentFromLibrary = true; } form.AddEvent(keyEvent); return(hookReturnValue); }
public static int hook(int scanCode, int virtualCode, HookMessage message, HookFlags flags, IntPtr param) { KeyEvent keyEvent = new KeyEvent(); keyEvent.scanCode = scanCode; keyEvent.virtualCode = virtualCode; keyEvent.hookMessage = message; int nFlags = (int)flags; if ((nFlags & (int)HookFlags.HF_ExtendedKey) > 0) { keyEvent.extendedKey = true; } if ((nFlags & (int)HookFlags.HF_AltKeyPressed) > 0) { keyEvent.altKeyPressed = true; } if ((nFlags & (int)HookFlags.HF_InjectedKey) > 0) { keyEvent.injectedKey = true; } if ((nFlags & (int)HookFlags.HF_KeyPress) > 0) { keyEvent.keyPress = true; } if ((nFlags & (int)HookFlags.HF_SentFromLibrary) > 0) { keyEvent.sentFromLibrary = true; } form.AddEvent(keyEvent); return hookReturnValue; }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Custom window procedure. </summary> /// /// <param name="hWnd"> The window. </param> /// <param name="msg"> The message. </param> /// <param name="wParam"> The parameter. </param> /// <param name="lParam"> The parameter. </param> /// /// <returns> An IntPtr. </returns> //////////////////////////////////////////////////////////////////////////////////////////////////// private IntPtr CustomWndProc(IntPtr hWnd, HookMsgType msg, IntPtr wParam, IntPtr lParam) { var m = new HookMessage(hWnd, msg, wParam, lParam); //Deactivated means there are zero callbacks and destroyed means that the WM_DESTROY message // has already been processed and there is no need to call our custom logic. I think there // are a few messages that can still come in after WM_DESTROY, such as WM_NCDESTROY that is // sent after all child Windows have been destroyed. Note that we try to unhook our custom // logic upon a WM_DESTROY by replacing it with the original WndProc but race conditions // could affect that timing. if (_isDeActivated || _isDestroyed) { return(CallWindowProc(_originalWndProc, m.HWnd, (uint)m.HookMsgType, m.WParam, m.LParam)); } //Grab a copy of the callbacks so we do not remain inside the lock while we are looping through // and calling back into unknown code that could (but hopefully not) be lengthy. In rare race // conditions this could cause a slight delay in the amount of time it takes to "UnRegister" // a callback if code desired to do so. // // TODO Window Procedure Performance Evaluation // Note that the performance of this design should be considered carefully. Although it makes // it flexible to be able to add callbacks to a Window throughout the application, the fact // that I am locking inside of a hot function is cause for careful thought. Atop of locking, // I am copying the current callbacks into another local variable. Since Window procedures // can cause recursion by design, that could lead to a stack overflow if the Size of // the RegisteredWndProcCallbacks grew. If an application only intended to attach one // callback at any given time, this could be simplified greatly. WndProcCallback[]? callbacksCopy = null; lock (_callbacksLocker) { callbacksCopy = RegisteredWndProcCallbacks.ToArray(); } if (callbacksCopy != null) { //Loop through all callbacks until one callback handles the message or we exhaust all // items in the loop. If a callback handles the message we can return the result so // long as it is not a DESTROY message, then we need to unhook. foreach (var callback in callbacksCopy) { if (!callback(ref m)) { continue; } if (msg != HookMsgType.DESTROY) { return(m.Result); } break; } } //This one makes me nervous, keep an eye on it. Of the many examples I happened upon, they // were re-hooking the WndProc with the original loop and for that reason I will do the // same. If you are seeing exceptions, this could be a race condition of some sort. if (msg == HookMsgType.DESTROY) { Destroy(); } //Note that this is still called after we call Destroy to unhook this routine because // it needs to receive the DESTROY message or else the window will not close. Also // notice that we are sending the values inside of the local HookMessage rather than // the ones that came into this CustomWndProc. This lets other callbacks change the // parameter values if needed. return(CallWindowProc(_originalWndProc, m.HWnd, (uint)m.HookMsgType, m.WParam, m.LParam)); }