Example #1
0
 wnd[] _FindAll(WndList_ k, wnd wParent)
 {
     using (k) {
         using var ab = new ArrayBuilder_ <wnd>();
         _FindInList(wParent, k, w => ab.Add(w));                 //CONSIDER: ab could be part of _WndList. Now the delegate creates garbage.
         return(ab.ToArray());
     }
 }
Example #2
0
 /// <summary>
 /// Returns true if control c properties match the specified properties.
 /// </summary>
 /// <param name="c">A control. Can be 0/invalid, then returns false.</param>
 /// <param name="wParent">Direct or indirect parent window. If used, returns false if it isn't parent (also depends on flag DirectChild).</param>
 public bool IsMatch(wnd c, wnd wParent = default)
 {
     if (!wParent.Is0 && !c.IsChildOf(wParent))
     {
         Result = default;
         return(false);
     }
     return(0 == _FindInList(wParent, new WndList_(c)));
 }
Example #3
0
 ArrayBuilder_ <wnd> _AllChildren(wnd wParent)
 {
     wParent.ThrowIfInvalid();
     return(EnumWindows2(EnumAPI.EnumChildWindows,
                         onlyVisible: 0 == (_flags & WCFlags.HiddenToo),
                         sortFirstVisible: true,
                         wParent: wParent,
                         directChild: 0 != (_flags & WCFlags.DirectChild)));
 }
Example #4
0
        static unsafe uint[,] _Pixels(RECT r, wnd w = default, bool printWindow = false)
        {
            using var mb = new MemoryBitmap(r.Width, r.Height);
            _CaptureToDC(mb, r, w, printWindow);
            var a = new uint[r.Height, r.Width];

            fixed(uint *p = a)
            {
                _GetPixelsFromDC(mb, r, p);
            }

            return(a);
        }
Example #5
0
            static wnd _WindowFromRect(ICResult r)
            {
                Thread.Sleep(25);                 //after the window is closed, sometimes need several ms until OS sets correct Z order. Until that may get different w1 and w2.
                wnd w1 = wnd.fromXY((r.rect.left, r.rect.top));
                wnd w2 = (r.image == null) ? w1 : wnd.fromXY((r.rect.right - 1, r.rect.bottom - 1));

                if (w2 != w1 || !_IsInClientArea(w1))
                {
                    wnd w3 = w1.Window, w4 = w2.Window;
                    w1 = (w4 == w3 && _IsInClientArea(w3)) ? w3 : default;
                }
                return(w1);

                bool _IsInClientArea(wnd w) => w.GetClientRect(out var rc, true) && rc.Contains(r.rect);
            }
Example #6
0
            /// <returns>0 Cancel, 1 OK, 2 Retry.</returns>
            public int Show(Bitmap img, ICFlags flags, RECT r)
            {
                _img    = img;
                _flags  = flags;
                _cursor = MouseCursor.Load(ResourceUtil.GetBytes("<Au>resources/red_cross_cursor.cur"), 32);
                _dpi    = screen.primary.Dpi;
                _w      = WndUtil.CreateWindow(_WndProc, true, "#32770", "Au.uiimage.CaptureUI", WS.POPUP | WS.VISIBLE, WSE.TOOLWINDOW | WSE.TOPMOST, r.left, r.top, r.Width, r.Height);
                _w.ActivateL();

                try {
                    while (Api.GetMessage(out var m) > 0 && m.message != Api.WM_APP)
                    {
                        switch (m.message)
                        {
                        case Api.WM_KEYDOWN when !_capturing:
                            switch ((KKey)(int)m.wParam)
                            {
                            case KKey.Escape: return(0);

                            case KKey.F3: return(2);
                            }
                            break;

                        case Api.WM_RBUTTONUP when m.hwnd == _w:
                            switch (popupMenu.showSimple("1 Retry\tF3|2 Cancel\tEsc", owner: _w))
                            {
                            case 1: return(2);

                            case 2: return(0);
                            }
                            break;
                        }
                        Api.DispatchMessage(m);
                    }
                }
                finally {
                    var w = _w; _w = default;
                    Api.DestroyWindow(w);
                }
                return(_res);
            }
