public void ControlPaint_DrawBorder_Dashed_Rendering()
        {
            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            using Graphics graphics = Graphics.FromHdc((IntPtr)emf.HDC);

            Rectangle bounds = new Rectangle(10, 10, 10, 10);

            ControlPaint.DrawBorder(graphics, bounds, Color.Pink, ButtonBorderStyle.Dashed);

            // For whatever reason GDI+ renders as polygons scaled 16x with a 1/16th world transform applied.
            Matrix3x2 oneSixteenth = Matrix3x2.CreateScale(0.0625f);

            // This is the default pen style GDI+ renders dotted lines with
            Gdi32.PS penStyle = Gdi32.PS.SOLID | Gdi32.PS.JOIN_ROUND | Gdi32.PS.COSMETIC | Gdi32.PS.ENDCAP_FLAT
                                | Gdi32.PS.JOIN_BEVEL | Gdi32.PS.GEOMETRIC;

            emf.Validate(
                state,
                Validate.PolyPolygon16(
                    new Rectangle(8, 8, 13, 13),
                    polyCount: 9,
                    State.Transform(oneSixteenth),
                    State.Pen(16, Color.Pink, penStyle),
                    State.Brush(Color.Pink, Gdi32.BS.SOLID)));
        }
        public void ControlPaint_DrawBorder_Inset_Rendering()
        {
            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            using Graphics graphics = Graphics.FromHdc((IntPtr)emf.HDC);

            Rectangle bounds = new Rectangle(10, 10, 10, 10);

            ControlPaint.DrawBorder(graphics, bounds, Color.Gray, ButtonBorderStyle.Inset);

            // For whatever reason GDI+ renders as polylines scaled 16x with a 1/16th world transform applied.
            // For test readability we'll transform the points from our coordinates to the logical coordinates.
            Matrix3x2 oneSixteenth = Matrix3x2.CreateScale(0.0625f);
            Matrix3x2 times16      = Matrix3x2.CreateScale(16.0f);

            // This is the default pen style GDI+ renders polylines with
            Gdi32.PS penStyle = Gdi32.PS.SOLID | Gdi32.PS.JOIN_ROUND | Gdi32.PS.COSMETIC | Gdi32.PS.ENDCAP_FLAT
                                | Gdi32.PS.JOIN_MITER | Gdi32.PS.GEOMETRIC;

            emf.Validate(
                state,
                // Top
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 10, 10, 19, 10),
                    State.Pen(16, ControlPaint.DarkDark(Color.Gray), penStyle),
                    State.Transform(oneSixteenth)),
                // Left
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 10, 10, 10, 19),
                    State.Pen(16, ControlPaint.DarkDark(Color.Gray), penStyle),
                    State.Transform(oneSixteenth)),
                // Bottom
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 10, 19, 19, 19),
                    State.Pen(16, ControlPaint.LightLight(Color.Gray), penStyle),
                    State.Transform(oneSixteenth)),
                // Right
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 19, 10, 19, 19),
                    State.Pen(16, ControlPaint.LightLight(Color.Gray), penStyle),
                    State.Transform(oneSixteenth)),
                // Top inset
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 11, 11, 18, 11),
                    State.Pen(16, ControlPaint.Light(Color.Gray), penStyle),
                    State.Transform(oneSixteenth)),
                // Left inset
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 11, 11, 11, 18),
                    State.Pen(16, ControlPaint.Light(Color.Gray), penStyle),
                    State.Transform(oneSixteenth))
                );
        }
        public unsafe void TextRenderer_DrawText_DefaultBackground_RendersTransparent(Func <IDeviceContext, Action> func)
        {
            using var emf = EmfScope.Create();
            DeviceContextState state = new DeviceContextState(emf);

            func(new HdcDeviceContextAdapter(emf)).Invoke();

            bool success = false;

            emf.EnumerateWithState((ref EmfRecord record, DeviceContextState state) =>
            {
                switch (record.Type)
                {
                case Gdi32.EMR.EXTTEXTOUTW:
                    var textOut = record.ExtTextOutWRecord;
                    Assert.Equal("Acrylic", textOut->emrtext.GetString().ToString());
                    Assert.Equal(Gdi32.MM.TEXT, state.MapMode);
                    Assert.Equal(Gdi32.BKMODE.TRANSPARENT, state.BackgroundMode);
                    Assert.Equal((COLORREF)Color.Blue, state.TextColor);
                    Assert.Equal(SystemFonts.DefaultFont.Name, state.SelectedFont);
                    success = true;
                    return(false);
                }
                return(true);
            },
                                   state);

            Assert.True(success, "Did not find the text out record.");
        }
