In this short article I’d like to demonstrate how to draw rounded rectangles by P/Invoking the GDI function RoundRect. Let’s create an extension method called FillRoundedRectangle to the Graphics class.

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;
static extern IntPtr CreatePen(int fnPenStyle, int nWidth, uint crColor);
static extern int SetBrushOrgEx(IntPtr hdc, int nXOrg, int nYOrg, ref Point lppt);
static extern IntPtr CreateSolidBrush(uint color);
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobject);
static extern bool DeleteObject(IntPtr hgdiobject);
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));
        SetBrushOrgEx(hdc, rectangle.Left, rectangle.Top, ref lppt);
        SelectObject(hdc, hpen);
        SelectObject(hdc, hbrush);
        SetBrushOrgEx(hdc, lppt.Y, lppt.X, ref lppt);

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))
        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