Example #7
0
        static unsafe Bitmap _Capture(RECT r, wnd w = default, bool printWindow = false, GraphicsPath path = null)
        {
            //Transfer from screen/window DC to memory DC (does not work without this) and get pixels.

            //rejected: parameter includeNonClient (GetWindowDC).
            //	Nothing good. If in background, captures incorrect caption etc.
            //	If need nonclient part, better activate window and capture window rectangle from screen.

            //FUTURE: if w is DWM-scaled...

            using var mb = new MemoryBitmap(r.Width, r.Height);
            _CaptureToDC(mb, r, w, printWindow);

#if !true //with this code can allocate gigabytes without triggering GC
            var R = new Bitmap(r.Width, r.Height, PixelFormat.Format32bppRgb);
            try {
                var d = R.LockBits(new Rectangle(0, 0, r.Width, r.Height), ImageLockMode.ReadWrite, R.PixelFormat); //tested: fast, no copy
                try { _GetPixelsFromDC(mb, r, (uint *)d.Scan0, path); }
                finally { R.UnlockBits(d); }                                                                        //tested: fast, no copy
                return(R);
            }
            catch { R.Dispose(); throw; }
#elif !true //with this code GC should be OK, but isn't. Allocates large amount before starting to free. Also unsafe etc because uses Tag.
            var a = GC.AllocateUninitializedArray <uint>(r.Width * r.Height, pinned: true);
            fixed(uint *p = a)
            {
                _GetPixelsFromDC(mb, r, p, path);
                return(new Bitmap(r.Width, r.Height, r.Width * 4, PixelFormat.Format32bppRgb, (IntPtr)p)
                {
                    Tag = a
                });
            }
#else
            var R = new Bitmap(r.Width, r.Height, PixelFormat.Format32bppRgb);
            GC_.AddObjectMemoryPressure(R, r.Width * r.Height * 4);
            var d = R.LockBits(new(0, 0, r.Width, r.Height), ImageLockMode.ReadWrite, R.PixelFormat); //tested: fast, no copy
            try { _GetPixelsFromDC(mb, r, (uint *)d.Scan0, path); }
            finally { R.UnlockBits(d); }                                                              //tested: fast, no copy
            return(R);
#endif
        }
Example #8
0
 static void _CaptureToDC(MemoryBitmap mb, RECT r, wnd w = default, bool printWindow = false)
 {
     if (printWindow)
     {
         if (!Api.PrintWindow(w, mb.Hdc, Api.PW_CLIENTONLY | (osVersion.minWin8_1 ? Api.PW_RENDERFULLCONTENT : 0)))
         {
             w.ThrowNoNative("Failed to get pixels");
         }
     }
     else
     {
         using var dc = new WindowDC_(w);
         if (dc.Is0)
         {
             w.ThrowNoNative("Failed to get pixels");
         }
         uint rop = !w.Is0 ? Api.SRCCOPY : Api.SRCCOPY | Api.CAPTUREBLT;
         bool ok  = Api.BitBlt(mb.Hdc, 0, 0, r.Width, r.Height, dc, r.left, r.top, rop);
         Debug.Assert(ok);                 //the API fails only if a HDC is invalid
     }
 }
Example #9
0
            nint _WndProc(wnd w, int msg, nint wParam, nint lParam)
            {
                //WndUtil.PrintMsg(w, msg, wParam, lParam);

                switch (msg)
                {
                case Api.WM_NCDESTROY:
                    _img.Dispose();
                    _cursor?.Dispose();
                    if (_w != default)
                    {
                        _w = default;
                        _w.Post(Api.WM_APP);
                    }
                    break;

                case Api.WM_SETCURSOR:
                    Api.SetCursor(_cursor.Handle);
                    return(1);

                case Api.WM_ERASEBKGND:
                    return(default);

                case Api.WM_PAINT:
                    var dc = Api.BeginPaint(w, out var ps);
                    _WmPaint(dc);
                    Api.EndPaint(w, ps);
                    return(default);

                case Api.WM_MOUSEMOVE:
                    _WmMousemove(Math2.NintToPOINT(lParam));
                    break;

                case Api.WM_LBUTTONDOWN:
                    _WmLbuttondown(Math2.NintToPOINT(lParam));
                    break;
                }

                return(Api.DefWindowProc(w, msg, wParam, lParam));
            }
