In order to use the function we need to create a few GDI objects: a Pen to draw the border, and a Brush to fill the rectangle. We will mostly use P/Invoke for creating and releasing GDI objects
const int PS_SOLID = 0;
const int PS_DASH = 1;
[DllImport("coredll.dll")]
static extern IntPtr CreatePen(int fnPenStyle, int nWidth, uint crColor);
[DllImport("coredll.dll")]
static extern int SetBrushOrgEx(IntPtr hdc, int nXOrg, int nYOrg, ref Point lppt);
[DllImport("coredll.dll")]
static extern IntPtr CreateSolidBrush(uint color);
[DllImport("coredll.dll")]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobject);
[DllImport("coredll.dll")]
static extern bool DeleteObject(IntPtr hgdiobject);
[DllImport("coredll.dll")]
static extern bool RoundRect(
IntPtr hdc,
int nLeftRect,
int nTopRect,
int nRightRect,
int nBottomRect,
int nWidth,
int nHeight);
The CreateSolidBrush function in native code actually takes a COLORREF parameter, and the developer would normally use the RGB macro to create it. We need to translate that macro into a .NET function
static uint GetColorRef(Color value)
{
return 0x00000000 | ((uint)value.B << 16) | ((uint)value.G << 8) | (uint)value.R;
}
Now we have our P/Invoke definitions in place we can neatly wrap all P/Invoke operations in a single function and let's call that FillRoundedRectangle()
public static void FillRoundedRectangle(
this Graphics graphics,
Pen border,
Color color,
Rectangle rectangle,
Size ellipseSize)
{
var lppt = new Point();
var hdc = graphics.GetHdc();
var style = border.DashStyle == DashStyle.Solid ? PS_SOLID : PS_DASH;
var hpen = CreatePen(style, (int)border.Width, GetColorRef(border.Color));
var hbrush = CreateSolidBrush(GetColorRef(color));
try
{
SetBrushOrgEx(hdc, rectangle.Left, rectangle.Top, ref lppt);
SelectObject(hdc, hpen);
SelectObject(hdc, hbrush);
RoundRect(hdc,
rectangle.Left,
rectangle.Top,
rectangle.Right,
rectangle.Bottom,
ellipseSize.Width,
ellipseSize.Height);
}
finally
{
SetBrushOrgEx(hdc, lppt.Y, lppt.X, ref lppt);
DeleteObject(hpen);
DeleteObject(hbrush);
graphics.ReleaseHdc(hdc);
}
}
Using this extension method should be straight forward, but here's an example where "e" is an instance of PaintEventArgs:
using (var pen = new Pen(Color.Blue))
e.Graphics.FillRoundedRectangle(
pen,
Color.LightBlue,
new Rectangle(10, 10, 100, 100),
new Size(16, 16));
I hope you found this useful. If you're interested in the full source code then you can grab it here
Hola Christian, muy interesante los codigos. me fueron de una gran ayuda. Gracias
ReplyDeleteStudents often find it difficult to determine how to draw an arm that extends away from a model’s body or the distance between two objects sitting on a table.
ReplyDeleteGreat, thank you
ReplyDelete