简体   繁体   English

在WinApi中使用C#笔和画笔?

[英]Using C# Pens and Brushes in WinApi?

How can I get HBRUSH from Brush and HPEN from Pen ? 我怎样才能得到HBRUSH画笔HPEN
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.) (我想使用未在.NET's System.Drawing实现的WinApi函数,例如DrawRoundRect / CreateRoundRectRgn ,我想使用.NET中的画笔而不是自己创建它们。)

The Brush class does have a private field called nativeBrush which holds the HBRUSH handle as an IntPtr. Brush类有一个名为nativeBrush的私有字段,它将HBRUSH句柄保存为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: 因为它是一个私有领域,它可能随着.Net的任何修订而改变,但如果你不介意使用一些狡猾的,脆弱的反射来获得它的价值,你可以做一些令人讨厌的事情:

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. Pen有一个类似的字段叫做nativePen ,您可以使用类似的反射代码访问它。

However, if you can use GraphicsPath as Don shows above, that would be much less risky. 但是,如果您可以像上面显示的Don那样使用GraphicsPath,那么风险就会大大降低。

Also check out this article on creating rounded rectangles using GraphicsPath 另请参阅有关使用GraphicsPath创建圆角矩形的文章

I don't have the original source any longer, might even have been a SO item. 我不再拥有原始资源,甚至可能是SO项目。 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. 只需在您传递Graphics对象的任何PaintPaintBackground事件中进行调用。 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. 它可以选择在没有外部P / Invokes的情况下将其全部保存在.NET中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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