Example #10
0
        static Bitmap _Capture(List <POINT> outline, wnd w = default, bool printWindow = false)
        {
            int n = outline?.Count ?? 0;

            if (n == 0)
            {
                throw new ArgumentException();
            }
            if (n == 1)
            {
                return(_Capture(new RECT(outline[0].x, outline[0].y, 1, 1)));
            }

            using var path = _CreatePath(outline);
            RECT r = RECT.From(path.GetBounds(), false);

            if (r.NoArea)
            {
                path.Widen(Pens.Black);                 //will be transparent, but no exception. Difficult to make non-transparent line.
                r = RECT.From(path.GetBounds(), false);
            }
            return(_Capture(r, w, printWindow, path));
        }
Example #11
0
 /// <summary>
 /// Finds the specified child control, like <see cref="wnd.Child"/>.
 /// </summary>
 /// <returns>If found, returns <see cref="Result"/>, else default(wnd).</returns>
 /// <param name="wParent">Direct or indirect parent window. Can be top-level window or control.</param>
 /// <exception cref="AuWndException">Invalid <i>wParent</i>.</exception>
 /// <remarks>
 /// Functions <b>Find</b> and <b>Exists</b> differ only in their return types.
 /// </remarks>
 public wnd Find(wnd wParent) => Exists(wParent) ? Result : default;
Example #12
0
 /// <summary>
 /// Creates image from a rectangle of window client area pixels.
 /// </summary>
 /// <param name="w">Window or control.</param>
 /// <param name="r">Rectangle in <i>w</i> client area coordinates. Use <c>w.ClientRect</c> to get whole client area.</param>
 /// <param name="printWindow">Get pixels like with flag <see cref="IFFlags.PrintWindow"/>.</param>
 /// <exception cref="AuWndException">Invalid <i>w</i>.</exception>
 /// <exception cref="ArgumentException">Empty rectangle.</exception>
 /// <exception cref="AuException">Failed. For example there is not enough memory for bitmap of this size (width*height*4 bytes).</exception>
 /// <remarks>
 /// Unlike <see cref="capture(RECT)"/>, this overload gets pixels directly from window, not from screen. Like with flag <see cref="IFFlags.WindowDC"/> or <see cref="IFFlags.PrintWindow"/>. The window can be under other windows. The captured image can be different than displayed on screen.
 /// If the window is partially or completely transparent, captures its non-transparent view.
 /// If the window is DPI-scaled, captures its non-scaled view. And <i>r</i> must contain non-scaled coordinates.
 /// </remarks>
 public static Bitmap capture(wnd w, RECT r, bool printWindow = false)
 => _Capture(r, w.ThrowIfInvalid(), printWindow);
Example #13
0
        /// <returns>If found, sets <see cref="Result"/> and returns true. Else throws exception or returns false (if <i>waitS</i> negative).</returns>
        /// <inheritdoc cref="Find(wnd, double)"/>
        public bool Exists(wnd wParent, double waitS)
        {
            var r = waitS == 0d ? Exists(wParent) : wait.forCondition(waitS < 0 ? waitS : -waitS, () => Exists(wParent));

            return(r || double.IsNegative(waitS) ? r : throw new NotFoundException());
        }
Example #14
0
 /// <summary>
 /// Finds the specified control in a list of controls.
 /// Returns 0-based index, or -1 if not found.
 /// The <see cref="Result"/> property will be the control.
 /// </summary>
 /// <param name="a">List of controls, for example returned by <see cref="wnd.getwnd.Children"/>.</param>
 /// <param name="wParent">Direct or indirect parent window. Used only for flag DirectChild.</param>
 public int FindInList(IEnumerable <wnd> a, wnd wParent = default)
 {
     using var k = new WndList_(a);
     return(_FindInList(wParent, k));
 }
