예제 #1
0
    /// <summary>
    /// Used only by the Save class.
    /// </summary>
    bool _SaveStateNow()
    {
        if (DB == null)
        {
            return(true);
        }
        try {
            using (var trans = DB.Transaction()) {
                DB.Execute("REPLACE INTO _misc VALUES ('expanded',?)",
                           string.Join(" ", Root.Descendants().Where(n => n.IsExpanded).Select(n => n.IdString)));

                using (new StringBuilder_(out var b)) {
                    var a = OpenFiles;
                    b.Append(a.IndexOf(_currentFile));
                    foreach (var v in a)
                    {
                        b.Append(' ').Append(v.IdString);                                      //FUTURE: also save current position and scroll position, eg "id.pos.scroll"
                    }
                    DB.Execute("REPLACE INTO _misc VALUES ('open',?)", b.ToString());
                }

                trans.Commit();
            }
            return(true);
        }
        catch (SLException ex) {
            Debug_.Print(ex);
            return(false);
        }
    }
예제 #2
0
        /// <summary>
        /// If possible, gets whether the window is DPI-scaled/virtualized, and gets physical and logical rects if scaled.
        /// Returns false if !osVersion.minWin10_1607 or if cannot get that info.
        /// Gets that info in a fast and reliable way.
        /// </summary>
        internal static bool GetScalingInfo_(wnd w, out bool scaled, out RECT rPhysical, out RECT rLogical)
        {
            scaled = false; rPhysical = default; rLogical = default;
            if (!osVersion.minWin10_1607)
            {
                return(false);
            }
            var awareness = WindowDpiAwareness(w);                                     //fast on Win10

            if (awareness is Awareness.System or Awareness.Unaware)                    //tested: unaware-gdi-scaled same as unaware
            {
                if (awareness == Awareness.System && Api.GetDpiForWindow(w) != System) /*fast*/
                //Cannot get rLogical. It's rare and temporary, ie when the user recently changed DPI of the primary screen.
                //Even if this func isn't used to get rects, without this fast code could be unreliable.
                {
                    Debug_.Print("w System DPI != our System DPI");
                    return(false);
                }
                for (; ;)
                {
                    RECT r1 = w.Rect, r2, r3;                     //note: with ClientRect 4 times faster, but unreliable if small rect. Now fast enough.
                    bool rectWorkaround = false;
                    using (var u = new AwarenessContext(awareness == Awareness.System ? -2 : -1)) {
                        if (Api.GetAwarenessFromDpiAwarenessContext(u.Previous_) != Awareness.PerMonitor)                           /*fast*/
                        //cannot get rPhysical. But let's set PM awareness and get it. Works even if this process is Unaware.
                        {
                            rectWorkaround = _GetRect(w, out r1);
                            Debug_.Print("bad DPI awareness of this thread; workaround " + (rectWorkaround ? "OK" : "failed"));
                            if (!rectWorkaround)
                            {
                                return(false);                                             //unlikely. Then the caller probably will call the legacy func, it works with any DPI awareness.
                            }
                        }
                        r2 = w.Rect;
                        if (r2 == r1)
                        {
                            break;
                        }
                    }
                    if (!rectWorkaround)
                    {
                        r3 = w.Rect;
                    }
                    else
                    {
                        _GetRect(w, out r3);
                    }
                    if (r3 != r1)
                    {
                        continue;                               //moved, resized or closed between Rect and Rect
                    }
                    scaled    = true;
                    rPhysical = r1;
                    rLogical  = r2;
                    break;
                }
예제 #3
0
파일: DWinapi.cs 프로젝트: qmgindi/Au
    void _TextChanged()
    {
        string name = tName.Text;
        var    a    = new List <(string name, string code)>();

        int nWild = 0; for (int i = 0; i < name.Length; i++)

        {
            switch (name[i])
            {
            case '*':
            case '?': nWild++; break;
            }
        }

        if (name.Length > 0 && (nWild == 0 || name.Length - nWild >= 2))
        {
            string sql;
            if (name.Contains(' '))
            {
                sql = $"in ('{string.Join("', '", name.RxFindAll(@"\b[A-Za-z_]\w\w+", (RXFlags)0))}')";
            }
            else if (name.FindAny("*?") >= 0)
            {
                sql = $"GLOB '{name}'";
            }
            else
            {
                sql = $"= '{name}'";
            }
            try {
                using var stat = _db.Statement("SELECT name, code FROM api WHERE name " + sql);
                //perf.first();
                while (stat.Step())
                {
                    a.Add((stat.GetText(0), stat.GetText(1)));
                }
                //perf.nw(); //30 ms cold, 10 ms warm. Without index.
            }
            catch (SLException ex) { Debug_.Print(ex.Message); }
        }

        string s = "";

        if (a.Count != 0)
        {
            s = a[0].code;
            if (a.Count > 1)
            {
                s = string.Join(s.Starts("internal const") ? "\r\n" : "\r\n\r\n", a.Select(o => o.code));
            }
            s += "\r\n";
        }
        code.ZSetText(s);
    }
예제 #4
0
 public _NetDocumentationProvider()
 {
     try {
         _db = EdDatabases.OpenDoc();                     //never mind: we don't dispose it on process exit
         if (_db.Get(out string s, "SELECT xml FROM doc WHERE name='.'"))
         {
             _refs = new HashSet <string>(s.Split('\n'));
         }
     }
     catch (SLException ex) { Debug_.Print(ex.Message); }
 }
예제 #5
0
        void _ThreadProc()
        {
            WindowsHook hk = null, hm = null; WinEventHook hwe = null;

            try {
                try {
                    if (_block.Has(BIEvents.Keys))
                    {
                        hk = WindowsHook.Keyboard(_keyHookProc ??= _KeyHookProc);
                    }
                    if (_block.HasAny(BIEvents.MouseClicks | BIEvents.MouseMoving))
                    {
                        hm = WindowsHook.Mouse(_mouseHookProc ??= _MouseHookProc);
                    }
                }
                catch (AuException e1) { Debug_.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.
                wait.doEvents();

                //print.it("started");
                Api.SetEvent(_syncEvent);

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

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

                if (_blockedKeys != null)
                {
                    bool onlyUp = _discardBlockedKeys || Environment.TickCount64 - _startTime > c_maxResendTime;
                    _blockedKeys.SendBlocked_(onlyUp);
                }
                //print.it("ended");
            }
            finally {
                _blockedKeys = null;
                hk?.Dispose();
                hm?.Dispose();
                hwe?.Dispose();
                Api.SetEvent(_syncEvent);
            }
            GC.KeepAlive(this);
        }
예제 #6
0
파일: Triggers.cs 프로젝트: qmgindi/Au
        nint _WndProc(wnd w, int message, nint wParam, nint lParam)
        {
            try {
                switch (message)
                {
                case Api.WM_USER + 1:
                    //_ht.Return((int)wParam, false); //test speed without _KeyMouseEvent
                    _KeyMouseEvent((int)wParam, (HooksThread.UsedEvents)lParam);
                    return(0);

                case Api.WM_USER + 20:
                    _windowTriggers.SimulateNew_(wParam, lParam);
                    return(0);

                case Api.WM_USER + 30:
                    _ShowToolbarsDialog();
                    return(0);
                }
            }
            catch (Exception ex) { Debug_.Print(ex.Message); return(default); }
예제 #7
0
파일: wnd_child.cs 프로젝트: qmgindi/Au
 /// <summary>
 /// Gets check state of this check box or radio button.
 /// Returns 0 if unchecked, 1 if checked, 2 if indeterminate. Also returns 0 if this is not a button or if failed to get state.
 /// </summary>
 /// <param name="useElm">Use <see cref="elm.State"/>. If false (default) and this button has a standard checkbox style, uses API <msdn>BM_GETCHECK</msdn>.</param>
 public int GetCheckState(bool useElm = false)
 {
     if (useElm || !_IsCheckbox())
     {
         //info: Windows Forms controls are user-drawn and don't have one of the styles, therefore BM_GETCHECK does not work.
         try {                 //avoid exception in property-get functions
             using var e = elm.fromWindow(W, EObjid.CLIENT, flags: EWFlags.NoThrow);
             if (e == null)
             {
                 return(0);
             }
             return(_GetElmCheckState(e));
         }
         catch (Exception ex) { Debug_.Print(ex); }                 //CONSIDER: if fails, show warning. In all wnd property-get functions.
         return(0);
     }
     else
     {
         return((int)W.Send(BM_GETCHECK));
     }
 }
예제 #8
0
            /// <summary>
            /// Gets indices of owned windows of the specified window, including all descendants.
            /// Can be called multiple times for different owner windows; uses arrays created in ctor (the slowest part).
            /// </summary>
            /// <param name="owner">Owner window.</param>
            /// <param name="skip">A callback function that receives descendant indice and can return true to skip that window and its descendants.</param>
            /// <param name="andOwner">Add <i>owner</i> to the list too, at the position matching the Z order.</param>
            /// <returns>List of <see cref="all"/> indices of owned windows. Sorted like in the Z order. Not null.</returns>
            public List <int> GetIndices(wnd owner, Func <int, bool> skip = null, bool andOwner = false)
            {
                var ai = new List <int>();

                _Owned(owner);

                void _Owned(wnd owner)
                {
                    int oint = (int)owner;

                    for (int i = 0; i < owners.Length; i++)
                    {
                        if (owners[i] == oint)
                        {
                            if (skip != null && skip(i))
                            {
                                continue;
                            }
                            ai.Add(i);
                            _Owned(all[i]);
                        }
                    }
                }

                if (andOwner)
                {
                    int j = Array.IndexOf(all, owner);
                    if (j >= 0)
                    {
                        ai.Add(j);
                    }
                    else
                    {
                        Debug_.Print("owner not in all");
                    }
                }
                ai.Sort();
                return(ai);
            }
예제 #9
0
파일: Panels.cs 프로젝트: qmgindi/Au
    public static void LoadAndCreateToolbars()
    {
        var pm = PanelManager = new KPanels();

        //FUTURE: later remove this code. Now may need to delete old custom Layout.xml.
        var customLayoutPath = AppSettings.DirBS + "Layout.xml";

        if (filesystem.exists(customLayoutPath).File)
        {
            try {
                var s2 = filesystem.loadText(customLayoutPath);
                //print.it(s2);
                if (!s2.Contains("<panel name=\"Outline\""))                   //v0.4 added several new panels etc, and users would not know the best place for them, or even how to move
                {
                    filesystem.delete(customLayoutPath, FDFlags.RecycleBin);
                    bool silent = s2.RxIsMatch(@"<document name=""documents"" ?/>\s*</tab>");                     //very old and incompatible
                    if (!silent)
                    {
                        print.it("Info: The window layout has been reset, because several new panels have been added in this app version.\r\n\tIf you want to undo it: 1. Exit the program. 2. Restore file Layout.xml from the Recycle Bin (replace the existing file). 3. Run the program. 4. Move panels from the bottom of the window to a better place.");
                    }
                    //rejected: show Yes/No dialog. Let users at first see the new default layout, then they can undo.
                }
            }
            catch (Exception e1) { Debug_.Print(e1.ToStringWithoutStack()); }
        }

        pm.BorderBrush = SystemColors.ActiveBorderBrush;
        //pm.Load(folders.ThisAppBS + @"Default\Layout.xml", null);
        pm.Load(folders.ThisAppBS + @"Default\Layout.xml", customLayoutPath);

        pm["Menu"].Content = Menu = new Menu();
        TFile    = _TB("File");
        TEdit    = _TB("Edit");
        TRun     = _TB("Run");
        TTools   = _TB("Tools");
        THelp    = _TB("Help", true);
        TCustom1 = _TB("Custom1");
        TCustom2 = _TB("Custom2");

        ToolBar _TB(string name, bool isHelp = false)
        {
            var c = new ToolBar {
                Name = name
            };

            c.UiaSetName(name);
            c.HideGripAndOverflow(false);
            var tt = new ToolBarTray {
                IsLocked = true
            };                                                        //because ToolBar looks bad if parent is not ToolBarTray

            tt.ToolBars.Add(c);
#if true
            if (isHelp)
            {
                var p = new DockPanel {
                    Background = tt.Background
                };
                DockPanel.SetDock(tt, Dock.Right);
                p.Children.Add(tt);
                //FUTURE
                //var box = new TextBox { Height = 20, Margin = new Thickness(3, 1, 3, 2), Padding = new Thickness(1, 1, 1, 0) };
                //p.Children.Add(box);
                pm[name].Content = p;
            }
            else
            {
                pm[name].Content = tt;
            }
#else
            if (name == "Help")
            {
                c.Items.Add(new TextBox {
                    Width = 150, Padding = new Thickness(1, 0, 1, 0)
                });
            }
            pm[name].Content = tt;
#endif
            return(c);
        }

        //		ToolBar _TB(string name, bool isHelp = false) {
        //			var c = new ToolBar { Name = name };
        //			var tt = new ToolBarTray { IsLocked = true }; //because ToolBar looks bad if parent is not ToolBarTray
        //			c.UiaSetName(name);
        //			tt.ToolBars.Add(c);
        //#if true
        //			if (isHelp) {
        //				var p = new DockPanel { Background = tt.Background };
        //				DockPanel.SetDock(tt, Dock.Right);
        //				p.Children.Add(tt);
        //				//FUTURE
        //				//var box = new TextBox { Height = 20, Margin = new Thickness(3, 1, 3, 2), Padding = new Thickness(1, 1, 1, 0) };
        //				//p.Children.Add(box);
        //				pm[name].Content = p;
        //			} else {
        //				pm[name].Content = tt;
        //			}
        //#else
        //			if (name == "Help") c.Items.Add(new TextBox { Width = 150, Padding = new Thickness(1, 0, 1, 0) });
        //			pm[name].Content = tt;
        //#endif
        //			return c;
        //		}
    }
예제 #10
0
            /// <summary>
            /// Creates documentation provider for assembly <i>asmPath</i>.
            /// Returns null if its xml file does not exist.
            /// Returns _DocumentationProvider if xml file is big and found or successfully created and successfully loaded database for it.
            /// Else returns _XmlFileDocumentationProvider.
            /// </summary>
            public static DocumentationProvider Create(string asmPath)
            {
                if (s_d.TryGetValue(asmPath, out var dp))
                {
                    return(dp);
                }

                var xmlPath = Path.ChangeExtension(asmPath, "xml");

                if (!filesystem.getProperties(xmlPath, out var px))
                {
                    return(null);
                }

                if (px.Size >= 10_000)
                {
                    var md5    = new Hash.MD5Context(); md5.Add(xmlPath.Lower());
                    var dbPath = folders.ThisAppTemp + md5.Hash.ToString() + ".db";
                    try {
                        if (!filesystem.getProperties(dbPath, out var pd) || pd.LastWriteTimeUtc != px.LastWriteTimeUtc)
                        {
                            //Debug_.Print($"creating db: {asmPath}  ->  {dbPath}");
                            filesystem.delete(dbPath);
                            using (var d = new sqlite(dbPath)) {
                                using var trans = d.Transaction();
                                d.Execute("CREATE TABLE doc (name TEXT PRIMARY KEY, xml TEXT)");
                                using var statInsert = d.Statement("INSERT INTO doc VALUES (?, ?)");

                                var xr = XmlUtil.LoadElem(xmlPath);
                                foreach (var e in xr.Descendants("member"))
                                {
                                    var name = e.Attr("name");

                                    //remove <remarks> and <example>.
                                    foreach (var v in e.Descendants("remarks").ToArray())
                                    {
                                        v.Remove();
                                    }
                                    foreach (var v in e.Descendants("example").ToArray())
                                    {
                                        v.Remove();
                                    }

                                    using var reader = e.CreateReader();
                                    reader.MoveToContent();
                                    var xml = reader.ReadInnerXml();
                                    //print.it(name, xml);

                                    statInsert.BindAll(name, xml).Step();
                                    statInsert.Reset();
                                }
                                trans.Commit();
                                d.Execute("VACUUM");
                            }
                            File.SetLastWriteTimeUtc(dbPath, px.LastWriteTimeUtc);
                        }
                        var db = new sqlite(dbPath, SLFlags.SQLITE_OPEN_READONLY);                         //never mind: we don't dispose it on process exit
                        s_d[asmPath] = dp = new _DocumentationProvider {
                            _db = db
                        };
                        return(dp);
                    }
                    catch (Exception ex) { Debug_.Print(ex.ToStringWithoutStack()); }
                }
                //return XmlDocumentationProvider.CreateFromFile(xmlPath); //no, need XML with root element.
                return(new _XmlFileDocumentationProvider(xmlPath));
            }
예제 #11
0
파일: Dwnd.cs 프로젝트: qmgindi/Au
    bool _FillProperties(bool newWindow)
    {
        bool isCon = !_con.Is0;

        _WinInfo f = default;

        if (!_GetClassName(_wnd, out f.wClass))
        {
            return(false);                                            //note: get even if !newWindow, to detect closed window
        }
        if (isCon && !_GetClassName(_con, out f.cClass))
        {
            return(false);
        }

        bool _GetClassName(wnd w, out string cn)
        {
            cn = w.ClassName; if (cn != null)
            {
                return(true);
            }
            _winInfo.zText       = "Failed to get " + (w == _wnd ? "window" : "control") + " properties: \r\n" + lastError.message;
            _scroller.Visibility = Visibility.Hidden;
            return(false);
        }

        _noeventValueChanged = true;

        var wndName = _wnd.NameTL_;

        if (newWindow)
        {
            nameW.Set(true, TUtil.EscapeWindowName(wndName, true));
            classW.Set(true, TUtil.StripWndClassName(f.wClass, true));
            f.wProg = _wnd.ProgramName;
            var ap = new List <string> {
                f.wProg, "WOwner.Process(processId)", "WOwner.Thread(threadId)"
            }; if (!_wnd.Get.Owner.Is0)
            {
                ap.Add("WOwner.Window(ow)");
            }
            programW.Set(wndName.NE(), f.wProg, ap);
            containsW.Set(false, null, _ContainsCombo_DropDown);
        }
        else if (wndName != _wndName)
        {
            if (TUtil.ShouldChangeTextBoxWildex(nameW.t.Text, wndName))
            {
                nameW.Set(true, TUtil.EscapeWindowName(wndName, true));
            }
        }
        f.wName = _wndName = wndName;

        if (isCon)
        {
            //name combo
            f.cName = _con.Name;
            int iSel = f.cName.NE() ? -1 : 0;
            var an   = new List <string> {
                TUtil.EscapeWildex(f.cName)
            };
            _ConNameAdd("***wfName ", f.cWF = _con.NameWinforms);
            /*bool isElm =*/
            _ConNameAdd("***elmName ", f.cElm = _con.NameElm);
            //bool isLabel = _ConNameAdd("***label ", f.cLabel = _con.NameLabel);
            //if(isElm && isLabel && iSel == an.Count - 2 && f.cElm == f.cLabel) iSel++; //if label == elmName, prefer label
            if (iSel < 0)
            {
                iSel = 0;                       //never select text, even if all others unavailable
            }
            _ConNameAdd("***text ", f.cText = _con.ControlText);
            bool _ConNameAdd(string prefix, string value)
            {
                if (value.NE())
                {
                    return(false);
                }
                if (iSel < 0)
                {
                    iSel = an.Count;
                }
                an.Add(prefix + TUtil.EscapeWildex(value));
                return(true);
            }

            bool idUseful = TUtil.GetUsefulControlId(_con, _wnd, out f.cId);
            //idC.Visible = idUseful;
            idC.Set(idUseful, f.cId.ToS() + (idUseful ? null : " /*probably not useful*/"));
            string sName = an[iSel], sClass = TUtil.StripWndClassName(f.cClass, true);
            nameC.Set(!idUseful, sName, an);
            classC.Set(!idUseful, sClass);
            bool hiddenToo = !_con.IsVisible;
            cHiddenTooC.IsChecked = hiddenToo;
            var skip = idUseful ? null : TUtil.GetControlSkip(_wnd, _con, sName, sClass, hiddenToo);
            skipC.Set(skip != null, skip);
        }

        bool checkControl = isCon && _checkControl;

        _cControl.IsChecked = checkControl;
        _ShowControlProperties(showGrid: checkControl, showAll: isCon);

        _noeventValueChanged = false;

        _scroller.Visibility = Visibility.Visible;
        _FillWindowInfo(f);
        return(true);

        List <string> _ContainsCombo_DropDown()
        {
            try {
                var a1 = new List <string>();
                //child
                foreach (var c in _wnd.Get.Children(onlyVisible: true))
                {
                    var cn = c.Name; if (cn.NE())
                    {
                        continue;
                    }
                    cn = "c '" + TUtil.StripWndClassName(c.ClassName, true) + "' " + TUtil.EscapeWildex(cn);
                    if (!a1.Contains(cn))
                    {
                        a1.Add(cn);
                    }
                }
                //elm
                var    a2       = new List <string>();
                var    a3       = _wnd.Elm[name : "?*", prop : "notin=SCROLLBAR\0maxcc=100", flags : EFFlags.ClientArea].FindAll();     //all that have a name
                string prevName = null;
                for (int i = a3.Length; --i >= 0;)
                {
                    if (!a3[i].GetProperties("Rn", out var prop))
                    {
                        continue;
                    }
                    if (prop.Name == prevName && prop.Role == "WINDOW")
                    {
                        continue;
                    }
                    prevName = prop.Name;                                                                                   //skip parent WINDOW
                    string rn = "e '" + prop.Role + "' " + TUtil.EscapeWildex(prop.Name);
                    if (!a2.Contains(rn))
                    {
                        a2.Add(rn);
                    }
                }
                a2.Reverse();
                a1.AddRange(a2);

                return(a1);
                //rejected: sort
            }
            catch (Exception ex) { Debug_.Print(ex); return(null); }
        }
    }
예제 #12
0
파일: Triggers.cs 프로젝트: qmgindi/Au
        /// <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()
        {
            //Debug_.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;
                }
            }
            //print.it(haveTriggers, (uint)llHooks);
            //if(!haveTriggers) return; //no. The message loop may be used for toolbars etc.

            if (!s_wasRun)
            {
                s_wasRun = true;
                WndUtil.RegisterWindowClass(c_cn);
            }
            _wMsg             = WndUtil.CreateMessageOnlyWindow(_WndProc, c_cn);
            _mainThreadId     = Api.GetCurrentThreadId();
            _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 = perf.local();
                            new wndFinder("*a").IsMatch(wnd.getwnd.root);                     //if used window scopes etc
                            _ = WindowsHook.LowLevelHooksTimeout;                             //slow JIT of registry functions
                            Jit_.Compile(typeof(ActionTriggers), nameof(_WndProc), nameof(_KeyMouseEvent));
                            Jit_.Compile(typeof(TriggerHookContext), nameof(TriggerHookContext.InitContext), nameof(TriggerHookContext.PerfEnd), nameof(TriggerHookContext.PerfWarn));
                            Jit_.Compile(typeof(ActionTrigger), nameof(ActionTrigger.MatchScopeWindowAndFunc));
                            Jit_.Compile(typeof(HotkeyTriggers), nameof(HotkeyTriggers.HookProc));
                            AutotextTriggers.JitCompile();
                            MouseTriggers.JitCompile();
                        }
                        catch (Exception ex) { Debug_.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);
                    }
                }
            }
        }