Beispiel #4
0
        public void NumericUpDown_VisualStyles_off_BasicRendering_ControlDisabled()
        {
            if (Application.RenderWithVisualStyles)
            {
                return;
            }

            using var form   = new Form();
            using var upDown = new NumericUpDown();

            form.Controls.Add(upDown);

            // Check the disabled state
            upDown.Enabled = false;

            using var emfDisabled = new EmfScope();
            DeviceContextState state = new DeviceContextState(emfDisabled);

            upDown.PrintToMetafile(emfDisabled);

            emfDisabled.Validate(
                state,
                Validate.Rectangle(
                    new Rectangle(0, 0, 99, 18),
                    State.Pen(1, upDown.BackColor, Gdi32.PS.SOLID)),
                Validate.Rectangle(
                    new Rectangle(1, 1, 97, 16),
                    State.Pen(1, SystemColors.Control, Gdi32.PS.SOLID)),
                Validate.SkipType(Gdi32.EMR.STRETCHDIBITS),
                Validate.SkipType(Gdi32.EMR.STRETCHDIBITS),
                Validate.LineTo(
                    (0, 18), (16, 18),
                    State.Pen(1, upDown.BackColor, Gdi32.PS.SOLID)));
        }
        public unsafe void Button_FlatStyle_WithText_Rectangle()
        {
            using Button button = new Button
                  {
                      Text      = "Flat Style",
                      FlatStyle = FlatStyle.Flat,
                  };

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Rectangle bounds = button.Bounds;

            button.PrintToMetafile(emf);

            emf.Validate(
                state,
                Validate.SkipType(Gdi32.EMR.BITBLT),
                Validate.TextOut("Flat Style"),
                Validate.Rectangle(
                    new Rectangle(0, 0, button.Width - 1, button.Height - 1),
                    penColor: Color.Black,
                    penStyle: Gdi32.PS.ENDCAP_ROUND,
                    brushColor: Color.Empty,        // Color doesn't really matter as we're using a null brush
                    brushStyle: Gdi32.BS.NULL,      // Regressed in https://github.com/dotnet/winforms/pull/3667
                    rop2: Gdi32.R2.COPYPEN));
        }
        public unsafe void Button_FlatStyle_WithText_Rectangle()
        {
            using Button button = new Button
                  {
                      Text      = "Flat Style",
                      FlatStyle = FlatStyle.Flat,
                  };

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Rectangle bounds = button.Bounds;

            button.PrintToMetafile(emf);

            emf.Validate(
                state,
                Validate.SkipType(Gdi32.EMR.BITBLT),
                Validate.TextOut("Flat Style"),
                Validate.Rectangle(
                    new Rectangle(0, 0, button.Width - 1, button.Height - 1),
                    State.PenColor(Color.Black),
                    State.PenStyle(Gdi32.PS.ENDCAP_ROUND),
                    State.BrushStyle(Gdi32.BS.NULL),       // Regressed in https://github.com/dotnet/winforms/pull/3667
                    State.Rop2(Gdi32.R2.COPYPEN)));
        }
Beispiel #7
0
        public void TextBox_Disabled_PlaceholderText_RendersBackgroundCorrectly()
        {
            // Regression test for https://github.com/dotnet/winforms/issues/3706

            using Form form       = new Form();
            using TextBox textBox = new TextBox
                  {
                      Size            = new Size(80, 23),
                      PlaceholderText = "abc",
                      Enabled         = false
                  };
            form.Controls.Add(textBox);

            // Force the handle creation
            Assert.NotEqual(IntPtr.Zero, form.Handle);
            Assert.NotEqual(IntPtr.Zero, textBox.Handle);

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            textBox.TestAccessor().Dynamic.DrawPlaceholderText(emf.HDC);

            emf.Validate(
                state,
                Validate.TextOut(
                    "abc",
                    bounds: null,                                   // Don't care about the bounds for this test
                    State.BackgroundMode(Gdi32.BKMODE.TRANSPARENT)));
        }
 /// <summary>
 ///  Creates a metafile for the specified <see cref="Control"/>.
 /// </summary>
 internal static void CreateMetafile(
     this Control control,
     EmfScope emf,
     User32.PRF prf = User32.PRF.CHILDREN | User32.PRF.CLIENT)
 {
     User32.SendMessageW(control.Handle, User32.WM.PRINT, (IntPtr)emf.HDC, (IntPtr)prf);
 }
        public void NumericUpDown_BasicRendering()
        {
            using var form   = new Form();
            using var upDown = new NumericUpDown();

            form.Controls.Add(upDown);

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Assert.Equal(new Rectangle(0, 0, 120, 23), upDown.Bounds);

            // The rendering here is the "fill" for the background around the child edit control, which
            // doesn't match up to the main control's bounds.
            upDown.PrintToMetafile(emf);
            emf.Validate(
                state,
                Validate.Rectangle(
                    new Rectangle(1, 1, 98, 17),
                    State.Pen(2, upDown.BackColor, Gdi32.PS.SOLID)));

            // Printing the main control doesn't get the redraw for the child controls on the first render,
            // directly hitting the up/down button subcontrol.

            using var emfButtons = new EmfScope();
            state = new DeviceContextState(emfButtons);
            upDown.Controls[0].PrintToMetafile(emfButtons);

            // This is the "fill" line under the up/down arrows
            emfButtons.Validate(
                state,
                Validate.SkipType(Gdi32.EMR.STRETCHDIBITS),
                Validate.SkipType(Gdi32.EMR.STRETCHDIBITS),
                Validate.LineTo(
                    (0, 18), (16, 18),
                    State.Pen(1, upDown.BackColor, Gdi32.PS.SOLID)));

            // Now check the disabled state

            upDown.Enabled = false;

            using var emfDisabled = new EmfScope();
            state = new DeviceContextState(emfDisabled);
            upDown.PrintToMetafile(emfDisabled);

            emfDisabled.Validate(
                state,
                Validate.Rectangle(
                    new Rectangle(0, 0, 99, 18),
                    State.Pen(1, upDown.BackColor, Gdi32.PS.SOLID)),
                Validate.Rectangle(
                    new Rectangle(1, 1, 97, 16),
                    State.Pen(1, SystemColors.Control, Gdi32.PS.SOLID)),
                Validate.SkipType(Gdi32.EMR.STRETCHDIBITS),
                Validate.SkipType(Gdi32.EMR.STRETCHDIBITS),
                Validate.LineTo(
                    (0, 18), (16, 18),
                    State.Pen(1, upDown.BackColor, Gdi32.PS.SOLID)));
        }
        public unsafe void CaptureButtonOnForm()
        {
            using Form form     = new Form();
            using Button button = new Button();
            form.Controls.Add(button);

            using var emf = new EmfScope();
            form.PrintToMetafile(emf);

            var details = emf.RecordsToString();
        }
