Beispiel #1
0
        /// <summary>
        /// Same as GetName, but faster when called several times for same window, like <c>if(w.ProgramName=="A" || w.ProgramName=="B")</c>.
        /// </summary>
        internal static string GetNameCached_(wnd w, int processId, bool fullPath = false)
        {
            if (processId == 0)
            {
                return(null);
            }
            var cache = _LastWndProps.OfThread;

            cache.Begin(w);
            var R = fullPath ? cache.ProgramPath : cache.ProgramName;

            if (R == null)
            {
                R = getName(processId, fullPath);
                if (fullPath)
                {
                    cache.ProgramPath = R;
                }
                else
                {
                    cache.ProgramName = R;
                }
            }
            return(R);
        }
Beispiel #2
0
        /// <summary>
        /// Gets nonbuffered DC with API <msdn>BeginPaint</msdn> or <msdn>GetDC</msdn>. Then gets buffered DC with API <msdn>BeginBufferedPaint</msdn> for entire client area or rectangle <i>r</i>.
        /// </summary>
        /// <param name="w"></param>
        /// <param name="wmPaint">Use API <b>BeginPaint</b>/<b>EndPaint</b>. If false, uses <b>GetDC</b>/<b>ReleaseDC</b>.</param>
        /// <param name="r">Part of client area.</param>
        public unsafe BufferedPaint(wnd w, bool wmPaint, RECT?r = null)
        {
            if (!s_inited)
            {
                s_inited = 0 == Api.BufferedPaintInit();
            }

            _w = w;
            if (_wmPaint = wmPaint)
            {
                _dcn = Api.BeginPaint(w, out _ps);
            }
            else
            {
                _ps  = default;
                _dcn = Api.GetDC(_w);
            }

            _r = r ?? _w.ClientRect;
            Api.BP_PAINTPARAMS pp = new() { cbSize = sizeof(Api.BP_PAINTPARAMS) };
            //var ru = wmPaint ? _ps.rcPaint : _r; //the buffer bitmap is smaller when rcPaint smaller, but in most cases don't need to change painting code, although GetViewportOrgEx etc get 0 offsets of the buffer DC. However problem with brush alignment.
            _hb = Api.BeginBufferedPaint(_dcn, _r, Api.BP_BUFFERFORMAT.BPBF_TOPDOWNDIB, ref pp, out _dcb);             //BPBF_COMPATIBLEBITMAP slower //tested: works with 16 and 8 bit colors too
            Debug_.PrintIf(_hb == default && !_r.NoArea, $"BeginBufferedPaint, {_r}");
            if (_hb == default)
            {
                _dcb = _dcn;
            }
        }
Beispiel #3
0
 public HooksThread(UsedEvents usedEvents, wnd wMsg)
 {
     _usedEvents = usedEvents;
     _wMsg       = wMsg;
     run.thread(_Thread, sta: false);             //important: not STA, because we use lock, which dispatches sent messages if STA
     Api.WaitForSingleObject(_eventStartStop, -1);
 }
Beispiel #4
0
        /// <summary>
        /// Gets the DPI of a window, as used by the window's process. It never changes for that window instance.
        /// </summary>
        /// <param name="w">A top-level window or control. Can belong to any process.</param>
        /// <param name="supportWin81">
        /// If true, works on Windows 8.1 and later; however on Windows 8.1 slower and less reliable.
        /// If false (default), works on Windows 10 1607 and later.
        /// </param>
        /// <remarks>
        /// The result depends on the DPI awareness of the window:
        /// - per-monitor-DPI-aware - usually DPI of the windows's screen.
        /// - system aware - system DPI (DPI of the primary screen).
        /// - unaware - 96.
        ///
        /// The result also depends on the Windows version:
        /// - Works best on Windows 10 1607 and later. Uses API <msdn>GetDpiForWindow</msdn>.
        /// - On Windows 8.1 works if <i>supportWin81</i> true. If false (default), returns <see cref="System"/>.
        /// - On Windows 7 and 8.0 always returns <see cref="System"/>, because there are no Windows API. Most apps are system-DPI-aware and the result is correct; for unaware apps the result is incorrect. These Windows versions don't support per-monitor DPI.
        ///
        /// Returns the system DPI (<see cref="System"/>) if fails.
        /// </remarks>
        public static int OfWindow(wnd w, bool supportWin81 = false)
        {
            if (!osVersion.minWin8_1)
            {
                return(System);
            }
            int R = 0;

            if (!w.Is0)
            {
                if (osVersion.minWin10_1607)
                {
                    R = Api.GetDpiForWindow(w);
                }
                else if (supportWin81)
                {
                    var v = WindowDpiAwareness(w);                     //info: quickly returns Awareness.PerMonitor if w.IsOfThisProcess
                    if (v == Awareness.Unaware)
                    {
                        R = 96;
                    }
                    else if (v == Awareness.PerMonitor)
                    {
                        if (0 != Api.GetDpiForMonitor(Api.MonitorFromWindow(w.Window, SODefault.Nearest), 0, out R, out _))
                        {
                            R = 0;
                        }
                    }
                }
            }
            return(R != 0 ? R : System);
        }