예제 #13
0
    /// <summary>
    /// Called at the end of opening this workspace.
    /// </summary>
    public void LoadState(bool expandFolders = false, bool openFiles = false)
    {
        if (DB == null)
        {
            return;
        }
        try {
            Save.LoadingState = true;

            if (expandFolders)
            {
                if (DB.Get(out string s, "SELECT data FROM _misc WHERE key='expanded'") && !s.NE())
                {
                    foreach (var v in s.Segments(" "))
                    {
                        var f = FindById(s[v.Range]);
                        //if (f != null) TreeControl.Expand(f, true);
                        if (f != null)
                        {
                            f.SetIsExpanded(true);
                        }
                    }
                }
            }

            if (openFiles)
            {
                if (DB.Get(out string s, "SELECT data FROM _misc WHERE key='open'") && !s.NE())
                {
                    //format: indexOfActiveDocOrMinusOne id1 id2 ...
                    int      i = -2, iActive = s.ToInt();
                    FileNode fnActive = null;
                    //perf.first();
                    foreach (var v in s.Segments(" "))
                    {
                        i++; if (i < 0)
                        {
                            continue;
                        }
                        var fn = FindById(s[v.Range]); if (fn == null)
                        {
                            continue;
                        }
                        OpenFiles.Add(fn);
                        if (i == iActive)
                        {
                            fnActive = fn;
                        }
                    }
                    //perf.next();
                    if (fnActive == null || !SetCurrentFile(fnActive))
                    {
                        _UpdateOpenFiles(null);                                                                    //disable Previous command
                    }
                    //perf.nw();
                }
            }
        }
        catch (Exception ex) { Debug_.Print(ex); }
        finally { Save.LoadingState = false; }
    }