Beispiel #11
0
        public void PropertyGridView_Render_Labels_Values_Correctly()
        {
            Point pt = default(Point);

            using PropertyGrid propertyGrid = new()
                  {
                      SelectedObject = pt,
                      Size           = new(300, 200),
                      Visible        = true
                  };

            PropertyGridView propertyGridView = propertyGrid.TestAccessor().GridView;

            // For us to be able to render PropertyGridView and its values
            // PropertyGrid must be visible and have a valid handle.
            // To be Visible is must either be visible (we don't want this in tests) or
            // have no parent - so we can't add it to another control (such as a form).
            propertyGrid.CreateControl();

            using var emf = new EmfScope();
            DeviceContextState state = new(emf);

            propertyGridView.PrintToMetafile(emf);

            // Only care about text: labels and values
            emf.Validate(
                state,

                // Category: Misc
                Validate.SkipTo(
                    Validate.TextOut("Misc", new(25, 4, 25, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),

                // Value for "X"
                Validate.SkipTo(
                    Validate.TextOut(" ", new(145, 22, 5, 14))), // blank??
                Validate.SkipTo(
                    Validate.TextOut(pt.X.ToString(), new(145, 22, 5, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),
                // Label for "X"
                Validate.SkipTo(
                    Validate.TextOut(nameof(Point.X), new(25, 23, 6, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),

                // Value for "Y"
                Validate.SkipTo(
                    Validate.TextOut(" ", new(145, 41, 5, 14))), // blank??
                Validate.SkipTo(
                    Validate.TextOut(pt.Y.ToString(), new(145, 41, 5, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),
                // Label for "Y"
                Validate.SkipTo(
                    Validate.TextOut(nameof(Point.Y), new(25, 42, 6, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),

                Validate.SkipAll());
        }
    }
        public unsafe void Button_VisualStyles_on_Default_WithText_LineDrawing()
        {
            if (!Application.RenderWithVisualStyles)
            {
                return;
            }

            using Button button = new Button { Text = "Hello" };
            using var emf       = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Rectangle bounds = button.Bounds;

            button.PrintToMetafile(emf);

            /*
             *
             * [ENHMETAHEADER] Bounds: {0, 0, 74, 22 (LTRB)} Device Size: {Width=3840, Height=2160} Header Size: 108
             * [EMRINTERSECTCLIPRECT] RECT: {0, 0, 75, 23 (LTRB)}
             * [EMRSETVIEWPORTORGEX] Point: {X=0,Y=0}
             * [EMRCREATEBRUSHINDIRECT] Index: 1 Style: SOLID Color: [R=240, G=240, B=240] (COLOR_MENU, COLOR_BTNFACE, COLOR_MENUBAR)
             * [EMRSELECTOBJECT] Index: 1
             * [EMRBITBLT] Bounds: {0, 0, -1, -1 (LTRB)} Destination: {0, 0, 120, 0 (LTRB)} Rop: PATCOPY Source DC Color: [R=0, G=0, B=0] (COLOR_BACKGROUND, COLOR_MENUTEXT, COLOR_WINDOWTEXT, COLOR_CAPTIONTEXT, COLOR_BTNTEXT, COLOR_INACTIVECAPTIONTEXT, COLOR_INFOTEXT)
             * [EMRSELECTOBJECT] StockObject: WHITE_BRUSH
             * [EMRDELETEOBJECT] Index: 1
             * [EMRCREATEBRUSHINDIRECT] Index: 1 Style: SOLID Color: [R=240, G=240, B=240] (COLOR_MENU, COLOR_BTNFACE, COLOR_MENUBAR)
             * [EMRSELECTOBJECT] Index: 1
             * [EMRBITBLT] Bounds: {0, 0, -1, -1 (LTRB)} Destination: {0, 0, 120, 0 (LTRB)} Rop: PATCOPY Source DC Color: [R=0, G=0, B=0] (COLOR_BACKGROUND, COLOR_MENUTEXT, COLOR_WINDOWTEXT, COLOR_CAPTIONTEXT, COLOR_BTNTEXT, COLOR_INACTIVECAPTIONTEXT, COLOR_INFOTEXT)
             * [EMRSELECTOBJECT] StockObject: WHITE_BRUSH
             * [EMRDELETEOBJECT] Index: 1
             * [EMRSETVIEWPORTORGEX] Point: {X=0,Y=0}
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 75, 23 (LTRB)} Rects: 1 Rect index 0: {0, 0, 75, 23 (LTRB)}
             * [EMRINTERSECTCLIPRECT] RECT: {0, 0, 75, 23 (LTRB)}
             * [EMRALPHABLEND]
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 75, 23 (LTRB)} Rects: 1 Rect index 0: {0, 0, 75, 23 (LTRB)}
             * [EMRSAVEDC]
             * [EMRSETICMMODE] Mode: ICM_OFF
             * [EMREXTSELECTCLIPRGN] Mode: Set Default
             * [EMRSETBKMODE] Mode: BKMODE_TRANSPARENT
             * [EMRSETTEXTCOLOR] Color: [R=0, G=0, B=0] (COLOR_BACKGROUND, COLOR_MENUTEXT, COLOR_WINDOWTEXT, COLOR_CAPTIONTEXT, COLOR_BTNTEXT, COLOR_INACTIVECAPTIONTEXT, COLOR_INFOTEXT)
             * [EMRSETTEXTALIGN] Mode: TA_BASELINE
             * [EMREXTCREATEFONTINDIRECTW] Index: 1 FaceName: 'Segoe UI' Height: -12 Weight: FW_NORMAL
             * [EMRSELECTOBJECT] Index: 1
             * [EMREXTTEXTOUTW] Bounds: {24, 4, 51, 18 (LTRB)} Text: 'Hello'
             * [EMRSELECTOBJECT] StockObject: SYSTEM_FONT
             * [EMRRESTOREDC] Index: -1
             * [EMRDELETEOBJECT] Index: 1
             * [EMREOF]
             *
             */
        }
Beispiel #13
0
        public unsafe void TextRenderer_DrawText_DefaultBackground_RendersTransparent(Func <IDeviceContext, Action> func)
        {
            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            func(new HdcDeviceContextAdapter(emf)).Invoke();

            emf.Validate(
                state,
                Validate.TextOut(
                    "Acrylic",
                    Color.Blue,
                    fontFace: SystemFonts.DefaultFont.Name));
        }
Beispiel #14
0
        public unsafe void TextRenderer_DrawText_DefaultBackground_RendersTransparent(Func <IDeviceContext, Action> func)
        {
            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            func(new HdcDeviceContextAdapter(emf)).Invoke();

            emf.Validate(
                state,
                Validate.TextOut(
                    "Acrylic",
                    bounds: null,                                   // Don't care about the bounds for this test
                    State.FontFace(SystemFonts.DefaultFont.Name),
                    State.TextColor(Color.Blue)));
        }
Beispiel #15
0
        public void ToolStrip_RendersBackgroundCorrectly()
        {
            using Form form           = new Form();
            using ToolStrip toolStrip = new ToolStrip
                  {
                      BackColor = Color.Blue,
                      Size      = new Size(200, 38)
                  };
            form.Controls.Add(toolStrip);

            // Force the handle creation
            _ = form.Handle;
            _ = toolStrip.Handle;
            form.PerformLayout();

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Rectangle      bounds = toolStrip.Bounds;
            PaintEventArgs e      = new PaintEventArgs(emf, bounds);

            toolStrip.TestAccessor().Dynamic.OnPaintBackground(e);

            Rectangle bitBltBounds = new Rectangle(bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);

            RECT[] expectedRects = new RECT[]
            {
                new RECT(0, 0, 1, 1),
                new RECT(bounds.Width - 3, 0, bounds.Width, 1),
                new RECT(bounds.Width - 1, 1, bounds.Width, 3),
                new RECT(0, bounds.Height - 2, 1, bounds.Height - 1),
                new RECT(bounds.Width - 1, bounds.Height - 2, bounds.Width, bounds.Height - 1),
                new RECT(0, bounds.Height - 1, 2, bounds.Height),
                new RECT(bounds.Width - 2, bounds.Height - 1, bounds.Width, bounds.Height)
            };

            emf.Validate(
                state,
                Validate.BitBltValidator(
                    bitBltBounds,
                    State.BrushColor(Color.Blue)),
                Validate.BitBltValidator(
                    bitBltBounds,
                    State.BrushColor(form.BackColor),
                    State.Clipping(expectedRects)));

            var details = emf.RecordsToString();
        }
        public unsafe void CaptureButton()
        {
            using Button button = new Button();

            using var emf = new EmfScope();
            button.PrintToMetafile(emf);

            var types   = new List <Gdi32.EMR>();
            var details = new List <string>();

            emf.Enumerate((ref EmfRecord record) =>
            {
                types.Add(record.Type);
                details.Add(record.ToString());
                return(true);
            });
        }
        public void ControlPaint_DrawBorder_Solid_Rendering()
        {
            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            using Graphics graphics = Graphics.FromHdc((IntPtr)emf.HDC);

            Rectangle bounds = new Rectangle(10, 10, 10, 10);

            ControlPaint.DrawBorder(graphics, bounds, Color.Blue, ButtonBorderStyle.Solid);

            emf.Validate(
                state,
                Validate.Rectangle(
                    // We match the legacy GDI+ rendering, where the right and bottom are drawn inside the bounds
                    new Rectangle(10, 10, 9, 9),
                    State.Pen(1, Color.Blue, Gdi32.PS.SOLID)));
        }
        public unsafe void Button_VisualStyles_off_Default_WithText_LineDrawing()
        {
            if (Application.RenderWithVisualStyles)
            {
                return;
            }

            using Button button = new Button { Text = "Hello" };
            using var emf       = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Rectangle bounds = button.Bounds;

            button.PrintToMetafile(emf);

            emf.Validate(
                state,
                Validate.SkipType(Gdi32.EMR.BITBLT),
                Validate.TextOut("Hello"),
                Validate.LineTo(
                    (bounds.Right - 1, 0), (0, 0),
                    State.PenColor(SystemColors.ControlLightLight)),
                Validate.LineTo(
                    (0, 0), (0, bounds.Bottom - 1),
                    State.PenColor(SystemColors.ControlLightLight)),
                Validate.LineTo(
                    (0, bounds.Bottom - 1), (bounds.Right - 1, bounds.Bottom - 1),
                    State.PenColor(SystemColors.ControlDarkDark)),
                Validate.LineTo(
                    (bounds.Right - 1, bounds.Bottom - 1), (bounds.Right - 1, -1),
                    State.PenColor(SystemColors.ControlDarkDark)),
                Validate.LineTo(
                    (bounds.Right - 2, 1), (1, 1),
                    State.PenColor(SystemColors.Control)),
                Validate.LineTo(
                    (1, 1), (1, bounds.Bottom - 2),
                    State.PenColor(SystemColors.Control)),
                Validate.LineTo(
                    (1, bounds.Bottom - 2), (bounds.Right - 2, bounds.Bottom - 2),
                    State.PenColor(SystemColors.ControlDark)),
                Validate.LineTo(
                    (bounds.Right - 2, bounds.Bottom - 2), (bounds.Right - 2, 0),
                    State.PenColor(SystemColors.ControlDark)));
        }
        public unsafe void CaptureButtonOnForm()
        {
            using Form form     = new Form();
            using Button button = new Button();
            form.Controls.Add(button);

            using var emf = EmfScope.Create();
            form.CreateMetafile(emf);

            var types   = new List <Gdi32.EMR>();
            var details = new List <string>();

            emf.Enumerate((ref EmfRecord record) =>
            {
                types.Add(record.Type);
                details.Add(record.ToString());
                return(true);
            });
        }
        public unsafe void Button_VisualStyles_on_Default_LineDrawing()
        {
            if (!Application.RenderWithVisualStyles)
            {
                return;
            }

            using Button button = new Button();
            using var emf       = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Rectangle bounds = button.Bounds;

            button.PrintToMetafile(emf);

            /*
             *
             * [ENHMETAHEADER] Bounds: {0, 0, 74, 22 (LTRB)} Device Size: {Width=1024, Height=768} Header Size: 108
             * [EMRINTERSECTCLIPRECT] RECT: {0, 0, 75, 23 (LTRB)}
             * [EMRSETVIEWPORTORGEX] Point: {X=0,Y=0}
             * [EMRCREATEBRUSHINDIRECT] Index: 1 Style: SOLID Color: [R=240, G=240, B=240] (COLOR_MENU, COLOR_BTNFACE, COLOR_MENUBAR)
             * [EMRSELECTOBJECT] Index: 1
             * [EMRBITBLT] Bounds: {0, 0, -1, -1 (LTRB)} Destination: {0, 0, 120, 0 (LTRB)} Rop: PATCOPY Source DC Color: [R=0, G=0, B=0] (COLOR_BACKGROUND, COLOR_MENUTEXT, COLOR_WINDOWTEXT, COLOR_CAPTIONTEXT, COLOR_BTNTEXT, COLOR_INACTIVECAPTIONTEXT, COLOR_INFOTEXT)
             * [EMRSELECTOBJECT] StockObject: WHITE_BRUSH
             * [EMRDELETEOBJECT] Index: 1
             * [EMRCREATEBRUSHINDIRECT] Index: 1 Style: SOLID Color: [R=240, G=240, B=240] (COLOR_MENU, COLOR_BTNFACE, COLOR_MENUBAR)
             * [EMRSELECTOBJECT] Index: 1
             * [EMRBITBLT] Bounds: {0, 0, -1, -1 (LTRB)} Destination: {0, 0, 120, 0 (LTRB)} Rop: PATCOPY Source DC Color: [R=0, G=0, B=0] (COLOR_BACKGROUND, COLOR_MENUTEXT, COLOR_WINDOWTEXT, COLOR_CAPTIONTEXT, COLOR_BTNTEXT, COLOR_INACTIVECAPTIONTEXT, COLOR_INFOTEXT)
             * [EMRSELECTOBJECT] StockObject: WHITE_BRUSH
             * [EMRDELETEOBJECT] Index: 1
             * [EMRSETVIEWPORTORGEX] Point: {X=0,Y=0}
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 75, 23 (LTRB)} Rects: 1 Rect index 0: {0, 0, 75, 23 (LTRB)}
             * [EMRINTERSECTCLIPRECT] RECT: {0, 0, 75, 23 (LTRB)}
             * [EMRALPHABLEND]
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 75, 23 (LTRB)} Rects: 1 Rect index 0: {0, 0, 75, 23 (LTRB)}
             * [EMREOF]
             *
             */
        }
Beispiel #21
0
        public unsafe void Button_Default_LineDrawing()
        {
            using Button button = new Button();
            using var emf       = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Rectangle bounds = button.Bounds;

            button.PrintToMetafile(emf);

            emf.Validate(
                state,
                Validate.Repeat(Validate.SkipType(Gdi32.EMR.BITBLT), 2),
                Validate.LineTo((bounds.Right - 1, 0), (0, 0), SystemColors.ControlLightLight),
                Validate.LineTo((0, 0), (0, bounds.Bottom - 1), SystemColors.ControlLightLight),
                Validate.LineTo((0, bounds.Bottom - 1), (bounds.Right - 1, bounds.Bottom - 1), SystemColors.ControlDarkDark),
                Validate.LineTo((bounds.Right - 1, bounds.Bottom - 1), (bounds.Right - 1, -1), SystemColors.ControlDarkDark),
                Validate.LineTo((bounds.Right - 2, 1), (1, 1), SystemColors.Control),
                Validate.LineTo((1, 1), (1, bounds.Bottom - 2), SystemColors.Control),
                Validate.LineTo((1, bounds.Bottom - 2), (bounds.Right - 2, bounds.Bottom - 2), SystemColors.ControlDark),
                Validate.LineTo((bounds.Right - 2, bounds.Bottom - 2), (bounds.Right - 2, 0), SystemColors.ControlDark));
        }
        public void StatusStrip_RendersBorderCorrectly()
        {
            using Form form = new Form();
            using StatusStrip statusStrip = new StatusStrip
                  {
                      BackColor  = Color.Blue,
                      SizingGrip = false,
                      Renderer   = new ToolStripProfessionalRenderer(new CustomColorTable()),
                      Size       = new Size(200, 38)
                  };
            form.Controls.Add(statusStrip);

            // Force the handle creation
            Assert.NotEqual(IntPtr.Zero, form.Handle);
            Assert.NotEqual(IntPtr.Zero, statusStrip.Handle);

            // Create an Enhance Metafile into which we will render the control
            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            // Render the control
            statusStrip.PrintToMetafile(emf);

            Rectangle bounds         = statusStrip.Bounds;
            Rectangle bitBltBounds   = new Rectangle(bounds.X, 0, bounds.Width - 1, bounds.Height - 1);
            Rectangle polylineBounds = new Rectangle(bounds.X, 0, bounds.Width - 1, 15);

            // This is the default pen style GDI+ renders polylines with
            Gdi32.PS penStyle = Gdi32.PS.SOLID | Gdi32.PS.JOIN_ROUND | Gdi32.PS.COSMETIC | Gdi32.PS.ENDCAP_FLAT | Gdi32.PS.JOIN_MITER | Gdi32.PS.GEOMETRIC;

            emf.Validate(
                state,
                Validate.BitBltValidator(bitBltBounds, State.BrushColor(Color.Blue)),
                Validate.Polyline16(polylineBounds, null, State.Pen(16, Color.Green, penStyle))
                );

            var details = emf.RecordsToString();
        }
        public void DataGridView_DefaultCellStyles_Rendering()
        {
            #region DataGridView setup

            using Font formFont1 = new Font("Times New Roman", 12F, FontStyle.Regular);
            using Form form      = new Form
                  {
                      Font = formFont1,
                      Size = new Size(700, 200)
                  };

            using Font customCellStyleFont    = new Font("Tahoma", 8.25F, FontStyle.Regular);
            using Font customColumnHeaderFont = new Font("Consolas", 14F, FontStyle.Italic);
            using Font customRowHeaderFont    = new Font("Arial", 9F, FontStyle.Bold);

            var defaultCellStyle = new DataGridViewCellStyle
            {
                Font = customCellStyleFont,

                // We must supply a completely initialised instance, else we'd be receiving a copy
                // refer to DefaultCellStyle implementation

                Alignment          = DataGridViewContentAlignment.MiddleLeft,
                BackColor          = SystemColors.Info,
                ForeColor          = Color.Maroon,
                SelectionBackColor = SystemColors.Highlight,
                SelectionForeColor = SystemColors.HighlightText,
                WrapMode           = DataGridViewTriState.False
            };

            using DataGridView dataGridView = new DataGridView
                  {
                      DefaultCellStyle = defaultCellStyle,
                      ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle { Font = customColumnHeaderFont },
                      RowHeadersDefaultCellStyle    = new DataGridViewCellStyle { Font = customRowHeaderFont },

                      Dock = DockStyle.Fill,
                      ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize,
                  };

            var column1 = new DataGridViewTextBoxColumn {
                HeaderText = "Style"
            };
            var column2 = new DataGridViewTextBoxColumn {
                HeaderText = "Font"
            };
            dataGridView.Columns.AddRange(new[] { column1, column2, });
            dataGridView.Rows.Add(nameof(DataGridView.DefaultCellStyle), customCellStyleFont.ToString());
            dataGridView.Rows.Add(nameof(DataGridView.ColumnHeadersDefaultCellStyle), customColumnHeaderFont.ToString());
            dataGridView.Rows.Add(nameof(DataGridView.RowHeadersDefaultCellStyle), customRowHeaderFont.ToString());
            for (int i = 0; i < dataGridView.Rows.Count; i++)
            {
                dataGridView.Rows[i].HeaderCell.Value = $"Row {i + 1}";
            }

            dataGridView.RowHeadersWidth = 100;

            Assert.Same(customCellStyleFont, dataGridView.DefaultCellStyle.Font);
            Assert.Same(customColumnHeaderFont, dataGridView.ColumnHeadersDefaultCellStyle.Font);
            Assert.Same(customRowHeaderFont, dataGridView.RowHeadersDefaultCellStyle.Font);

            // Add the datagridview to the form, this will trigger Font change via OnFontChanged
            form.Controls.Add(dataGridView);

            #endregion

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Assert.NotEqual(IntPtr.Zero, dataGridView.Handle);
            dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

            dataGridView.PrintToMetafile(emf);

            // We only care about font styles, nothing else
            emf.Validate(
                state,

                // Column headers
                Validate.SkipTo(
                    Validate.TextOut(column1.HeaderText, stateValidators: State.FontFace(customColumnHeaderFont.Name))),
                Validate.SkipTo(
                    Validate.TextOut(column2.HeaderText, stateValidators: State.FontFace(customColumnHeaderFont.Name))),

                // Row1
                Validate.SkipTo(
                    Validate.TextOut("Row 1", stateValidators: State.FontFace(customRowHeaderFont.Name))),
                Validate.SkipTo(
                    Validate.TextOut(nameof(DataGridView.DefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))),
                Validate.SkipTo(
                    Validate.TextOut(customCellStyleFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))),

                // Row2
                Validate.SkipTo(
                    Validate.TextOut("Row 2", stateValidators: State.FontFace(customRowHeaderFont.Name))),
                Validate.SkipTo(
                    Validate.TextOut(nameof(DataGridView.ColumnHeadersDefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))),
                Validate.SkipTo(
                    Validate.TextOut(customColumnHeaderFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))),

                // Row3
                Validate.SkipTo(
                    Validate.TextOut("Row 3", stateValidators: State.FontFace(customRowHeaderFont.Name))),
                Validate.SkipTo(
                    Validate.TextOut(nameof(DataGridView.RowHeadersDefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))),
                Validate.SkipTo(
                    Validate.TextOut(customRowHeaderFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))),

                Validate.SkipAll());
        }
        public void DataGridView_GridColor_Rendering()
        {
            using Form form = new Form();

            // Only want to render one cell to validate
            using var dataGrid = new DataGridView
                  {
                      GridColor            = Color.Blue,
                      ColumnCount          = 1,
                      RowCount             = 1,
                      ColumnHeadersVisible = false,
                      RowHeadersVisible    = false
                  };

            form.Controls.Add(dataGrid);

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            dataGrid.PrintToMetafile(emf);

            Assert.Equal(new Rectangle(0, 0, 240, 150), dataGrid.Bounds);
            Assert.Equal(new Size(100, 25), dataGrid[0, 0].Size);

            Rectangle bounds = dataGrid.Bounds;

            // For whatever reason GDI+ renders as polylines scaled 16x with a 1/16th world transform applied.
            // For test readability we'll transform the points from our coordinates to the logical coordinates.
            Matrix3x2 oneSixteenth = Matrix3x2.CreateScale(0.0625f);
            Matrix3x2 times16      = Matrix3x2.CreateScale(16.0f);

            // This is the default pen style GDI+ renders with
            Gdi32.PS penStyle = Gdi32.PS.SOLID | Gdi32.PS.JOIN_ROUND | Gdi32.PS.COSMETIC | Gdi32.PS.ENDCAP_FLAT
                                | Gdi32.PS.JOIN_MITER | Gdi32.PS.GEOMETRIC;

            // Don't really care about the bounds, just the actual shapes/lines
            emf.Validate(
                state,
                // The datagrid background
                Validate.Polygon16(
                    bounds: null,
                    PointArray(times16, 1, 1, 1, 149, 239, 149, 239, 1, 1, 1),
                    State.Pen(1, Color.Empty, Gdi32.PS.NULL),
                    State.Brush(SystemColors.ButtonShadow, Gdi32.BS.SOLID),
                    State.Transform(oneSixteenth)),
                // Left cell border
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 1, 1, 1, 26),
                    State.Pen(16, Color.Blue, penStyle),
                    State.Transform(oneSixteenth)),
                // Right cell border
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 101, 1, 101, 26),
                    State.Pen(16, Color.Blue, penStyle),
                    State.Transform(oneSixteenth)),
                // Top cell border
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 1, 1, 101, 1),
                    State.Pen(16, Color.Blue, penStyle),
                    State.Transform(oneSixteenth)),
                // Bottom cell border
                Validate.Polyline16(
                    bounds: null,
                    PointArray(times16, 1, 26, 101, 26),
                    State.Pen(16, Color.Blue, penStyle),
                    State.Transform(oneSixteenth)),
                // Cell background
                Validate.Polygon16(
                    bounds: null,
                    PointArray(times16, 2, 2, 2, 26, 101, 26, 101, 2, 2, 2),
                    State.Pen(1, Color.Empty, Gdi32.PS.NULL),
                    State.Brush(SystemColors.ButtonHighlight, Gdi32.BS.SOLID),
                    State.Transform(oneSixteenth)),
                // Datagrid border
                Validate.Polygon16(
                    bounds: null,
                    PointArray(times16, 0, 0, 239, 0, 239, 149, 0, 149),
                    State.Pen(16, SystemColors.Desktop, penStyle),
                    State.Brush(Color.Empty, Gdi32.BS.NULL),
                    State.Transform(oneSixteenth)));
        }