Beispiel #5
0
        /// <summary>
        /// Gets text cursor (caret) position and size.
        /// Returns false if fails.
        /// </summary>
        /// <param name="r">Receives the rectangle, in screen coordinates.</param>
        /// <param name="w">Receives the control that contains the text cursor.</param>
        /// <param name="orMouse">If fails, get mouse pointer coodinates.</param>
        /// <remarks>
        /// Can get only standard text cursor. Many apps use non-standard cursor; then fails.
        /// Also fails if the text cursor currently is not displayed.
        /// </remarks>
        public static bool getTextCursorRect(out RECT r, out wnd w, bool orMouse = false)
        {
            if (getGUIThreadInfo(out var g) && !g.hwndCaret.Is0)
            {
                if (g.rcCaret.bottom <= g.rcCaret.top)
                {
                    g.rcCaret.bottom = g.rcCaret.top + 16;
                }
                r = g.rcCaret;
                g.hwndCaret.MapClientToScreen(ref r);
                w = g.hwndCaret;
                return(true);
            }
            if (orMouse)
            {
                Api.GetCursorPos(out var p);
                r = new RECT(p.x, p.y, 0, 16);
            }
            else
            {
                r = default;
            }
            w = default;
            return(false);

            //note: in Word, after changing caret pos, gets pos 0 0. After 0.5 s gets correct. After typing always correct.
            //tested: accessibleobjectfromwindow(objid_caret) is the same, but much slower.
        }
