简体   繁体   中英

Using C# Pens and Brushes in WinApi?

How can I get HBRUSH from Brush and HPEN from Pen ?
I wonder is there any connection between the two sides ?

(I want to use WinApi functions that are not implemented in .NET's System.Drawing such as DrawRoundRect / CreateRoundRectRgn and I want to use brushes from .NET for that instead of creating them on my own.)

The Brush class does have a private field called nativeBrush which holds the HBRUSH handle as an IntPtr.

Because it's a private field, it could change with any revision to .Net, but if you don't mind using some dodgy, brittle reflection to get at its value, you could do something nasty like this:

Brush brush = ...the brush that you want to get at the handle for
FieldInfo field = typeof(Brush).GetField("nativeBrush",BindingFlags.NonPublic|BindingFlags.Instance);
IntPtr hbrush = (IntPtr)field.GetValue(brush);

There is a similar field for Pen called nativePen which you can access using similar reflection code.

However, if you can use GraphicsPath as Don shows above, that would be much less risky.

Also check out this article on creating rounded rectangles using GraphicsPath

I don't have the original source any longer, might even have been a SO item. At any rate, here's a class someone provided a while back that I use:

/// <summary>
/// Collection of often-used classes and methods for easy access.
/// </summary>
public class RoundedDrawing
{
    private static GraphicsPath GetRoundedRectanglePath(Int32 x, Int32 y, Int32 width, Int32 height, Int32 radius)
    {
        GraphicsPath path = new GraphicsPath();
        path.AddLine(x + radius, y, x + width - radius, y);
        if (radius > 0)
            path.AddArc(x + width - 2 * radius, y, 2 * radius, 2 * radius, 270.0f, 90.0f);
        path.AddLine(x + width, y + radius, x + width, y + height - radius);
        if (radius > 0)
            path.AddArc(x + width - 2 * radius, y + height - 2 * radius, 2 * radius, 2 * radius, 0.0f, 90.0f);
        path.AddLine(x + width - radius, y + height, x + radius, y + height);
        if (radius > 0)
            path.AddArc(x, y + height - 2 * radius, 2 * radius, 2 * radius, 90.0f, 90.0f);
        path.AddLine(x, y + height - radius, x, y + radius);
        if (radius > 0)
            path.AddArc(x, y, 2 * radius, 2 * radius, 180.0f, 90.0f);
        return path;
    }

    /// <summary>
    /// Fills the interior of a rounded rectangle.
    /// </summary>
    public static void FillRoundedRectangle(Graphics graphics, Brush brush, float x, float y, float width, float height, float radius)
    {
        FillRoundedRectangle(graphics, brush, (Int32)x, (Int32)y, (Int32)width, (Int32)height, (Int32)radius);
    }

    /// <summary>
    /// Fills the interior of a rounded rectangle.
    /// </summary>
    public static void FillRoundedRectangle(Graphics graphics, Brush brush, Rectangle rect, Int32 radius)
    {
        FillRoundedRectangle(graphics, brush, rect.Left, rect.Top, rect.Width, rect.Height, radius);
    }

    /// <summary>
    /// Fills the interior of a rounded rectangle.
    /// </summary>
    public static void FillRoundedRectangle(Graphics graphics, Brush brush, RectangleF rect, float radius)
    {
        FillRoundedRectangle(graphics, brush, (Int32)rect.Left, (Int32)rect.Top, (Int32)rect.Width, (Int32)rect.Height, (Int32)radius);
    }

    /// <summary>
    /// Fills the interior of a rounded rectangle.
    /// </summary>
    public static void FillRoundedRectangle(Graphics graphics, Brush brush, Int32 x, Int32 y, Int32 width, Int32 height, Int32 radius)
    {
        using (GraphicsPath path = GetRoundedRectanglePath(x, y, width, height, radius))
            graphics.FillPath(brush, path);
    }

    /// <summary>
    /// Draws the outline of a rounded rectangle.
    /// </summary>
    public static void DrawRoundedRectangle(Graphics graphics, Pen pen, float x, float y, float width, float height, float radius)
    {
        DrawRoundedRectangle(graphics, pen, (Int32)x, (Int32)y, (Int32)width, (Int32)height, (Int32)radius);
    }

    /// <summary>
    /// Draws the outline of a rounded rectangle.
    /// </summary>
    public static void DrawRoundedRectangle(Graphics graphics, Pen pen, Rectangle rect, Int32 radius)
    {
        DrawRoundedRectangle(graphics, pen, rect.Left, rect.Top, rect.Width, rect.Height, radius);
    }

    /// <summary>
    /// Draws the outline of a rounded rectangle.
    /// </summary>
    public static void DrawRoundedRectangle(Graphics graphics, Pen pen, RectangleF rect, float radius)
    {
        DrawRoundedRectangle(graphics, pen, (Int32)rect.Left, (Int32)rect.Top, (Int32)rect.Width, (Int32)rect.Height, (Int32)radius);
    }

    /// <summary>
    /// Draws the outline of a rounded rectangle.
    /// </summary>
    public static void DrawRoundedRectangle(Graphics graphics, Pen pen, Int32 x, Int32 y, Int32 width, Int32 height, Int32 radius)
    {
        using (GraphicsPath path = GetRoundedRectanglePath(x, y, width, height, radius))
            graphics.DrawPath(pen, path);
    }
}

Just make calls from within any Paint or PaintBackground event where you're handed a Graphics object. Pass that in along with whatever else, and draw rounded stuff.

It's an option to keep it all in .NET without external P/Invokes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM