用本机方法绘制矩形填充白色背景

Draw rectangle with native method fills with white background

我正在使用本机方法在表单中绘制矩形。当我使用 graphics.DrawRectangle 方法时,矩形将正确绘制。但是当使用像下面代码这样的本地方法时,它总是填充矩形内的白色背景。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.BackColor = Color.Yellow;
    }

protected override void OnPaint(PaintEventArgs e)
{
    Rectangle rect = new Rectangle(20,20,100,30);
    e.Graphics.DrawRectangle(new Pen(Color.Red, 1), rect);
    IntPtr hdc = e.Graphics.GetHdc();
    DrawRectangle(hdc, Pens.Red, new Rectangle(25, 60, 100, 30));
    e.Graphics.ReleaseHdc();
    base.OnPaint(e);
}

public void DrawRectangle(IntPtr hdc, Pen pen, Rectangle rect)
{
    IntPtr hpen = IntPtr.Zero;
    try
    {
        hpen = CreatePen((int)pen.DashStyle, (int)pen.Width, (int)new RGB(pen.Color).ToInt32());
        SelectObject(hdc, hpen);
        RectangleCE(hdc, rect.Left, rect.Top, rect.Right, rect.Bottom);
    }
    finally
    {
        if (hpen != IntPtr.Zero)
            DeleteObject(hpen);
    }
}

[DllImport("gdi32")]
public static extern IntPtr CreatePen(int penStyle, int width, int color);


[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj);

[DllImport("gdi32.dll", EntryPoint = "Rectangle", SetLastError = true)]
public static extern uint RectangleCE(IntPtr hdc, int leftRect, int topRect, int rightRect, int bottomRect);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int DeleteObject(IntPtr hObject);

/// <summary>
/// Selects a red, green, blue (RGB) color based on the arguments supplied and the color capabilities of the output device
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct RGB
{
    /// <summary>
    /// The reserved fields.
    /// </summary>
    private byte r, g, b, reserved;

    /// <summary>
    /// Initializes a new instance of the <see cref="RGB"/> struct.
    /// </summary>
    /// <param name="colorIn">The color value.</param>
    public RGB(Color colorIn)
    {
        r = colorIn.R;
        g = colorIn.G;
        b = colorIn.B;
        reserved = 0;
    }

    /// <summary>
    /// Convert the RGB color value to integer value.
    /// </summary>
    /// <returns>Returns the converted value.</returns>
    public int ToInt32()
    {
        var colors = new byte[4];
        colors[0] = r;
        colors[1] = g;
        colors[2] = b;
        colors[3] = reserved;
        return BitConverter.ToInt32(colors, 0);
    }
}

}

请看附件图片,表格中填满了黄色。第一个矩形是使用 graphics.DrawRectangle 方法绘制的,第二个是使用上述本机方法绘制的。

请问有人建议如何使用上述本机方法绘制不填充白色背景的矩形吗?

Rectangle 函数将使用当前画笔绘制一个矩形,并使用当前画笔填充内部。

https://msdn.microsoft.com/en-us/library/aa269219(v=vs.60).aspx

您可以使用 SelectObject 更改当前画笔,如下所示。但设置 Color.Transparent 将被视为白色。

var yColor = (uint) new RGB(Color.Yellow).ToInt32();
SelectObject(hdc, CreateSolidBrush(yColor));
hpen = CreatePen((int)pen.DashStyle, (int)pen.Width, (uint)new RGB(pen.Color).ToInt32());
SelectObject(hdc, hpen);
RectangleCE(hdc, rect.Left, rect.Top, rect.Right, rect.Bottom);

如果不想给内部填充,那就得用FrameRect函数了。但是使用这个功能,线的粗细总是1,我们不能调整它。

https://msdn.microsoft.com/en-us/library/dd144838(v=vs.85).aspx

var rect2 = new RECT(rect);
FrameRect(hdc, ref rect2, CreateSolidBrush((uint)new RGB(Color.Red).ToInt32()));