示例#1
0
        void _Thread()
        {
            _tid = AThread.NativeId;

            AHookWin hookK = null, hookM = null;

            if (_usedEvents.Has(UsedEvents.Keyboard))
            {
                hookK = AHookWin.Keyboard(_KeyboardHookProc);                 //note: don't use lambda, because then very slow JIT on first hook event
            }
            if (_usedEvents.Has(UsedEvents.Mouse))
            {
                hookM = AHookWin.MouseRaw_(_MouseHookProc);
            }
            if (_usedEvents.Has(UsedEvents.MouseEdgeMove))
            {
                _emDetector = new MouseTriggers.EdgeMoveDetector_();
            }
            //tested: don't need JIT-compiling.

            Api.SetEvent(_eventStartStop);

            while (Api.GetMessage(out var m) > 0)
            {
                Api.DispatchMessage(m);
            }

            //AOutput.Write("hooks thread ended");
            hookK?.Dispose();
            hookM?.Dispose();
            _emDetector = null;
            Api.SetEvent(_eventStartStop);
        }
示例#2
0
            /// <summary>
            /// Creates native/unmanaged window of a class registered with <see cref="RegisterWindowClass"/> with null <i>wndProc</i>, and sets its window procedure.
            /// </summary>
            /// <exception cref="ArgumentException">The class is not registered with <see cref="RegisterWindowClass"/>, or registered with non-null <i>wndProc</i>.</exception>
            /// <exception cref="AuException">Failed to create window. Unlikely.</exception>
            /// <remarks>
            /// Calls API <msdn>CreateWindowEx</msdn>.
            /// Protects the <i>wndProc</i> delegate from GC.
            /// Later call <see cref="DestroyWindow"/> or <see cref="Close"/>.
            /// </remarks>
            public static AWnd CreateWindow(Native.WNDPROC wndProc, string className, string name = null, WS style = 0, WS2 exStyle = 0, int x = 0, int y = 0, int width = 0, int height = 0, AWnd parent = default, LPARAM controlId = default, IntPtr hInstance = default, LPARAM param = default)
            {
                var a = t_windows ??= new List <(AWnd w, Native.WNDPROC p)>();

                for (int i = a.Count; --i >= 0;)
                {
                    if (!a[i].w.IsAlive)
                    {
                        a.RemoveAt(i);
                    }
                }

                lock (s_classes) {
                    if (!s_classes.TryGetValue(className, out var wp) || wp != null)
                    {
                        throw new ArgumentException("Window class must be registered with RegisterWindowClass with null wndProc");
                    }
                }

                AWnd w;

                //need to cubclass the new window. But not after CreateWindowEx, because wndProc must receive all messages.
#if CW_CBT                                       //slightly slower and dirtier. Invented before Core, to support multiple appdomains.
                using (AHookWin.ThreadCbt(c => { //let CBT hook subclass before any messages
                    if (c.code == HookData.CbtEvent.CREATEWND)
                    {
                        //note: unhook as soon as possible. Else possible exception etc.
                        //	If eg hook proc uses 'lock' and that 'lock' must wait,
                        //		our hook proc is called again and again while waiting, until 'lock' throws exception.
                        //	In STA thread 'lock' dispatches messages, but I don't know why hook proc is called multiple times for same event.
                        c.hook.Unhook();

                        var ww = (AWnd)c.wParam;
                        Debug.Assert(ww.ClassNameIs(className));
                        ww.SetWindowLong(Native.GWL.WNDPROC, Marshal.GetFunctionPointerForDelegate(wndProc));
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                    return(false);
                })) {
                    w = Api.CreateWindowEx(exStyle, className, name, style, x, y, width, height, parent, controlId, hInstance, param);
                }
#else
                t_cwProc = wndProc;                 //let _DefWndProc subclass on first message
                try { w = Api.CreateWindowEx(exStyle, className, name, style, x, y, width, height, parent, controlId, hInstance, param); }
                finally { t_cwProc = null; }        //if CreateWindowEx failed and _CWProc not called
#endif

                if (w.Is0)
                {
                    throw new AuException(0);
                }
                a.Add((w, wndProc));
                return(w);
            }
示例#3
0
        protected override unsafe void WndProc(ref Message m)
        {
            //AWnd.More.PrintMsg(m, Api.WM_SETCURSOR, Api.WM_NCHITTEST, Api.WM_NCMOUSEMOVE);
            switch (m.Msg)
            {
            case Api.WM_MOUSEACTIVATE:
                switch (AMath.HiShort(m.LParam))
                {
                case Api.WM_MBUTTONDOWN:
                    Hide();                     //never mind: we probably don't receive this message if our thread is inactive
                    m.Result = (IntPtr)Api.MA_NOACTIVATEANDEAT;
                    break;

                default:
                    m.Result = (IntPtr)Api.MA_NOACTIVATE;
                    break;
                }
                return;

            case Api.WM_NCLBUTTONDOWN:
                var wa = AWnd.ThisThread.Active;
                if (wa != default && wa.Handle != m.HWnd)
                {
                    var h = m.HWnd;
                    using (AHookWin.ThreadCbt(d => d.code == HookData.CbtEvent.ACTIVATE && d.ActivationInfo(out _, out _).Handle == h))
                        base.WndProc(ref m);
                    return;
                }
                break;
            }
            //Somehow OS ignores WS_EX_NOACTIVATE if the active window is of this thread. Workaround: on WM_MOUSEACTIVATE return MA_NOACTIVATE.
            //Also then activates when clicked in non-client area, eg when moving or resizing. Workaround: on WM_NCLBUTTONDOWN suppress activation with a CBT hook.
            //When moving or resizing, WM_NCLBUTTONDOWN returns when moving/resizing ends. On resizing would activate on mouse button up.

            base.WndProc(ref m);

            switch (m.Msg)
            {
            case Api.WM_SHOWWINDOW:
                if (m.WParam == default)
                {
                    ZHiddenOrDestroyed?.Invoke(false);
                }
                break;

            case Api.WM_DESTROY:
                ZHiddenOrDestroyed?.Invoke(true);
                break;
            }
        }
示例#4
0
文件: Program.cs 项目: alexfordc/Au
 static void _Hook()
 {
     s_hook = AHookWin.ThreadCbt(m => {
         //AOutput.Write(m.code, m.wParam, m.lParam);
         //switch(m.code) {
         //case HookData.CbtEvent.ACTIVATE:
         //case HookData.CbtEvent.SETFOCUS:
         //	AOutput.Write((AWnd)m.wParam);
         //	AOutput.Write(AWnd.Active);
         //	AOutput.Write(AWnd.ThisThread.Active);
         //	AOutput.Write(AWnd.Focused);
         //	AOutput.Write(AWnd.ThisThread.Focused);
         //	break;
         //}
         if (m.code == HookData.CbtEvent.ACTIVATE)
         {
             var w = (AWnd)m.wParam;
             if (!w.HasExStyle(WS2.NOACTIVATE))
             {
                 //AOutput.Write(w);
                 //AOutput.Write(w.ExStyle);
                 //Api.SetForegroundWindow(w); //does not work
                 ATimer.After(1, _ => {
                     if (s_hook == null)
                     {
                         return;
                     }
                     //AOutput.Write(AWnd.Active);
                     //AOutput.Write(AWnd.ThisThread.Active);
                     bool isActive = w == AWnd.Active, activate = !isActive && w == AWnd.ThisThread.Active;
                     if (isActive || activate)
                     {
                         s_hook.Dispose(); s_hook = null;
                     }
                     if (activate)
                     {
                         Api.SetForegroundWindow(w);
                         //w.ActivateLL(); //no, it's against Windows rules, and works differently with meta outputPath
                         //Before starting task, editor calls AllowSetForegroundWindow. But if clicked etc a window after that:
                         //	SetForegroundWindow fails always or randomly;
                         //	Activate[LL] fails if that window is of higher UAC IL, unless the foreground lock timeout is 0.
                     }
                 });
             }
         }
         return(false);
     });
 }
示例#5
0
        void _ThreadProc()
        {
            AHookWin hk = null, hm = null; AHookAcc hwe = null;

            try {
                try {
                    if (_block.Has(BIEvents.Keys))
                    {
                        hk = AHookWin.Keyboard(_keyHookProc ??= _KeyHookProc);
                    }
                    if (_block.HasAny(BIEvents.MouseClicks | BIEvents.MouseMoving))
                    {
                        hm = AHookWin.Mouse(_mouseHookProc ??= _MouseHookProc);
                    }
                }
                catch (AuException e1) { ADebug.Print(e1); _block = 0; return; }                //failed to hook

                //This prevents occassional inserting a foreign key after the first our-script-pressed key.
                //To reproduce, let our script send small series of chars in loop, and simultaneously a foreign script send other chars.
                ATime.DoEvents();

                //AOutput.Write("started");
                Api.SetEvent(_syncEvent);

                //the acc hook detects Ctrl+Alt+Del, Win+L, UAC consent, etc. SystemEvents.SessionSwitch only Win+L.
                try { hwe = new AHookAcc(AccEVENT.SYSTEM_DESKTOPSWITCH, 0, _winEventProc ??= _WinEventProc); }
                catch (AuException e1) { ADebug.Print(e1); }                //failed to hook

                AWaitFor.Wait_(-1, WHFlags.DoEvents, _stopEvent, _threadHandle);

                if (_blockedKeys != null)
                {
                    bool onlyUp = _discardBlockedKeys || ATime.WinMilliseconds - _startTime > c_maxResendTime;
                    _blockedKeys.SendBlocked_(onlyUp);
                }
                //AOutput.Write("ended");
            }
            finally {
                _blockedKeys = null;
                hk?.Dispose();
                hm?.Dispose();
                hwe?.Dispose();
                Api.SetEvent(_syncEvent);
            }
            GC.KeepAlive(this);
        }
示例#6
0
文件: t-mouse.cs 项目: alexfordc/Au
 void _SetTempKeybHook()
 {
     //AOutput.Write(". hook");
     if (_keyHook == null)
     {
         _keyHook = AHookWin.Keyboard(k => {
             if (ATime.WinMilliseconds >= _keyHookTimeout)
             {
                 _ResetUpAndUnhookTempKeybHook();
                 ADebug.Print("hook timeout");
             }
             else
             {
                 var mod = k.Mod;
                 if (0 != (mod & _upMod) && k.IsUp)
                 {
                     _upMod &= ~mod;
                     if (_upMod == 0 && _upEvent == 0 && _upTrigger != null)
                     {
                         _triggers.RunAction_(_upTrigger, _upArgs);
                         _ResetUp();
                     }
                 }
                 if (0 != (mod & _eatMod))
                 {
                     //AOutput.Write(k);
                     k.BlockEvent();
                     if (k.IsUp)
                     {
                         _eatMod &= ~mod;
                     }
                 }
                 if (0 == (_upMod | _eatMod))
                 {
                     _UnhookTempKeybHook();
                 }
             }
         }, setNow: false);
     }
     if (!_keyHook.IsSet)
     {
         _keyHook.Hook();
     }
     _keyHookTimeout = _keyHook.IgnoreModInOtherHooks_(5000);
 }
示例#7
0
            /// <summary>
            /// Releases modifier keys if pressed and no option NoModOff. Turns off CapsLock if toggled and no option NoCapsOff.
            /// When releasing modifiers, if pressed Alt or Win without Ctrl, presses-releases Ctrl to avoid menu mode.
            /// Returns true if turned off CapsLock.
            /// Does not sleep, blockinput, etc.
            /// </summary>
            internal static bool ReleaseModAndCapsLock(OptKey opt)
            {
                //note: don't call Hook here, it does not make sense.

                bool R = !opt.NoCapsOff && IsCapsLock;

                if (R)
                {
                    if (IsPressed(KKey.CapsLock))
                    {
                        SendKey(KKey.CapsLock, 2);                                              //never mind: in this case later may not restore CapsLock because of auto-repeat
                    }
                    SendKey(KKey.CapsLock);
                    if (IsCapsLock)
                    {
                        //Probably Shift is set to turn off CapsLock in CP dialog "Text Services and Input Languages".
                        //	Win10: Settings -> Time & Language -> Language -> Input method -> Hot keys.
                        AHookWin.IgnoreLShiftCaps_(2000);
                        SendKey(KKey.Shift);
                        AHookWin.IgnoreLShiftCaps_(0);
                        R = !IsCapsLock;
                        Debug.Assert(R);

                        //note: need IgnoreLShiftCaps_, because when we send Shift, the BlockInput hook receives these events:
                        //Left Shift down, not injected //!!
                        //Caps Lock down, not injected
                        //Caps Lock up, not injected
                        //Left Shift up, injected

                        //speed: often ~15 ms. Without Shift max 5 ms.

                        //never mind: don't need to turn off CapsLock if there is only text, unless Options.TextOption == KTextOption.Keys.
                    }
                }
                if (!opt.NoModOff)
                {
                    ReleaseModAndDisableModMenu();
                }
                return(R);
            }
示例#8
0
            protected override unsafe void WndProc(ref Message m)
            {
                //if(_tb.Name=="ddd") AWnd.More.PrintMsg(m, new PrintMsgOptions(Api.WM_GETTEXT, Api.WM_GETTEXTLENGTH, Api.WM_NCHITTEST, Api.WM_SETCURSOR, Api.WM_NCMOUSEMOVE, Api.WM_MOUSEMOVE));
                //AWnd.More.PrintMsg(m, new PrintMsgOptions(Api.WM_GETTEXT, Api.WM_GETTEXTLENGTH));

                switch (m.Msg)
                {
                case Api.WM_CREATE:
                    _WmCreate();
                    break;

                case Api.WM_DESTROY:
                    _WmDestroy();
                    break;

                case Api.WM_NCPAINT:
                    if (_WmNcpaint((AWnd)m.HWnd))
                    {
                        return;                                              //draws border if need
                    }
                    break;

                case Api.WM_NCHITTEST:
                    if (_WmNchittest(ref m))
                    {
                        return;                                         //returns a hittest code to move or resize if need
                    }
                    break;

                case Api.WM_NCLBUTTONDOWN:
                    //workaround for: Windows tries to activate this window when moving or sizing it, unless this process is not allowed to activate windows.
                    //	Usually this window would not become the foreground window, but it receives wm_activateapp, wm_activate, wm_setfocus, and is moved to the top of Z order.
                    //	tested: LockSetForegroundWindow does not work.
                    //	This code better would be under WM_SYSCOMMAND, but then works only when sizing. When moving, activates before WM_SYSCOMMAND.
                    int ht = (int)m.WParam;
                    if (ht == Api.HTCAPTION || (ht >= Api.HTSIZEFIRST && ht <= Api.HTSIZELAST))
                    {
                        using (AHookWin.ThreadCbt(d => d.code == HookData.CbtEvent.ACTIVATE))
                            base.WndProc(ref m);
                        return;
                    }
                    break;

                case Api.WM_ENTERSIZEMOVE:
                    _tb._InMoveSize(true);
                    break;

                case Api.WM_EXITSIZEMOVE:
                    _tb._InMoveSize(false);
                    break;

                case Api.WM_LBUTTONDOWN:
                case Api.WM_RBUTTONDOWN:
                case Api.WM_MBUTTONDOWN:
                    var tb1 = _tb._SatPlanetOrThis;
                    if (tb1.IsOwned && !tb1.MiscFlags.Has(TBFlags.DontActivateOwner))
                    {
                        tb1.OwnerWindow.ActivateLL();
                        //never mind: sometimes flickers. Here tb1._Zorder() does not help. The OBJECT_REORDER hook zorders when need. This feature is rarely used.
                    }
                    break;

                case Api.WM_MOUSEMOVE:
                case Api.WM_NCMOUSEMOVE:
                    _tb._SatMouse();
                    break;

                case Api.WM_WINDOWPOSCHANGING:
                    _tb._OnWindowPosChanging(ref *(Api.WINDOWPOS *)m.LParam);
                    break;
                }

                base.WndProc(ref m);

                switch (m.Msg)
                {
                case Api.WM_WINDOWPOSCHANGED:
                    _tb._OnWindowPosChanged(in * (Api.WINDOWPOS *)m.LParam);
                    break;

                case Api.WM_DISPLAYCHANGE:
                    _tb._OnDisplayChanged();
                    break;

                case Api.WM_PAINT:
                    _paintedOnce = true;
                    //APerf.NW();
                    break;

                case Api.WM_RBUTTONUP:
                case Api.WM_NCRBUTTONUP:
                    _ContextMenu(this);
                    break;
                }
            }