Beispiel #25
0
        public void NumericUpDown_VisualStyles_on_BasicRendering()
        {
            if (!Application.RenderWithVisualStyles)
            {
                return;
            }

            using var form   = new Form();
            using var upDown = new NumericUpDown();

            form.Controls.Add(upDown);

            using var emf = new EmfScope();
            DeviceContextState state = new DeviceContextState(emf);

            Assert.Equal(new Rectangle(0, 0, 120, 23), upDown.Bounds);

            // The rendering here is the "fill" for the background around the child edit control, which
            // doesn't match up to the main control's bounds.
            upDown.PrintToMetafile(emf);

            /*
             *
             * [ENHMETAHEADER] Bounds: {0, 0, 119, 22 (LTRB)} Device Size: {Width=3840, Height=2160} Header Size: 108
             * [EMRSETBKCOLOR] Color: [R=171, G=173, B=179]
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, 0, 22 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, 0, 0 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 22, 0, 22 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMRSETBKCOLOR] Color: [R=171, G=173, B=179]
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, 0, 0 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {119, 0, 119, 0 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, 119, 0 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMRSETBKCOLOR] Color: [R=171, G=173, B=179]
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {119, 0, 119, 22 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {119, 0, 119, 0 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {119, 22, 119, 22 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMRSETBKCOLOR] Color: [R=171, G=173, B=179]
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 22, 0, 22 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {119, 22, 119, 22 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 22, 119, 22 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMREXTTEXTOUTW] Bounds: {0, 0, -1, -1 (LTRB)} Text: ''
             * [EMRSETBKCOLOR] Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMRCREATEPEN] Index: 1 Style: ENDCAP_ROUND Width: {X=1,Y=0} Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMRSELECTOBJECT] Index: 1
             * [EMRSETROP2] Mode: R2_COPYPEN
             * [EMRSELECTOBJECT] StockObject: NULL_BRUSH
             * [EMRRECTANGLE] RECT: {1, 1, 102, 21 (LTRB)}
             * [EMRSELECTOBJECT] StockObject: WHITE_BRUSH
             * [EMRSELECTOBJECT] StockObject: BLACK_PEN
             * [EMRDELETEOBJECT] Index: 1
             * [EMREOF]
             *
             */

            // Printing the main control doesn't get the redraw for the child controls on the first render,
            // directly hitting the up/down button subcontrol.

            using var emfButtons = new EmfScope();
            state = new DeviceContextState(emfButtons);
            upDown.Controls[0].PrintToMetafile(emfButtons);

            /*
             *
             * [ENHMETAHEADER] Bounds: {0, 0, 16, 20 (LTRB)} Device Size: {Width=3840, Height=2160} Header Size: 108
             * [EMRINTERSECTCLIPRECT] RECT: {0, 0, 16, 10 (LTRB)}
             * [EMRBITBLT] Bounds: {0, 0, 15, 9 (LTRB)} Destination: {0, 0, 16, 10 (LTRB)} Rop: SRCCOPY Source DC Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 16, 21 (LTRB)} Rects: 1 Rect index 0: {0, 0, 16, 21 (LTRB)}
             * [EMRINTERSECTCLIPRECT] RECT: {4, 2, 11, 8 (LTRB)}
             * [EMRALPHABLEND]
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 16, 21 (LTRB)} Rects: 1 Rect index 0: {0, 0, 16, 21 (LTRB)}
             * [EMRINTERSECTCLIPRECT] RECT: {0, 10, 16, 20 (LTRB)}
             * [EMRBITBLT] Bounds: {0, 10, 15, 19 (LTRB)} Destination: {0, 10, 16, 20 (LTRB)} Rop: SRCCOPY Source DC Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 16, 21 (LTRB)} Rects: 1 Rect index 0: {0, 0, 16, 21 (LTRB)}
             * [EMRINTERSECTCLIPRECT] RECT: {4, 12, 11, 18 (LTRB)}
             * [EMRALPHABLEND]
             * [EMREXTSELECTCLIPRGN] Mode: COPY Bounds: {0, 0, 16, 21 (LTRB)} Rects: 1 Rect index 0: {0, 0, 16, 21 (LTRB)}
             * [EMRSETROP2] Mode: R2_COPYPEN
             * [EMRSETBKMODE] Mode: BKMODE_TRANSPARENT
             * [EMRCREATEPEN] Index: 1 Style: ENDCAP_ROUND Width: {X=1,Y=0} Color: [R=255, G=255, B=255] (COLOR_WINDOW, COLOR_HIGHLIGHTTEXT, COLOR_BTNHIGHLIGHT)
             * [EMRSELECTOBJECT] Index: 1
             * [EMRMOVETOEX] Point: {X=0,Y=20}
             * [EMRLINETO] Point: {X=16,Y=20}
             * [EMRMOVETOEX] Point: {X=0,Y=0}
             * [EMRSELECTOBJECT] StockObject: BLACK_PEN
             * [EMRSETBKMODE] Mode: BKMODE_OPAQUE
             * [EMRDELETEOBJECT] Index: 1
             * [EMREOF]
             *
             */
        }