Example #15
0
        /// <summary>
        /// Creates image from a user-selected area of screen pixels. Or gets single pixel color, or just rectangle.
        /// Returns false if cancelled.
        /// </summary>
        /// <param name="result">Receives results.</param>
        /// <param name="flags"></param>
        /// <param name="owner">Owner window. Temporarily minimizes it.</param>
        /// <remarks>
        /// Gets all screen pixels and shows in a full-screen topmost window, where the user can select an area.
        /// </remarks>
        public static bool captureUI(out ICResult result, ICFlags flags = 0, AnyWnd owner = default)
        {
            result = default;

            switch (flags & (ICFlags.Image | ICFlags.Color | ICFlags.Rectangle))
            {
            case 0:
            case ICFlags.Image:
            case ICFlags.Color:
            case ICFlags.Rectangle: break;

            default: throw new ArgumentException();
            }

            wnd wTool = default;

            try {
                if (!owner.IsEmpty)
                {
                    wTool = owner.Hwnd;
                    wTool.ShowMinimized(noAnimation: true);
                    using (new inputBlocker(BIEvents.MouseClicks)) Au.wait.doEvents(300);                     //time for animations
                }

g1:
                RECT rs = screen.virtualScreen;
                //RECT rs = screen.primary.Rect; //for testing, to see Write output in other screen
                Bitmap bs;
                bool   windowPixels = flags.HasAny(ICFlags.WindowDC | ICFlags.PrintWindow);
                if (windowPixels)
                {
                    if (!_WaitForHotkey("Press F3 to select window from mouse pointer. Or Esc."))
                    {
                        return(false);
                    }
                    var w  = wnd.fromMouse(WXYFlags.NeedWindow);
                    var rc = w.ClientRect;
                    using var bw = capture(w, rc, flags.Has(ICFlags.PrintWindow));
                    bs           = new Bitmap(rs.Width, rs.Height);
                    using var g  = Graphics.FromImage(bs);
                    g.Clear(Color.Black);
                    w.MapClientToScreen(ref rc);
                    g.DrawImage(bw, rc.left - rs.left, rc.top - rs.top);
                }
                else
                {
                    bs = capture(rs);
                }

                var cw = new _CapturingWindow();
                switch (cw.Show(bs, flags, rs))
                {
                case 1: break;

                case 2:
                    if (!windowPixels && !_WaitForHotkey("Press F3 when ready for new screenshot. Or Esc."))
                    {
                        return(false);
                    }
                    goto g1;

                default: return(false);
                }

                var r = cw.Result;
                r.w    = _WindowFromRect(r);
                result = r;
            }
            finally {
                if (wTool.IsAlive)
                {
                    wTool.ShowNotMinimized();
                    wTool.ActivateL();
                }
            }
            return(true);
Example #16
0
 /// <summary>
 /// Finds all matching child controls, like <see cref="wnd.ChildAll"/>.
 /// Returns array containing 0 or more control handles as wnd.
 /// </summary>
 /// <param name="wParent">Direct or indirect parent window. Can be top-level window or control.</param>
 /// <exception cref="AuWndException">Invalid wParent.</exception>
 public wnd[] FindAll(wnd wParent)
 {
     return(_FindAll(new WndList_(_AllChildren(wParent)), wParent));
 }
Example #17
0
 /// <summary>
 /// Gets pixel colors from a rectangle in window client area.
 /// </summary>
 /// <returns>2-dimensional array [row, column] containing pixel colors in 0xAARRGGBB format. Alpha 0xFF.</returns>
 /// <param name="w">Window or control.</param>
 /// <param name="r">Rectangle in <i>w</i> client area coordinates. Use <c>w.ClientRect</c> to get whole client area.</param>
 /// <param name="printWindow">Get pixels like with flag <see cref="IFFlags.PrintWindow"/>.</param>
 /// <exception cref="AuWndException">Invalid <i>w</i>.</exception>
 /// <exception cref="ArgumentException">Empty rectangle.</exception>
 /// <exception cref="AuException">Failed. Probably there is not enough memory for bitmap of this size (width*height*4 bytes).</exception>
 /// <remarks>
 /// Unlike <see cref="getPixels(RECT)"/>, this overload gets pixels directly from window, not from screen. Like with flag <see cref="IFFlags.WindowDC"/> or <see cref="IFFlags.PrintWindow"/>. The window can be under other windows. The captured image can be different than displayed on screen.
 /// If the window is partially or completely transparent, captures its non-transparent view.
 /// If the window is DPI-scaled, captures its non-scaled view. And <i>r</i> must contain non-scaled coordinates.
 /// </remarks>
 public static uint[,] getPixels(wnd w, RECT r, bool printWindow = false)
 => _Pixels(r, w.ThrowIfInvalid(), printWindow);
Example #18
0
 /// <summary>
 /// Creates image from a non-rectangular area of window client area pixels.
 /// </summary>
 /// <param name="w">Window or control.</param>
 /// <param name="outline">The outline (shape) of the area in w client area coordinates. If single element, captures single pixel.</param>
 /// <param name="printWindow"></param>
 /// <exception cref="AuWndException">Invalid <i>w</i>.</exception>
 /// <exception cref="ArgumentException"><i>outline</i> is null or has 0 elements.</exception>
 /// <exception cref="AuException">Failed. Probably there is not enough memory for bitmap of this size.</exception>
 /// <remarks>More info: <see cref="capture(wnd, RECT, bool)"/>.</remarks>
 public static Bitmap capture(wnd w, List <POINT> outline, bool printWindow = false)
 {
     w.ThrowIfInvalid();
     return(_Capture(outline, w, printWindow));
 }
Example #19
0
 /// <returns>If found, sets <see cref="Result"/> and returns true, else false.</returns>
 /// <inheritdoc cref="Find(wnd)"/>
 public bool Exists(wnd wParent)
 {
     using var k = new WndList_(_AllChildren(wParent));
     return(_FindInList(wParent, k) >= 0);
 }
Example #20
0
 /// <summary>
 /// Finds all matching controls in a list of controls.
 /// Returns array containing 0 or more control handles as wnd.
 /// </summary>
 /// <param name="a">List of controls, for example returned by <see cref="wnd.getwnd.Children"/>.</param>
 /// <param name="wParent">Direct or indirect parent window. Used only for flag DirectChild.</param>
 public wnd[] FindAllInList(IEnumerable <wnd> a, wnd wParent = default)
 {
     return(_FindAll(new WndList_(a), wParent));
 }
Example #21
0
        /// <summary>
        /// Returns index of matching element or -1.
        /// Returns -1 if using getAll.
        /// </summary>
        /// <param name="wParent">Parent window. Can be default(wnd) if inList is true and no DirectChild flag and not using winforms name.</param>
        /// <param name="a">List of wnd. Does not dispose it.</param>
        /// <param name="getAll">If not null, calls it for all matching and returns -1.</param>
        int _FindInList(wnd wParent, WndList_ a, Action <wnd> getAll = null)
        {
            Result = default;
            if (a.Type == WndList_.ListType.None)
            {
                return(-1);
            }
            bool inList    = a.Type != WndList_.ListType.ArrayBuilder;
            int  skipCount = _skipCount;

            try {             //will need to dispose something
                for (int index = 0; a.Next(out wnd w); index++)
                {
                    if (w.Is0)
                    {
                        continue;
                    }

                    if (inList)                       //else the enum function did this
                    {
                        if (!_flags.Has(WCFlags.HiddenToo))
                        {
                            if (!w.IsVisibleIn_(wParent))
                            {
                                continue;
                            }
                        }

                        if (_flags.Has(WCFlags.DirectChild) && !wParent.Is0)
                        {
                            if (w.ParentGWL_ != wParent)
                            {
                                continue;
                            }
                        }
                    }

                    if (_id != null)
                    {
                        if (w.ControlId != _id.Value)
                        {
                            continue;
                        }
                    }

                    if (_className != null)
                    {
                        if (!_className.Match(w.ClassName))
                        {
                            continue;
                        }
                    }

                    if (_name != null)
                    {
                        string s;
                        switch (_nameIs)
                        {
                        case _NameIs.text:
                            s = w.ControlText;
                            break;

                        case _NameIs.elmName:
                            s = w.NameElm;
                            break;

                        case _NameIs.wfName:
                            if (_wfControls == null)
                            {
                                try {
                                    _wfControls = new WinformsControlNames(wParent.Is0 ? w : wParent);
                                }
                                catch (AuWndException) {                                 //invalid parent window
                                    return(-1);
                                }
                                catch (AuException e) {                                 //probably process of higher UAC integrity level
                                    print.warning($"Failed to get winforms control names. {e.Message}");
                                    return(-1);
                                }
                            }
                            s = _wfControls.GetControlName(w);
                            break;

                        //case _NameIs.label:
                        //	s = w.NameLabel;
                        //	break;
                        default:
                            s = w.Name;
                            break;
                        }

                        if (!_name.Match(s))
                        {
                            continue;
                        }
                    }

                    if (_also != null && !_also(w))
                    {
                        continue;
                    }

                    if (getAll != null)
                    {
                        getAll(w);
                        continue;
                    }

                    if (skipCount-- > 0)
                    {
                        continue;
                    }

                    Result = w;
                    return(index);
                }
            }
            finally {
                if (_wfControls != null)
                {
                    _wfControls.Dispose(); _wfControls = null;
                }
            }

            return(-1);
        }
Example #22
0
 /// <summary>
 /// Finds a top-level window and returns its handle as <b>wnd</b>.
 /// </summary>
 /// <returns>Returns <c>default(wnd)</c> if not found. See also: <see cref="Is0"/>.</returns>
 /// <param name="name">
 /// Name.
 /// Full, case-insensitive. Wildcard etc not supported.
 /// null means 'can be any'. "" means 'no name'.
 /// </param>
 /// <param name="cn">
 /// Class name.
 /// Full, case-insensitive. Wildcard etc not supported.
 /// null means 'can be any'. Cannot be "".
 /// </param>
 /// <param name="messageOnly">Search only message-only windows.</param>
 /// <param name="wAfter">If used, starts searching from the next window in the Z order.</param>
 /// <remarks>
 /// Calls API <msdn>FindWindowEx</msdn>.
 /// Faster than <see cref="find"/>, which uses API <msdn>EnumWindows</msdn>.
 /// Finds hidden windows too.
 /// Supports <see cref="lastError"/>.
 /// It is not recommended to use this function in a loop to enumerate windows. It would be unreliable because window positions in the Z order can be changed while enumerating. Also then it would be slower than <b>Find</b> and <b>FindAll</b>.
 /// </remarks>
 public static wnd findFast(string name = null, string cn = null, bool messageOnly = false, wnd wAfter = default)
 {
     return(Api.FindWindowEx(messageOnly ? SpecHWND.MESSAGE : default, wAfter, cn, name));
Example #23
0
 /// <summary>
 /// Finds the specified child control, like <see cref="wnd.Child"/>. Can wait and throw <b>NotFoundException</b>.
 /// </summary>
 /// <returns>If found, returns <see cref="Result"/>. Else throws exception or returns default(wnd) (if <i>waitS</i> negative).</returns>
 /// <param name="wParent">Direct or indirect parent window. Can be top-level window or control.</param>
 /// <param name="waitS">The wait timeout, seconds. If 0, does not wait. If negative, does not throw exception when not found.</param>
 /// <exception cref="AuWndException">Invalid <i>wParent</i>.</exception>
 /// <exception cref="NotFoundException" />
 /// <remarks>
 /// Functions <b>Find</b> and <b>Exists</b> differ only in their return types.
 /// </remarks>
 public wnd Find(wnd wParent, double waitS) => Exists(wParent, waitS) ? Result : default;