Ejemplo n.º 1
0
        /// <summary>
        /// Creates a WindowsGraphics object from a Graphics object.  Clipping and coordinate transforms
        /// are preserved.
        ///
        /// Notes:
        /// - The passed Graphics object cannot be used until the WindowsGraphics is disposed
        /// since it borrows the hdc from the Graphics object locking it.
        /// - Changes to the hdc using the WindowsGraphics object are not preserved into the Graphics object;
        /// the hdc is returned to the Graphics object intact.
        ///
        /// Some background about how Graphics uses the internal hdc when created from an existing one
        /// (mail from GillesK from GDI+ team):
        /// User has an HDC with a particular state:
        /// Graphics object gets created based on that HDC. We query the HDC for its state and apply it to the Graphics.
        /// At this stage, we do a SaveHDC and clear everything out of it.
        /// User calls GetHdc. We restore the HDC to the state it was in and give it to the user.
        /// User calls ReleaseHdc, we save the current state of the HDC and clear everything
        /// (so that the graphics state gets applied next time we use it).
        /// Next time the user calls GetHdc we give him back the state after the second ReleaseHdc.
        /// (But the state changes between the GetHdc and ReleaseHdc are not applied to the Graphics).
        /// Please note that this only applies the HDC created graphics, for Bitmap derived graphics, GetHdc creates a new DIBSection and
        /// things get a lot more complicated.
        /// </summary>
        public static WindowsGraphics FromGraphics(Graphics g)
        {
            ApplyGraphicsProperties properties = ApplyGraphicsProperties.All;

            return(WindowsGraphics.FromGraphics(g, properties));
        }
Ejemplo n.º 2
0
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            Debug.Assert(g != null, "null Graphics object.");

            WindowsRegion wr = null;

            float[] elements = null;

            Region clipRgn     = null;
            Matrix worldTransf = null;

            if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0 || (properties & ApplyGraphicsProperties.Clipping) != 0)
            {
                object[] data = g.GetContextInfo() as object[];

                if (data != null && data.Length == 2)
                {
                    clipRgn     = data[0] as Region;
                    worldTransf = data[1] as Matrix;
                }

                if (worldTransf != null)
                {
                    if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0)
                    {
                        elements = worldTransf.Elements;
                    }
                    worldTransf.Dispose();
                }

                if (clipRgn != null)
                {
                    if ((properties & ApplyGraphicsProperties.Clipping) != 0)
                    {
                        // We have to create the WindowsRegion and dipose the Region object before locking the Graphics object,
                        // in case of an unlikely exception before releasing the WindowsRegion, the finalizer will do it for us.
                        // (no try-finally block since this method is used frequently - perf).
                        // If the Graphics.Clip has not been set (Region.IsInfinite) we don't need to apply it to the DC.
                        if (!clipRgn.IsInfinite(g))
                        {
                            wr = WindowsRegion.FromRegion(clipRgn, g); // WindowsRegion will take ownership of the hRegion.
                        }
                    }
                    clipRgn.Dispose(); // Disposing the Region object doesn't destroy the hRegion.
                }
            }

            WindowsGraphics wg = WindowsGraphics.FromHdc(g.GetHdc()); // This locks the Graphics object.

            wg._graphics = g;

            // Apply transform and clip
            if (wr != null)
            {
                using (wr)
                {
                    // If the Graphics object was created from a native DC the actual clipping region is the intersection
                    // beteween the original DC clip region and the GDI+ one - for display Graphics it is the same as
                    // Graphics.VisibleClipBounds.
                    wg.DeviceContext.IntersectClip(wr);
                }
            }

            if (elements != null)
            {
                // elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset.
                wg.DeviceContext.TranslateTransform((int)elements[4], (int)elements[5]);
            }

            return(wg);
        }
Ejemplo n.º 3
0
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            Debug.Assert(g != null, "null Graphics object.");

            WindowsRegion?wr = null;

            PointF offset = default;

            if (properties != ApplyGraphicsProperties.None)
            {
                Region?clip = null;

#if NETCOREAPP3_1_OR_GREATER
                if (properties.HasFlag(ApplyGraphicsProperties.Clipping))
                {
                    g.GetContextInfo(out offset, out clip);
                }
                else
                {
                    g.GetContextInfo(out offset);
                }
#else
                Matrix?worldTransf = null;
                if (g.GetContextInfo() is object[] data && data.Length == 2)
                {
                    if (properties.HasFlag(ApplyGraphicsProperties.Clipping))
                    {
                        clip = data[0] as Region;
                    }
                    worldTransf = data[1] as Matrix;
                    if (worldTransf != null)
                    {
                        offset = worldTransf.Offset;
                    }
                }
#endif

                if (clip is not null)
                {
                    // We have to create the WindowsRegion and dipose the Region object before locking the Graphics object,
                    // in case of an unlikely exception before releasing the WindowsRegion, the finalizer will do it for us.
                    // (no try-finally block since this method is used frequently - perf).

                    // If clipping has not been set (Region.IsInfinite) GetContextInfo will return a null Region.

                    wr = WindowsRegion.FromRegion(clip, g); // WindowsRegion will take ownership of the hRegion.
                    clip.Dispose();                         // Disposing the Region object doesn't destroy the hRegion.
                }
            }

            WindowsGraphics wg = FromHdc(g.GetHdc()); // This locks the Graphics object.
            wg._graphics = g;

            // Apply transform and clip
            if (wr is not null)
            {
                using (wr)
                {
                    // If the Graphics object was created from a native DC the actual clipping region is the intersection
                    // beteween the original DC clip region and the GDI+ one - for display Graphics it is the same as
                    // Graphics.VisibleClipBounds.
                    wg.DeviceContext.IntersectClip(wr);
                }
            }

            if (offset != default)
            {
                // elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset.
                wg.DeviceContext.TranslateTransform((int)offset.X, (int)offset.Y);
            }

            return(wg);
        }