コード例 #1
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;
                }
コード例 #2
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);
 }