Ejemplo n.º 1
0
        /// <summary>
        /// Gets visible top-level window or control from point.
        /// </summary>
        /// <param name="p">
        /// Coordinates.
        /// Tip: To specify coordinates relative to the right, bottom, work area or a non-primary screen, use <see cref="Coord.Normalize"/>, like in the example.
        /// </param>
        /// <param name="flags"></param>
        /// <remarks>
        /// Unlike API <msdn>WindowFromPhysicalPoint</msdn> etc, this function: does not skip disabled controls; always skips transparent control like group box if a smaller sibling is there. All this is not true with flag Raw.
        /// </remarks>
        /// <example>
        /// Find window at 100 200.
        /// <code><![CDATA[
        /// var w = wnd.FromXY((100, 200), WXYFlags.NeedWindow);
        /// print.it(w);
        /// ]]></code>
        ///
        /// Find window or control at 50 from left and 100 from bottom of the work area.
        /// <code><![CDATA[
        /// var w = wnd.FromXY(Coord.Normalize(50, ^100, workArea: true));
        /// print.it(w);
        /// ]]></code>
        /// </example>
        public static wnd fromXY(POINT p, WXYFlags flags = 0)
        {
            bool needW = flags.Has(WXYFlags.NeedWindow);
            bool needC = flags.Has(WXYFlags.NeedControl);

            if (needW && needC)
            {
                throw new ArgumentException("", "flags");
            }

            if (flags.HasAny(WXYFlags.Raw | WXYFlags.NeedWindow))
            {
                var w = Api.WindowFromPoint(p);
                if (needW)
                {
                    return(w.Window);
                }
                return(!needC || w.IsChild ? w : default);
Ejemplo n.º 2
0
        //FUTURE: test when this process is not DPI-aware:
        //	Coordinate-related API on Win7 high DPI.
        //	AO location on Win10 with different DPI of monitors.

        /// <summary>
        /// Gets visible top-level window or control from point.
        /// </summary>
        /// <param name="p">
        /// Coordinates.
        /// Tip: To specify coordinates relative to the right, bottom, work area or a non-primary screen, use <see cref="Coord.Normalize"/>, like in the example.
        /// </param>
        /// <param name="flags"></param>
        /// <remarks>
        /// Alternatively can be used API <msdn>WindowFromPoint</msdn>, <msdn>ChildWindowFromPointEx</msdn> or <msdn>RealChildWindowFromPoint</msdn>, but all they have various limitations and are not very useful in automation scripts.
        /// This function gets non-transparent controls that are behind (in the Z order) transparent controls (group button, tab control etc); supports more control types than <msdn>RealChildWindowFromPoint</msdn>. Also does not skip disabled controls. All this is not true with flag Raw.
        /// This function is not very fast, probably 0.3 - 1 ms.
        /// </remarks>
        /// <example>
        /// Find window at 100 200.
        /// <code><![CDATA[
        /// var w = AWnd.FromXY((100, 200), WXYFlags.NeedWindow);
        /// AOutput.Write(w);
        /// ]]></code>
        ///
        /// Find window or control at 50 from left and 100 from bottom of the work area.
        /// <code><![CDATA[
        /// var w = AWnd.FromXY(Coord.Normalize(50, Coord.Reverse(100), true));
        /// AOutput.Write(w);
        /// ]]></code>
        /// </example>
        public static AWnd FromXY(POINT p, WXYFlags flags = 0)
        {
            bool needW = 0 != (flags & WXYFlags.NeedWindow);
            bool needC = 0 != (flags & WXYFlags.NeedControl);

            if (needW && needC)
            {
                throw new ArgumentException("", "flags");
            }
            AWnd w;

            if (needW)
            {
                w = Api.RealChildWindowFromPoint(Api.GetDesktopWindow(), p);                 //much faster than WindowFromPoint
                if (!w.HasExStyle(WS2.TRANSPARENT | WS2.LAYERED))
                {
                    return(w);                                        //fast. Windows that have both these styles are mouse-transparent.
                }
                return(Api.WindowFromPoint(p).Window);                //ChildWindowFromPointEx would be faster, but less reliable

                //info:
                //WindowFromPoint is the most reliable. It skips really transparent top-level windows (TL). Unfortunately it skips disabled controls (but not TL).
                //ChildWindowFromPointEx with CWP_SKIPINVISIBLE|CWP_SKIPTRANSPARENT skips all with WS_EX_TRANSPARENT, although without WS_EX_LAYERED they aren't actually transparent.
                //RealChildWindowFromPoint does not skip transparent TL. It works like ChildWindowFromPointEx(CWP_SKIPINVISIBLE).
                //None of the above API prefers a really visible control that is under a transparent part of a sibling control. RealChildWindowFromPoint does it only for group buttons, but not for tab controls etc.
                //All API skip windows that have a hole etc in window region at that point.
                //None of the API uses WM_NCHITTEST+HTTRANSPARENT. Tested only with TL of other processes.
                //AccessibleObjectFromPoint.get_Parent in most cases gets the most correct window/control, but it is dirty, unreliable and often very slow, because sends WM_GETOBJECT etc.
                //speed:
                //RealChildWindowFromPoint is the fastest.
                //ChildWindowFromPointEx is slower.
                //WindowFromPoint is 4 times slower; .Window does not make significantly slower.
                //AccessibleObjectFromPoint.get_Parent often is of RealChildWindowFromPoint speed, but often much slower than all others.
                //IUIAutomation.FromPoint very slow. Getting window handle from it is not easy, > 0.5 ms.
            }

            w = Api.WindowFromPoint(p);
            if (w.Is0)
            {
                return(w);
            }

            if (0 != (flags & WXYFlags.Raw))
            {
                if (needW)
                {
                    w = w.Window;
                }
                else if (needC && w == w.Window)
                {
                    w = default;
                }
                return(w);
            }

            AWnd t = w.Get.DirectParent;             //need parent because need to call realchildwindowfrompoint on it, else for group box would go through the slow way of detecting transparen control

            if (!t.Is0)
            {
                w = t;
            }

            t = w._ChildFromXY(p, false, true);
            if (t.Is0)
            {
                t = w;
            }
            if (needC && t == w)
            {
                return(default);