Beispiel #6
0
 /// <summary>
 /// Gets info of a menu item from point.
 /// Returns null if fails, eg the point is not in the menu or the window is hung.
 /// </summary>
 /// <param name="pScreen">Point in screen coordinates.</param>
 /// <param name="w">Popup menu window, class name "#32768".</param>
 /// <param name="msTimeout">Timeout (ms) to use when the window is busy or hung.</param>
 public static MenuItemInfo FromXY(POINT pScreen, wnd w, int msTimeout = 5000)
 {
     if (!w.SendTimeout(msTimeout, out var hm, Api.MN_GETHMENU))
     {
         return(null);
     }
     int i = Api.MenuItemFromPoint(default, hm, pScreen); if (i == -1)
Beispiel #7
0
            IntPtr _w, _wDesk;             //not wnd because then TypeLoadException

            public int IsShellWindow(wnd w)
            {
                if (w.Is0)
                {
                    return(0);
                }
                wnd wDesk = getwnd.shellWindow;                 //fast

                if (w == wDesk)
                {
                    return(1);                            //Progman. Other window (WorkerW) may be active when desktop active.
                }
                //cache because GetWindowThreadProcessId quite slow
                if (w.Handle != _w)
                {
                    _w = w.Handle; _tidW = w.GetThreadProcessId(out _pidW);
                }
                if (wDesk.Handle != _wDesk)
                {
                    _wDesk = wDesk.Handle; _tidD = wDesk.GetThreadProcessId(out _pidD);
                }

                if (_tidW == _tidD)
                {
                    return(1);
                }
                if (_pidW == _pidD)
                {
                    return(2);
                }
                return(0);
            }
Beispiel #8
0
 public static KPopup FromHwnd(wnd w)
 {
     if (w.IsAlive && HwndSource.FromHwnd(w.Handle) is _HwndSource hs)
     {
         return(hs.kpopup);
     }
     return(null);
 }
Beispiel #9
0
 static int _Code(int code, wnd w)
 {
     if (code != 0 || w.IsAlive)
     {
         return(code);
     }
     return(Api.ERROR_INVALID_WINDOW_HANDLE);
 }
Beispiel #10
0
        nint _WndProc(wnd w, int msg, nint wParam, nint lParam)
        {
            //var pmo = new PrintMsgOptions(Api.WM_NCHITTEST, Api.WM_SETCURSOR, Api.WM_MOUSEMOVE, Api.WM_NCMOUSEMOVE, 0x10c1);
            //if (WndUtil.PrintMsg(out string s, _w, msg, wParam, lParam, pmo)) print.it("<><c green>" + s + "<>");
            //if (WndUtil.PrintMsg(out string s, _w, msg, wParam, lParam)) print.it("<><c green>" + s + "<>");

            if (_vscroll.WndProc(w, msg, wParam, lParam) || _hscroll.WndProc(w, msg, wParam, lParam))
            {
                return(default);
Beispiel #11
0
        /// <summary>
        /// On Win10+, if w is "ApplicationFrameWindow", returns the real app window "Windows.UI.Core.CoreWindow" hosted by w.
        /// If w is minimized, cloaked (eg on other desktop) or the app is starting, the "Windows.UI.Core.CoreWindow" is not its child. Then searches for a top-level window named like w. It is unreliable, but MS does not provide API for this.
        /// Info: "Windows.UI.Core.CoreWindow" windows hosted by "ApplicationFrameWindow" belong to separate processes. All "ApplicationFrameWindow" windows belong to a single process.
        /// </summary>
        static wnd _WindowsStoreAppFrameChild(wnd w)
        {
            bool   retry = false;
            string name;

g1:
            if (!osVersion.minWin10 || !w.ClassNameIs("ApplicationFrameWindow"))
            {
                return(default);
Beispiel #12
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;
                }
Beispiel #13
0
        //Called from Main() in non-admin process when command line starts with /dd.
        public static void MainDD(string[] args)
        {
            _msgWnd = (wnd)args[1].ToInt();

            WndUtil.RegisterWindowClass("Au.Editor.DD", _WndProc);
            _w = WndUtil.CreateWindow("Au.Editor.DD", null, WS.POPUP | WS.DISABLED, WSE.LAYERED | WSE.NOACTIVATE | WSE.TOOLWINDOW | WSE.TOPMOST);
            Api.SetLayeredWindowAttributes(_w, 0, 1, 2);

            Thread.CurrentThread.TrySetApartmentState(ApartmentState.Unknown);             //uninit MTA
            Api.OleInitialize(default);
Beispiel #14
0
            internal void Begin(wnd w)
            {
                var t = Api.GetTickCount64();

                if (w != _w || t - _time > 300)
                {
                    _w = w; ProgramName = ProgramPath = null;
                }
                _time = t;
            }
Beispiel #15
0
 /// <summary>
 /// Specifies a window or control and a rectangle in its client area.
 /// The parameters are of <see cref="Coord"/> type, therefore can be easily specified reverse and fractional coordinates, like <c>^10</c> and <c>.5f</c>. Use <c>^0</c> for right or bottom edge.
 /// </summary>
 public IFArea(wnd w, Coord left, Coord top, Coord right, Coord bottom)
 {
     Type    = AreaType.Wnd;
     W       = w;
     cLeft   = left;
     cTop    = top;
     cRight  = right;
     cBottom = bottom;
     HasRect = HasCoord = true;
 }
Beispiel #16
0
 static bool _GetRect(wnd w, out RECT r)
 {
     using (var u2 = new AwarenessContext(-4)) {                     //per-monitor-v2
         if (u2.Previous_ == 0)
         {
             r = default; return(false);
         }                                                                             //API failed. Unlikely. Works even if this process is Unaware.
         r = w.Rect;
     }
     return(true);
 }
Beispiel #17
0
        /// <summary>
        /// Detects whether the window is DPI-scaled/virtualized.
        /// </summary>
        /// <returns>Returns false if not DPI-scaled/virtualized or if fails to detect or if invalid window handle.</returns>
        /// <param name="w">A top-level window or control. Can belong to any process.</param>
        /// <remarks>
        /// The user can recognize such windows easily: entire client area is a little blurry.
        ///
        /// OS scales a window when it is on a high-DPI screen, depending on the DPI awareness of the window:
        /// - Unaware - always.
        /// - System - if the screen DPI is not equal to the system DPI of that process (which usually is of the primary screen, but not always).
        ///
        /// Such windows have various problems for automation apps:
        /// - Often difficult or impossible to get correct rectangles of UI elements (and therefore cannot click etc) or get correct UI element from point. It depends on used API (UIA, MSAA, JAB), inproc/notinproc, OS version and application.
        /// - On Windows 7 and 8.0 cannot easily get correct rectangles of such windows and their controls. This library ignores it, because would be too much work to apply workarounds in so many places and just for legacy OS versions (it has been fixed in Windows 8.1).
        /// - If with <see cref="uiimage"/> want to use window pixels, need to capture image from window pixels, not from screen pixels.
        ///
        /// This function is not completely reliable. And not very fast. This process should be per-monitor-DPI-aware.
        /// </remarks>
        public static bool IsWindowVirtualized(wnd w)
        {
            if (GetScalingInfo_(w, out bool scaled, out _, out _))
            {
                return(scaled);
            }
            return(IsWindowVirtualizedLegacy_(w));

            //note: child windows can have different DPI awareness (minWin10_1607). See GetWindowDpiHostingBehavior. Not tested, not seen.

            //Also tested detecting with GDI. GDI functions return logical (not DPI-scaled) offsets/rectangles/etc. Works, but much slower.
        }
Beispiel #18
0
 /// <summary>
 /// Gets the programming name of a Windows Forms control.
 /// Returns null if it is not a Windows Forms control or if fails.
 /// </summary>
 /// <param name="c">The control. Can be top-level window too.</param>
 /// <remarks>This function is easy to use and does not throw excaptions. However, when you need names of multiple controls of a single window, better create a WinformsControlNames instance (once) and for each control call its GetControlNameOrText method, it will be faster.</remarks>
 public static string GetSingleControlName(wnd c)
 {
     if (!IsWinformsControl(c))
     {
         return(null);
     }
     try {
         using (var x = new WinformsControlNames(c)) return(x.GetControlName(c));
     }
     catch { }
     return(null);
 }
Beispiel #19
0
 static nint _WndProc(wnd w, int message, nint wparam, nint lparam)
 {
     switch (message)
     {
     case Api.WM_COPYDATA:
         if (App.Loaded >= EProgramState.Unloading)
         {
             return(default);
         }
         try { return(_WmCopyData(wparam, lparam)); }
         catch (Exception ex) { print.it(ex.Message); }
         return(default);
Beispiel #20
0
        //Called from editor's CommandLine. Almost same as _Run. Does not throw.
        internal static int RunCL_(wnd w, int mode, string script, string[] args, Action <string> resultA)
        {
            bool wait = 0 != (mode & 1), needResult = 0 != (mode & 2);

            using var tr = new _TaskResults();
            if (needResult && !tr.Init())
            {
                return((int)RunResult_.cannotGetResult);
            }

            var data = Serializer_.Serialize(script, args, tr.pipeName);
            int pid  = (int)WndCopyData.Send <byte>(w, 101, data, mode);

            if (pid == 0)
            {
                pid--;                       //RunResult_.failed
            }
            switch ((RunResult_)pid)
            {
            case RunResult_.failed:
            case RunResult_.notFound:
                return(pid);

            case RunResult_.deferred:             //possible only if !wait
            case RunResult_.editorThread:         //the script ran sync and already returned. Ignore needResult, as it it auto-detected, not explicitly specified.
                return(0);
            }

            if (wait)
            {
                using var hProcess = WaitHandle_.FromProcessId(pid, Api.SYNCHRONIZE | Api.PROCESS_QUERY_LIMITED_INFORMATION);
                if (hProcess == null)
                {
                    return((int)RunResult_.cannotWait);
                }

                if (!needResult)
                {
                    hProcess.WaitOne(-1);
                }
                else if (!tr.WaitAndRead(hProcess, resultA))
                {
                    return((int)RunResult_.cannotWaitGetResult);
                }

                if (!Api.GetExitCodeProcess(hProcess.SafeWaitHandle.DangerousGetHandle(), out pid))
                {
                    pid = int.MinValue;
                }
            }
            return(pid);
        }
Beispiel #21
0
 public static void ShowActiveTriggers()
 {
     for (wnd w = default; ;)
     {
         w = wnd.findFast(null, "Au.Triggers.Hooks", messageOnly: true, w);
         if (w.Is0)
         {
             break;
         }
         Api.AllowSetForegroundWindow(w.ProcessId);
         w.Post(Api.WM_USER + 30);
     }
 }
Beispiel #22
0
 public void Close(bool destroyOwnerWindow)
 {
     if (_isOpen)
     {
         Api.CloseClipboard();
         _isOpen = false;
     }
     if (destroyOwnerWindow && !_w.Is0)
     {
         Api.DestroyWindow(_w);
         _w = default;
     }
 }
Beispiel #23
0
 /// <summary>
 /// Unregisters the hotkey.
 /// </summary>
 /// <remarks>
 /// Called implicitly when disposing this variable.
 /// Must be called from the same thread as when registering, and the window must be still alive.
 /// If fails, calls <see cref="print.warning"/>.
 /// </remarks>
 public void Unregister()
 {
     if (_id != 0)
     {
         if (!Api.UnregisterHotKey(_w, _id))
         {
             var es = lastError.message;
             print.warning($"Failed to unregister hotkey, id={_id}. {es}");
             return;
         }
         _id = 0; _w = default;
         //Hotkey = default;
     }
 }
Beispiel #24
0
        //SendMessage from _wTransparent on WM_CREATE.
        public static void OnTransparentWindowCreated(wnd wTransparent)
        {
            var x = s_inst;

            if (x?._isDragMode ?? false)
            {
                x._wTransparent = wTransparent;
                x._SetTransparentSizeZorder();
            }
            else
            {
                wTransparent.Post(Api.WM_USER);                //let it close self
            }
        }
Beispiel #25
0
        static api.IWebBrowserApp _GetIWebBrowserApp(wnd w)
        {
            var sw = new api.ShellWindows() as api.IShellWindows;

            for (int i = 0, n = sw.Count(); i < n; i++)
            {
                var b = sw.Item(i) as api.IWebBrowserApp;
                if ((wnd)b.HWND == w)
                {
                    return(b);
                }
            }
            return(null);
        }
Beispiel #26
0
 public OpenClipboard_(bool createOwner, bool noOpenNow = false)
 {
     _isOpen = false;
     _w      = default;
     if (createOwner)
     {
         _w = WndUtil.CreateWindowDWP_(messageOnly: true);
         //MSDN says, SetClipboardData fails if OpenClipboard called with 0 hwnd. It doesn't, but better use hwnd.
     }
     if (!noOpenNow)
     {
         Reopen();
     }
 }
Beispiel #27
0
        /// <summary>Destroys the OSD window.</summary>
        protected virtual void Dispose(bool disposing)
        {
            if (_w.Is0)
            {
                return;
            }
            Api.ShowWindow(_w, 0);
            _TopmostWorkaroundUndo();
            var w = _w; _w = default;

            if (!Api.DestroyWindow(w))
            {
                w.Post(Api.WM_CLOSE);
            }
        }
Beispiel #28
0
            /// <summary>
            /// Subclasses clipOwner.
            /// </summary>
            /// <param name="paste">true if used for paste, false if for copy.</param>
            /// <param name="data">If used for paste, can be string containing Unicode text or int/string dictionary containing clipboard format/data.</param>
            /// <param name="clipOwner">Our clipboard owner window.</param>
            /// <param name="wFocus">The target control or window.</param>
            public _ClipboardListener(bool paste, object data, wnd clipOwner, wnd wFocus)
            {
                _paste   = paste;
                _data    = data;
                _wndProc = _WndProc;
                _wFocus  = wFocus;
                WndUtil.SubclassUnsafe_(clipOwner, _wndProc);

                //rejected: use SetClipboardViewer to block clipboard managers/viewers/etc. This was used in QM2.
                //	Nowadays most such programs don't use SetClipboardViewer. They use AddClipboardFormatListener+WM_CLIPBOARDUPDATE.
                //	known apps that have clipboard viewer installed with SetClipboardViewer:
                //		OpenOffice, LibreOffice: tested Writer, Calc.
                //		VLC: after first Paste.
                //_wPrevClipViewer = Api.SetClipboardViewer(clipOwner);
                //print.it(_wPrevClipViewer);
            }
Beispiel #29
0
            /// <summary>
            /// Calls/returns <see cref="findFast"/> and stores found hwnd and time. Returns the cached hwnd if called frequently and it's still valid.
            /// </summary>
            public wnd FindFast(string name, string cn, bool messageOnly)
            {
                long t = Environment.TickCount64;

                if (t - _time > 1000 || !_w.IsAlive)
                {
                    lock ("x5rX3BZJrE+pOTqszh4ttQ") {
                        if (t - _time > 1000 || !_w.IsAlive)
                        {
                            _w = findFast(name, cn, messageOnly);
                        }
                    }
                }
                _time = t;
                return(_w);
            }
Beispiel #30
0
    void _SetWndCon(wnd w, wnd con, bool useCon, bool updateCodeIfNeed)
    {
        var wPrev = _WndSearchIn;

        _wnd = w;

        _con = con == w ? default : con;

               _noeventValueChanged = !updateCodeIfNeed;
               _useCon            = useCon && !_con.Is0;
               controlC.IsChecked = _useCon; controlC.IsEnabled = !_con.Is0;
               if (_WndSearchIn != wPrev)
               {
                   rectC.c.IsChecked = false;
               }
               _noeventValueChanged = false;
    }