ITriggers _Get(TriggerType e) { int i = (int)e; var t = _t[i]; if (t == null) { switch (e) { case TriggerType.Hotkey: t = new HotkeyTriggers(this); break; case TriggerType.Autotext: t = new AutotextTriggers(this); break; case TriggerType.Mouse: t = new MouseTriggers(this); break; case TriggerType.Window: t = new WindowTriggers(this); break; default: Debug.Assert(false); break; } _t[i] = t; } return(t); }
/// <summary> /// Makes triggers alive. /// </summary> /// <remarks> /// This function monitors hotkeys, activated windows and other events. When an event matches an added trigger, launches the thrigger's action, which runs in other thread by default. /// Does not return immediately. Runs until this process is terminated or <see cref="Stop"/> called. /// </remarks> /// <example>See <see cref="ActionTriggers"/>.</example> /// <exception cref="InvalidOperationException">Already running.</exception> /// <exception cref="AuException">Something failed.</exception> public unsafe void Run() { //ADebug.PrintLoadedAssemblies(true, true, true); ThrowIfRunning_(); //bool haveTriggers = false; HooksThread.UsedEvents hookEvents = 0; _windowTriggers = null; for (int i = 0; i < _t.Length; i++) { var t = _t[i]; if (t == null || !t.HasTriggers) { continue; } //haveTriggers = true; switch ((TriggerType)i) { case TriggerType.Hotkey: hookEvents |= HooksThread.UsedEvents.Keyboard; break; case TriggerType.Autotext: hookEvents |= HooksThread.UsedEvents.Keyboard | HooksThread.UsedEvents.Mouse; break; case TriggerType.Mouse: hookEvents |= (t as MouseTriggers).UsedHookEvents_; break; case TriggerType.Window: _windowTriggers = t as WindowTriggers; break; } } //AOutput.Write(haveTriggers, (uint)llHooks); //if(!haveTriggers) return; //no. The message loop may be used for toolbars etc. if (!s_wasRun) { s_wasRun = true; AWnd.More.RegisterWindowClass(c_cn); } _wMsg = AWnd.More.CreateMessageOnlyWindow(_WndProc, c_cn); _mainThreadId = AThread.NativeId; _winTimerPeriod = 0; _winTimerLastTime = 0; if (hookEvents != 0) { //prevent big delay later on first LL hook event while hook proc waits if (!s_wasKM) { s_wasKM = true; ThreadPool.QueueUserWorkItem(_ => { try { //using var p1 = APerf.Create(); new AWnd.Finder("*a").IsMatch(AWnd.GetWnd.Root); //if used window scopes etc _ = AHookWin.LowLevelHooksTimeout; //slow JIT of registry functions Util.AJit.Compile(typeof(ActionTriggers), nameof(_WndProc), nameof(_KeyMouseEvent)); Util.AJit.Compile(typeof(TriggerHookContext), nameof(TriggerHookContext.InitContext), nameof(TriggerHookContext.PerfEnd), nameof(TriggerHookContext.PerfWarn)); Util.AJit.Compile(typeof(ActionTrigger), nameof(ActionTrigger.MatchScopeWindowAndFunc)); Util.AJit.Compile(typeof(HotkeyTriggers), nameof(HotkeyTriggers.HookProc)); AutotextTriggers.JitCompile(); MouseTriggers.JitCompile(); } catch (Exception ex) { ADebug.Print(ex); } }); } _thc = new TriggerHookContext(this); _ht = new HooksThread(hookEvents, _wMsg); } try { _evStop = Api.CreateEvent(false); _StartStopAll(true); IntPtr h = _evStop; _Wait(&h, 1); } finally { if (hookEvents != 0) { _ht.Dispose(); _ht = null; } Api.DestroyWindow(_wMsg); _wMsg = default; Stopping?.Invoke(this, EventArgs.Empty); _evStop.Dispose(); _StartStopAll(false); _mainThreadId = 0; _threads?.Dispose(); _threads = null; } void _StartStopAll(bool start) { foreach (var t in _t) { if (t?.HasTriggers ?? false) { t.StartStop(start); } } } }