private unsafe void CreatePen() { if (_width > 1) { // Geometric pen. // From MSDN: if width > 1, the style must be PS_NULL, PS_SOLID, or PS_INSIDEFRAME. _style |= Gdi32.PS.GEOMETRIC | Gdi32.PS.SOLID; } if (_wndBrush == null) { _nativeHandle = Gdi32.CreatePen(_style, _width, ColorTranslator.ToWin32(_color)); } else { var lb = new Gdi32.LOGBRUSH { lbColor = ColorTranslator.ToWin32(_wndBrush.Color), lbStyle = Gdi32.BS.SOLID, lbHatch = IntPtr.Zero }; // Note: We currently don't support custom styles, that's why 0 and null for last two params. _nativeHandle = Gdi32.ExtCreatePen(_style, _width, ref lb, 0, null); } }
public WindowsPen(DeviceContext dc, Gdi32.PS style, int width, Color color) { _style = style; _width = width; _color = color; _dc = dc; }
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 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 WindowsPen(DeviceContext dc, Gdi32.PS style, int width, WindowsBrush windowsBrush) { Debug.Assert(windowsBrush != null, "null windowsBrush"); _style = style; _wndBrush = (WindowsBrush)windowsBrush.Clone(); _width = width; _color = windowsBrush.Color; _dc = dc; }
public RectangleValidator( RECT bounds, Color penColor, Color brushColor, int penWidth = 1, Gdi32.PS penStyle = default, Gdi32.R2 rop2 = Gdi32.R2.COPYPEN, Gdi32.BKMODE backgroundMode = Gdi32.BKMODE.TRANSPARENT, Gdi32.BS brushStyle = default, Flags validate = default) { _bounds = bounds; _brushColor = brushColor; _brushStyle = brushStyle; _penWidth = penWidth; _penColor = penColor; _penStyle = penStyle; _rop2 = rop2; _backgroundMode = backgroundMode; if (validate != default) { _validate = validate; return; } // Default values for all of these are valid expectations so we always turn them on. _validate = Flags.Bounds | Flags.PenStyle | Flags.BrushStyle; if (penWidth != 0) { _validate |= Flags.PenWidth; } if (!penColor.IsEmpty) { _validate |= Flags.PenColor; } if (!brushColor.IsEmpty) { _validate |= Flags.BrushColor; } if (backgroundMode != default) { _validate |= Flags.BackgroundMode; } if (_rop2 != default) { _validate |= Flags.RopMode; } }
public LineToValidator( Point from, Point to, Color penColor, int penWidth = 1, Gdi32.PS penStyle = default, Gdi32.R2 rop2 = Gdi32.R2.COPYPEN, Gdi32.BKMODE backgroundMode = Gdi32.BKMODE.TRANSPARENT, Flags validate = default) { _from = from; _to = to; _penWidth = penWidth; _penColor = penColor; _penStyle = penStyle; _rop2 = rop2; _backgroundMode = backgroundMode; if (validate != default) { _validate = validate; return; } // Default values for all of these are valid expectations so we always turn them on. _validate = Flags.From | Flags.To | Flags.PenStyle; if (penWidth != 0) { _validate |= Flags.PenWidth; } if (!penColor.IsEmpty) { _validate |= Flags.PenColor; } if (backgroundMode != default) { _validate |= Flags.BackgroundMode; } if (_rop2 != default) { _validate |= Flags.RopMode; } }
internal static IEmfValidator LineTo( EasyPoint from, EasyPoint to, Color penColor, int penWidth = 1, Gdi32.PS penStyle = default, Gdi32.R2 rop2Mode = Gdi32.R2.COPYPEN, Gdi32.BKMODE backgroundMode = Gdi32.BKMODE.TRANSPARENT, LineToValidator.Flags validate = default) => new LineToValidator( from, to, penColor, penWidth, penStyle, rop2Mode, backgroundMode, validate);
internal static IEmfValidator Rectangle( RECT bounds, Color penColor, Color brushColor, int penWidth = 1, Gdi32.PS penStyle = default, Gdi32.R2 rop2 = Gdi32.R2.COPYPEN, Gdi32.BKMODE backgroundMode = Gdi32.BKMODE.TRANSPARENT, Gdi32.BS brushStyle = default, RectangleValidator.Flags validate = default) => new RectangleValidator( bounds, penColor, brushColor, penWidth, penStyle, rop2, backgroundMode, brushStyle, validate);
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_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))); }
public PenStyleValidator(Gdi32.PS penStyle) => _penStyle = penStyle;
internal static IStateValidator PenStyle(Gdi32.PS penStyle) => new PenStyleValidator(penStyle);
internal static IStateValidator Pen(int penWidth, Color penColor, Gdi32.PS penStyle) => new PenValidator(penWidth, penColor, penStyle);
public PenValidator(int penWidth, Color penColor, Gdi32.PS penStyle) { _penWidth = penWidth; _penColor = penColor; _penStyle = penStyle; }