예제 #14
0
파일: clipboard.cs 프로젝트: qmgindi/Au
            nint _WndProc(wnd w, int message, nint wParam, nint lParam)
            {
                //WndUtil.PrintMsg(w, message, wParam, lParam);

                switch (message)
                {
                //case Api.WM_DESTROY:
                //	Api.ChangeClipboardChain(w, _wPrevClipViewer);
                //	break;
                case Api.WM_RENDERFORMAT:
                    if (_paste && !Success)
                    {
                        IsBadWindow = !_IsTargetWindow();

                        //note: need to set clipboard data even if bad window.
                        //	Else the clipboard program may retry in loop. Eg Ditto. Then often pasting fails.
                        //	If IsBadWindow, we'll then sleep briefly.
                        //	Good clipboard programs get clipboard data with a delay. Therefore usually they don't interfere, unless the target app is very slow.
                        //		Eg Windows Clipboard History 200 ms. Eg Ditto default is 100 ms and can be changed.
                        //	Also, after setting clipboard data we cannot wait for good window, because we'll not receive second WM_RENDERFORMAT.

                        try { _SetClipboard(_data, false); }
                        catch (Exception ex) { FailedToSetData = ex; }                         //cannot throw in wndproc, will throw later
                        waitVar = true;
                    }
                    return(0);

                case Api.WM_CLIPBOARDUPDATE:
                    //posted, not sent. Once, not for each format. Added in WinVista. QM2 used SetClipboardViewer/WM_DRAWCLIPBOARD.
                    if (!_paste)
                    {
                        waitVar = true;
                    }
                    return(0);
                }

                return(Api.DefWindowProc(w, message, wParam, lParam));

                //Returns false if probably not the target app reads from the clipboard. Probably a clipboard viewer/manager/etc.
                bool _IsTargetWindow()
                {
                    wnd wOC = Api.GetOpenClipboardWindow();

                    //int color = 0; if(wOC != _wFocus) color = wOC.ProcessId == _wFocus.ProcessId ? 0xFF0000 : 0xFF;
                    //print.it($"<><c {color}>{wOC}</c>");

                    if (wOC == _wFocus)
                    {
                        return(true);
                    }
                    if (wOC.Is0)
                    {
                        return(true);                             //tested: none of tested apps calls OpenClipboard(0)
                    }
                    if (wOC.ProcessId == _wFocus.ProcessId)
                    {
                        return(true);                                                        //often classnamed "CLIPBRDWNDCLASS". Some clipboard managers too, eg Ditto.
                    }
                    if (osVersion.minWin10 && 0 != _wFocus.Window.IsUwpApp)
                    {
                        var prog = wOC.ProgramName;
                        if (prog.Eqi("svchost.exe"))
                        {
                            return(true);
                        }
                        //if (prog.Eqi("RuntimeBroker.exe")) return true; //used to be Store apps
                        //tested: no problems on Win8.1
                    }
                    //tested: WinUI3 (cn "WinUIDesktopWin32WindowClass"): wOC != _wFocus, but same process.

                    //CONSIDER: option to return true for user-known windows, eg using a callback. Print warning that includes wOC info.

                    Debug_.Print(wOC.ToString());
                    return(false);

                    //BlueStacks problems:
                    //	Uses an aggressive viewer. Always debugprints while it is running, even when other apps are active.
                    //	Sometimes pastes old text, usually after starting BlueStacks or after some time of not using it.
                    //		With or without clipboard restoring.
                    //		Then starts to work correctly always. Difficult to debug.
                    //		KeySpeedClipboard=100 usually helps, but sometimes even 300 does not help.
                }
            }
예제 #15
0
파일: CiSignature.cs 프로젝트: qmgindi/Au
    System.Windows.Documents.Section _FormatText(int iSel, bool userSelected)
    {
        _data.iSelected = iSel;
        if (userSelected)
        {
            _data.iUserSelected = iSel;
        }

        var     r           = _data.r;
        ISymbol currentItem = null;
        SignatureHelpParameter currentParameter = null;
        var x = new CiText();

        //print.clear();
        for (int i = 0; i < r.Items.Count; i++)
        {
            var sh = r.Items[i];
            if (sh is AbstractSignatureHelpProvider.SymbolKeySignatureHelpItem kk)
            {
                var sym = kk.Symbol;
                if (i == iSel)
                {
                    currentItem = sym;
                }
                x.StartOverload(i == iSel, i);
#if false
                x.AppendTaggedParts(sh.PrefixDisplayParts);                 //works, but formats not as I like (too much garbage). Has bugs with tuples.
#else
                //if(nt != null) {
                //	print.it(1, nt.IsGenericType, nt.IsTupleType, nt.IsUnboundGenericType, nt.Arity, nt.CanBeReferencedByName);
                //	print.it(2, nt.IsAnonymousType, nt.IsDefinition, nt.IsImplicitlyDeclared, nt.Kind, nt.TypeKind);
                //	print.it(3, nt.MemberNames);
                //	print.it(4, nt.Name, nt.MetadataName, nt.OriginalDefinition, nt.TupleUnderlyingType);
                //	print.it("TypeParameters:");
                //	print.it(nt.TypeParameters);
                //	print.it("TypeArguments:");
                //	print.it(nt.TypeArguments);
                //	print.it("TupleElements:");
                //	try { var te = nt.TupleElements; if(!te.IsDefault) print.it(te); } catch(Exception e1) { print.it(e1.ToStringWithoutStack()); }
                //	print.it("---");
                //}

                int isTuple = 0;                 //1 ValueTuple<...>, 2 (...)
                var nt      = sym as INamedTypeSymbol;
                if (nt != null && nt.IsTupleType)
                {
                    isTuple = nt.IsDefinition ? 1 : 2;
                }

                if (isTuple == 1)
                {
                    x.Append("ValueTuple");                               //AppendSymbolWithoutParameters formats incorrectly
                }
                else if (isTuple == 0)
                {
                    x.AppendSymbolWithoutParameters(sym);
                }
                string b1 = "(", b2 = ")";
                if (nt != null)
                {
                    if (nt.IsGenericType && isTuple != 2)
                    {
                        b1 = "<"; b2 = ">";
                    }
                }
                else if (sym is IPropertySymbol)
                {
                    b1 = "["; b2 = "]";
                }
                x.Append(b1);
#endif
                int iArg = r.ArgumentIndex, lastParam = sh.Parameters.Length - 1;
                int selParam = iArg <= lastParam ? iArg : (sh.IsVariadic ? lastParam : -1);
                if (!r.ArgumentName.NE())
                {
                    var pa = sh.Parameters;
                    for (int pi = 0; pi < pa.Length; pi++)
                    {
                        if (pa[pi].Name == r.ArgumentName)
                        {
                            selParam = pi; break;
                        }
                    }
                }
                x.AppendParameters(sym, selParam, sh);
                //x.AppendParameters(sh, selParam); //works, but formats not as I like (too much garbage)
#if false
                x.AppendTaggedParts(sh.SuffixDisplayParts);
#else
                x.Append(b2);
#endif
                if (i == iSel && selParam >= 0)
                {
                    currentParameter = sh.Parameters[selParam];
                }
                x.EndOverload(i == iSel);
            }
            else
            {
                Debug_.Print(sh);
            }
        }

        if (currentItem != null)
        {
            var    tt        = r.Items[iSel].DocumentationFactory?.Invoke(default);
예제 #16
0
    static void _Statements(string s, ICSFlags flags, bool separate)
    {
        if (!App.Hmain.IsVisible)
        {
            App.ShowWindow();
        }
        if (!CodeInfo.GetContextAndDocument(out var k, metaToo: true))
        {
            print.it(s);
            return;
        }
        var root  = k.syntaxRoot;
        var code  = k.code;
        var pos   = k.pos;
        var token = root.FindToken(pos);
        var node  = token.Parent;

        //get the best valid insertion place

        bool havePos = false;
        var  last    = root.AttributeLists.LastOrDefault() as SyntaxNode
                       ?? root.Usings.LastOrDefault() as SyntaxNode
                       ?? root.Externs.LastOrDefault() as SyntaxNode
                       ?? root.GetDirectives(o => o is DefineDirectiveTriviaSyntax).LastOrDefault();

        if (last != null)
        {
            int e1 = last.FullSpan.End;
            if (havePos = pos <= e1)
            {
                pos = e1;
            }
        }

        if (!havePos)
        {
            var members = root.Members;
            if (members.Any())
            {
                var g           = members.LastOrDefault(o => o is GlobalStatementSyntax);
                int posAfterTLS = g?.FullSpan.End ?? members.First().FullSpan.Start;

                bool done1 = false;
                if (node is BlockSyntax)
                {
                    done1 = node.Span.ContainsInside(pos);
                }
                else if (node is MemberDeclarationSyntax)
                {
                    done1 = true;
                    //don't use posAfterTLS if before the first type
                    bool here = node == members.FirstOrDefault(o => o is not GlobalStatementSyntax) && pos <= node.SpanStart;
                    pos = Math.Min(pos, here ? node.SpanStart : posAfterTLS);
                }
                else if (node is CompilationUnitSyntax && g != members[^ 1])                    //after types
                {
                    done1 = true;
                    pos   = Math.Min(pos, posAfterTLS);
                }
                if (!done1)
                {
                    for (; node is not CompilationUnitSyntax; node = node.Parent)
                    {
                        //CiUtil.PrintNode(node);
                        if (node is StatementSyntax)
                        {
                            var pa = node.Parent;
                            if (node is BlockSyntax && pa is not(BlockSyntax or GlobalStatementSyntax))
                            {
                                continue;
                            }
                            var span = node.Span;
                            if (havePos = pos >= span.End && token.IsKind(SyntaxKind.CloseBraceToken))
                            {
                                pos = node.FullSpan.End;
                            }
                            else if (havePos = pos >= span.Start)
                            {
                                pos = span.Start;
                            }
                            break;
                        }
                        if (node is MemberDeclarationSyntax)
                        {
                            pos = posAfterTLS;
                            break;
                        }
                    }
                }

                havePos |= pos == posAfterTLS;
            }
        }

        if (k.meta.end > 0 && pos <= k.meta.end)
        {
            havePos = true;
            pos     = k.meta.end;
            if (code.Eq(pos, "\r\n"))
            {
                pos += 2;
            }
            else if (code.Eq(pos, '\n'))
            {
                pos++;
            }
        }

        if (!havePos)           //if in comments or directive or disabled code, move to the start of trivia or line
        {
            var trivia = root.FindTrivia(pos);
            var tk     = trivia.Kind();
            if (tk is not(SyntaxKind.EndOfLineTrivia or SyntaxKind.None))
            {
                if (tk == SyntaxKind.DisabledTextTrivia)
                {
                    while (pos > 0 && code[pos - 1] != '\n')
                    {
                        pos--;
                    }
                }
                else
                {
                    pos = trivia.FullSpan.Start;
                }
                //rejected: move to the start of entire #if ... block.
                //	Rare, not easy, may be far, and maybe user wants to insert into disabled code.
            }
        }

        //rename symbols in s if need

        try { _RenameNewSymbols(ref s, k.document, node, pos); }
        catch (Exception e1) { Debug_.Print(e1); }

        //indent, newlines

        string breakLine = null;

        for (; pos > 0 && code[pos - 1] != '\n'; pos--)
        {
            if (code[pos - 1] is not(' ' or '\t'))
            {
                breakLine = "\r\n"; break;
            }
        }
        int replTo = pos; while (replTo < code.Length && code[replTo] is ' ' or '\t')
        {
            replTo++;
        }

        var d = k.sci;

        var t2 = root.FindToken(pos); if (t2.SpanStart >= pos)
        {
            t2 = t2.GetPreviousToken();
        }
        bool afterOpenBrace   = t2.IsKind(SyntaxKind.OpenBraceToken);
        bool beforeCloseBrace = replTo < code.Length && code[replTo] == '}';

        int indent = d.zLineIndentationFromPos(true, pos);

        if (afterOpenBrace && breakLine != null && !(t2.Parent is BlockSyntax bs1 && bs1.Parent is GlobalStatementSyntax))
        {
            indent++;
        }