在C#中调用DrawRectangle方法时如何使用XOR模式

发布于 2024-12-29 11:17:37 字数 104 浏览 7 评论 0原文

正如标题所说,我想用XOR模式画一些东西,因为我想在一段时间后清理它。

我正在使用 C#(窗口窗体)和 Visual Studio 2010。

有人可以帮助我吗?

As the title says, I want to paint something with XOR mode because I want to clean it after a period of time.

I'm using C# (Window Form) with Visual Studio 2010.

Can anybody help me with this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你另情深 2025-01-05 11:17:37

我为 .net 做了一个很好的扩展:

public static class XorDrawing
{

    [DllImport("gdi32.dll", EntryPoint = "SetROP2", CallingConvention = CallingConvention.StdCall)]
    private extern static int SetROP2(IntPtr hdc, int fnDrawMode);

    [DllImport("gdi32.dll", EntryPoint = "MoveToEx", CallingConvention = CallingConvention.StdCall)]
    private extern static bool MoveToEx(IntPtr hdc, int x, int y, IntPtr lpPoint);

    [DllImport("gdi32.dll", EntryPoint = "LineTo", CallingConvention = CallingConvention.StdCall)]
    private extern static bool LineTo(IntPtr hdc, int x, int y);

    [DllImport("gdi32.dll", SetLastError = true)]
    static extern IntPtr CreateCompatibleDC(IntPtr hdc);

    [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
    public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj);

    [DllImport("gdi32.dll")]
    static extern bool DeleteObject(IntPtr target);

    [DllImport("gdi32.dll")]
    static extern IntPtr CreatePen(PenStyle fnPenStyle, int nWidth, uint crColor);

    [DllImport("gdi32.dll")]
    static extern bool SetWorldTransform(IntPtr hdc, [In] ref XFORM lpXform);

    [DllImport("gdi32.dll")]
    public static extern int SetGraphicsMode(IntPtr hdc, int iMode);

    /// <summary>
    ///   The XFORM structure specifies a world-space to page-space transformation.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct XFORM
    {
        public float eM11;
        public float eM12;
        public float eM21;
        public float eM22;
        public float eDx;
        public float eDy;

        public XFORM(float eM11, float eM12, float eM21, float eM22, float eDx, float eDy)
        {
            this.eM11 = eM11;
            this.eM12 = eM12;
            this.eM21 = eM21;
            this.eM22 = eM22;
            this.eDx = eDx;
            this.eDy = eDy;
        }

        /// <summary>
        ///   Allows implicit converstion to a managed transformation matrix.
        /// </summary>
        public static implicit operator System.Drawing.Drawing2D.Matrix(XFORM xf)
        {
            return new System.Drawing.Drawing2D.Matrix(xf.eM11, xf.eM12, xf.eM21, xf.eM22, xf.eDx, xf.eDy);
        }

        /// <summary>
        ///   Allows implicit converstion from a managed transformation matrix.
        /// </summary>
        public static implicit operator XFORM(System.Drawing.Drawing2D.Matrix m)
        {
            float[] elems = m.Elements;
            return new XFORM(elems[0], elems[1], elems[2], elems[3], elems[4], elems[5]);
        }
    }

    public enum BinaryRasterOperations
    {
        R2_BLACK = 1,
        R2_NOTMERGEPEN = 2,
        R2_MASKNOTPEN = 3,
        R2_NOTCOPYPEN = 4,
        R2_MASKPENNOT = 5,
        R2_NOT = 6,
        R2_XORPEN = 7,
        R2_NOTMASKPEN = 8,
        R2_MASKPEN = 9,
        R2_NOTXORPEN = 10,
        R2_NOP = 11,
        R2_MERGENOTPEN = 12,
        R2_COPYPEN = 13,
        R2_MERGEPENNOT = 14,
        R2_MERGEPEN = 15,
        R2_WHITE = 16
    }

    private enum PenStyle : int
    {
        PS_SOLID = 0, //The pen is solid.
        PS_DASH = 1, //The pen is dashed.
        PS_DOT = 2, //The pen is dotted.
        PS_DASHDOT = 3, //The pen has alternating dashes and dots.
        PS_DASHDOTDOT = 4, //The pen has alternating dashes and double dots.
        PS_NULL = 5, //The pen is invisible.
        PS_INSIDEFRAME = 6,// Normally when the edge is drawn, it’s centred on the outer edge meaning that half the width of the pen is drawn
        // outside the shape’s edge, half is inside the shape’s edge. When PS_INSIDEFRAME is specified the edge is drawn 
        //completely inside the outer edge of the shape.
        PS_USERSTYLE = 7,
        PS_ALTERNATE = 8,
        PS_STYLE_MASK = 0x0000000F,

        PS_ENDCAP_ROUND = 0x00000000,
        PS_ENDCAP_SQUARE = 0x00000100,
        PS_ENDCAP_FLAT = 0x00000200,
        PS_ENDCAP_MASK = 0x00000F00,

        PS_JOIN_ROUND = 0x00000000,
        PS_JOIN_BEVEL = 0x00001000,
        PS_JOIN_MITER = 0x00002000,
        PS_JOIN_MASK = 0x0000F000,

        PS_COSMETIC = 0x00000000,
        PS_GEOMETRIC = 0x00010000,
        PS_TYPE_MASK = 0x000F0000
    };

    public enum GraphicsMode : int
    {   
        GM_COMPATIBLE = 1,
        GM_ADVANCED = 2,
    }

    private static IntPtr BeginDraw(System.Drawing.Bitmap bmp, System.Drawing.Graphics graphics, int x1, int y1, int x2, int y2, bool dash, out int oldRop, out IntPtr img, out IntPtr oldpen)
    {
        var gHdc = graphics.GetHdc();
        var hdc = CreateCompatibleDC(gHdc);
        graphics.ReleaseHdc(hdc);

        img = bmp.GetHbitmap();
        SelectObject(hdc, img);

        oldpen = IntPtr.Zero;
        if (dash)
        {
            var pen = CreatePen(PenStyle.PS_DASH, 1, 0);
            oldpen = SelectObject(hdc, pen);
        }
        oldRop = SetROP2(hdc, (int)BinaryRasterOperations.R2_NOTXORPEN); // Switch to inverted mode. (XOR)

        SetGraphicsMode(hdc, (int)GraphicsMode.GM_ADVANCED);
        XFORM transform = graphics.Transform;
        SetWorldTransform(hdc, ref transform);

        return hdc;
    }


    private static void FinishDraw(System.Drawing.Bitmap bmp, System.Drawing.Graphics graphics, IntPtr hdc, IntPtr oldpen, int oldRop, IntPtr img, bool dash)
    {
        SetROP2(hdc, oldRop);

        var transform = graphics.Transform;
        graphics.ResetTransform(); //in case there is transform
        var outBmp = System.Drawing.Image.FromHbitmap(img);
        //CopyChannel(bmp, outBmp, ChannelARGB.Alpha, ChannelARGB.Alpha);
        graphics.Clear(Color.Transparent);
        graphics.DrawImage(outBmp, 0, 0); //draw the xored image on the bitmap
        graphics.Transform = transform;

        if (dash) DeleteObject(SelectObject(hdc, oldpen)); //delete new pen (switch to oldpen)
        DeleteObject(img); // Delete the GDI bitmap (important).
        DeleteObject(hdc);
    }

    public static void DrawXorLine(this System.Drawing.Graphics graphics, System.Drawing.Bitmap bmp, int x1, int y1, int x2, int y2, bool dash = true)
    {
        int oldRop;
        IntPtr oldpen, img;
        var hdc = BeginDraw(bmp, graphics, x1, y1, x2, y2, dash, out oldRop, out img, out oldpen);

        MoveToEx(hdc, x1, y1, IntPtr.Zero);
        LineTo(hdc, x2, y2);

        FinishDraw(bmp, graphics, hdc, oldpen, oldRop, img, dash);
    }

    public static void DrawXorRectangle(this System.Drawing.Graphics graphics, System.Drawing.Bitmap bmp, int x1, int y1, int x2, int y2, bool dash = true)
    {
        int oldRop;
        IntPtr oldpen, img;
        var hdc = BeginDraw(bmp, graphics, x1, y1, x2, y2, dash, out oldRop, out img, out oldpen);

        MoveToEx(hdc, x1, y1, IntPtr.Zero); //clockwise
        LineTo(hdc, x2, y1);
        LineTo(hdc, x2, y2);
        LineTo(hdc, x1, y2);
        LineTo(hdc, x1, y1);

        FinishDraw(bmp, graphics, hdc, oldpen, oldRop, img, dash);
    }
}

Usage

g.DrawXorRectangle(bmp, outRect.Left, outRect.Top, outRect.Left + outRect.Width, outRect.Top + outRect.Height);

Or

g.DrawXorLine(bmp, x1, y1, x2, y2);

I made a nice extension for .net:

public static class XorDrawing
{

    [DllImport("gdi32.dll", EntryPoint = "SetROP2", CallingConvention = CallingConvention.StdCall)]
    private extern static int SetROP2(IntPtr hdc, int fnDrawMode);

    [DllImport("gdi32.dll", EntryPoint = "MoveToEx", CallingConvention = CallingConvention.StdCall)]
    private extern static bool MoveToEx(IntPtr hdc, int x, int y, IntPtr lpPoint);

    [DllImport("gdi32.dll", EntryPoint = "LineTo", CallingConvention = CallingConvention.StdCall)]
    private extern static bool LineTo(IntPtr hdc, int x, int y);

    [DllImport("gdi32.dll", SetLastError = true)]
    static extern IntPtr CreateCompatibleDC(IntPtr hdc);

    [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
    public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj);

    [DllImport("gdi32.dll")]
    static extern bool DeleteObject(IntPtr target);

    [DllImport("gdi32.dll")]
    static extern IntPtr CreatePen(PenStyle fnPenStyle, int nWidth, uint crColor);

    [DllImport("gdi32.dll")]
    static extern bool SetWorldTransform(IntPtr hdc, [In] ref XFORM lpXform);

    [DllImport("gdi32.dll")]
    public static extern int SetGraphicsMode(IntPtr hdc, int iMode);

    /// <summary>
    ///   The XFORM structure specifies a world-space to page-space transformation.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct XFORM
    {
        public float eM11;
        public float eM12;
        public float eM21;
        public float eM22;
        public float eDx;
        public float eDy;

        public XFORM(float eM11, float eM12, float eM21, float eM22, float eDx, float eDy)
        {
            this.eM11 = eM11;
            this.eM12 = eM12;
            this.eM21 = eM21;
            this.eM22 = eM22;
            this.eDx = eDx;
            this.eDy = eDy;
        }

        /// <summary>
        ///   Allows implicit converstion to a managed transformation matrix.
        /// </summary>
        public static implicit operator System.Drawing.Drawing2D.Matrix(XFORM xf)
        {
            return new System.Drawing.Drawing2D.Matrix(xf.eM11, xf.eM12, xf.eM21, xf.eM22, xf.eDx, xf.eDy);
        }

        /// <summary>
        ///   Allows implicit converstion from a managed transformation matrix.
        /// </summary>
        public static implicit operator XFORM(System.Drawing.Drawing2D.Matrix m)
        {
            float[] elems = m.Elements;
            return new XFORM(elems[0], elems[1], elems[2], elems[3], elems[4], elems[5]);
        }
    }

    public enum BinaryRasterOperations
    {
        R2_BLACK = 1,
        R2_NOTMERGEPEN = 2,
        R2_MASKNOTPEN = 3,
        R2_NOTCOPYPEN = 4,
        R2_MASKPENNOT = 5,
        R2_NOT = 6,
        R2_XORPEN = 7,
        R2_NOTMASKPEN = 8,
        R2_MASKPEN = 9,
        R2_NOTXORPEN = 10,
        R2_NOP = 11,
        R2_MERGENOTPEN = 12,
        R2_COPYPEN = 13,
        R2_MERGEPENNOT = 14,
        R2_MERGEPEN = 15,
        R2_WHITE = 16
    }

    private enum PenStyle : int
    {
        PS_SOLID = 0, //The pen is solid.
        PS_DASH = 1, //The pen is dashed.
        PS_DOT = 2, //The pen is dotted.
        PS_DASHDOT = 3, //The pen has alternating dashes and dots.
        PS_DASHDOTDOT = 4, //The pen has alternating dashes and double dots.
        PS_NULL = 5, //The pen is invisible.
        PS_INSIDEFRAME = 6,// Normally when the edge is drawn, it’s centred on the outer edge meaning that half the width of the pen is drawn
        // outside the shape’s edge, half is inside the shape’s edge. When PS_INSIDEFRAME is specified the edge is drawn 
        //completely inside the outer edge of the shape.
        PS_USERSTYLE = 7,
        PS_ALTERNATE = 8,
        PS_STYLE_MASK = 0x0000000F,

        PS_ENDCAP_ROUND = 0x00000000,
        PS_ENDCAP_SQUARE = 0x00000100,
        PS_ENDCAP_FLAT = 0x00000200,
        PS_ENDCAP_MASK = 0x00000F00,

        PS_JOIN_ROUND = 0x00000000,
        PS_JOIN_BEVEL = 0x00001000,
        PS_JOIN_MITER = 0x00002000,
        PS_JOIN_MASK = 0x0000F000,

        PS_COSMETIC = 0x00000000,
        PS_GEOMETRIC = 0x00010000,
        PS_TYPE_MASK = 0x000F0000
    };

    public enum GraphicsMode : int
    {   
        GM_COMPATIBLE = 1,
        GM_ADVANCED = 2,
    }

    private static IntPtr BeginDraw(System.Drawing.Bitmap bmp, System.Drawing.Graphics graphics, int x1, int y1, int x2, int y2, bool dash, out int oldRop, out IntPtr img, out IntPtr oldpen)
    {
        var gHdc = graphics.GetHdc();
        var hdc = CreateCompatibleDC(gHdc);
        graphics.ReleaseHdc(hdc);

        img = bmp.GetHbitmap();
        SelectObject(hdc, img);

        oldpen = IntPtr.Zero;
        if (dash)
        {
            var pen = CreatePen(PenStyle.PS_DASH, 1, 0);
            oldpen = SelectObject(hdc, pen);
        }
        oldRop = SetROP2(hdc, (int)BinaryRasterOperations.R2_NOTXORPEN); // Switch to inverted mode. (XOR)

        SetGraphicsMode(hdc, (int)GraphicsMode.GM_ADVANCED);
        XFORM transform = graphics.Transform;
        SetWorldTransform(hdc, ref transform);

        return hdc;
    }


    private static void FinishDraw(System.Drawing.Bitmap bmp, System.Drawing.Graphics graphics, IntPtr hdc, IntPtr oldpen, int oldRop, IntPtr img, bool dash)
    {
        SetROP2(hdc, oldRop);

        var transform = graphics.Transform;
        graphics.ResetTransform(); //in case there is transform
        var outBmp = System.Drawing.Image.FromHbitmap(img);
        //CopyChannel(bmp, outBmp, ChannelARGB.Alpha, ChannelARGB.Alpha);
        graphics.Clear(Color.Transparent);
        graphics.DrawImage(outBmp, 0, 0); //draw the xored image on the bitmap
        graphics.Transform = transform;

        if (dash) DeleteObject(SelectObject(hdc, oldpen)); //delete new pen (switch to oldpen)
        DeleteObject(img); // Delete the GDI bitmap (important).
        DeleteObject(hdc);
    }

    public static void DrawXorLine(this System.Drawing.Graphics graphics, System.Drawing.Bitmap bmp, int x1, int y1, int x2, int y2, bool dash = true)
    {
        int oldRop;
        IntPtr oldpen, img;
        var hdc = BeginDraw(bmp, graphics, x1, y1, x2, y2, dash, out oldRop, out img, out oldpen);

        MoveToEx(hdc, x1, y1, IntPtr.Zero);
        LineTo(hdc, x2, y2);

        FinishDraw(bmp, graphics, hdc, oldpen, oldRop, img, dash);
    }

    public static void DrawXorRectangle(this System.Drawing.Graphics graphics, System.Drawing.Bitmap bmp, int x1, int y1, int x2, int y2, bool dash = true)
    {
        int oldRop;
        IntPtr oldpen, img;
        var hdc = BeginDraw(bmp, graphics, x1, y1, x2, y2, dash, out oldRop, out img, out oldpen);

        MoveToEx(hdc, x1, y1, IntPtr.Zero); //clockwise
        LineTo(hdc, x2, y1);
        LineTo(hdc, x2, y2);
        LineTo(hdc, x1, y2);
        LineTo(hdc, x1, y1);

        FinishDraw(bmp, graphics, hdc, oldpen, oldRop, img, dash);
    }
}

Usage

g.DrawXorRectangle(bmp, outRect.Left, outRect.Top, outRect.Left + outRect.Width, outRect.Top + outRect.Height);

Or

g.DrawXorLine(bmp, x1, y1, x2, y2);
回首观望 2025-01-05 11:17:37

您可以使用 Windows API 函数。我将导入包装在静态类 Win32 中。

public static class Win32
{
    [DllImport("gdi32.dll", EntryPoint = "SetROP2", CallingConvention = CallingConvention.StdCall)]
    public extern static int SetROP2(IntPtr hdc, int fnDrawMode);

    [DllImport("user32.dll", EntryPoint = "GetDC", CallingConvention = CallingConvention.StdCall)]
    public extern static IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll", EntryPoint = "ReleaseDC", CallingConvention = CallingConvention.StdCall)]
    public extern static IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("gdi32.dll", EntryPoint = "MoveToEx", CallingConvention = CallingConvention.StdCall)]
    public extern static bool MoveToEx(IntPtr hdc, int x, int y, IntPtr lpPoint);

    [DllImport("gdi32.dll", EntryPoint = "LineTo", CallingConvention = CallingConvention.StdCall)]
    public extern static bool LineTo(IntPtr hdc, int x, int y);

    public const int R2_NOT = 6;  // Inverted drawing mode

}

使用这些定义,您可以像这样进行绘制。

IntPtr hdc = Win32.GetDC(IntPtr.Zero); // Get device context.
Win32.SetROP2(hdc, Win32.R2_NOT); // Switch to inverted mode. (XOR)
Win32.MoveToEx(hdc, x1, y1, IntPtr.Zero);
Win32.LineTo(hdc, x2, y2);
Win32.ReleaseDC(IntPtr.Zero, hdc); // Release device context.

请注意,.NET 通过 Graphics 对象提供的标准绘图函数在反转模式下不起作用。您必须使用 API 的函数,此处以 MoveToExLineTo 为例。


我从我的代码项目文章 Drag-and-Drop ListBox。

You can use Windows API functions. I wrapped the imports in the static class Win32.

public static class Win32
{
    [DllImport("gdi32.dll", EntryPoint = "SetROP2", CallingConvention = CallingConvention.StdCall)]
    public extern static int SetROP2(IntPtr hdc, int fnDrawMode);

    [DllImport("user32.dll", EntryPoint = "GetDC", CallingConvention = CallingConvention.StdCall)]
    public extern static IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll", EntryPoint = "ReleaseDC", CallingConvention = CallingConvention.StdCall)]
    public extern static IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("gdi32.dll", EntryPoint = "MoveToEx", CallingConvention = CallingConvention.StdCall)]
    public extern static bool MoveToEx(IntPtr hdc, int x, int y, IntPtr lpPoint);

    [DllImport("gdi32.dll", EntryPoint = "LineTo", CallingConvention = CallingConvention.StdCall)]
    public extern static bool LineTo(IntPtr hdc, int x, int y);

    public const int R2_NOT = 6;  // Inverted drawing mode

}

Using these definitions you can draw like this

IntPtr hdc = Win32.GetDC(IntPtr.Zero); // Get device context.
Win32.SetROP2(hdc, Win32.R2_NOT); // Switch to inverted mode. (XOR)
Win32.MoveToEx(hdc, x1, y1, IntPtr.Zero);
Win32.LineTo(hdc, x2, y2);
Win32.ReleaseDC(IntPtr.Zero, hdc); // Release device context.

Note that the standard drawing functions provided by .NET through the Graphics object do not work in inverted mode. You must use the functions of the API, shown here with MoveToEx and LineTo as an example.


I extracted these examples from my Code Project article Drag-and-Drop ListBox.

世界如花海般美丽 2025-01-05 11:17:37

您应该更具体地说明您正在使用的内容,但我假设使用 GDI+ 和 Windows 窗体。

Region region = new Region();
region.MakeEmpty();
region.Xor(rectangle1);
region.Xor(rectangle2);
e.Graphics.FillRegion(Brushes.Black, region); // use e.Graphics if in Paint event

You should be more specific about what you are using, but I am assuming GDI+ and Windows Forms.

Region region = new Region();
region.MakeEmpty();
region.Xor(rectangle1);
region.Xor(rectangle2);
e.Graphics.FillRegion(Brushes.Black, region); // use e.Graphics if in Paint event
辞慾 2025-01-05 11:17:37
/// <summary>
/// Wrapper class for the gdi32.dll.
/// </summary>
public class Gdi32
{
    public enum DrawingMode
    {
        R2_NOTXORPEN = 10
    }

    [DllImport("gdi32.dll")]
    public static extern bool Rectangle(IntPtr hDC, int left, int top, int right, int bottom);

    [DllImport("gdi32.dll")]
    public static extern int SetROP2(IntPtr hDC, int fnDrawMode);

    [DllImport("gdi32.dll")]
    public static extern bool MoveToEx(IntPtr hDC, int x, int y, ref Point p);

    [DllImport("gdi32.dll")]
    public static extern bool LineTo(IntPtr hdc, int x, int y);

    [DllImport("gdi32.dll")]
    public static extern IntPtr CreatePen(int fnPenStyle, int nWidth, int crColor);

    [DllImport("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj);

    [DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObj);

}

/// <summary>
/// Provides utilities directly accessing the gdi32.dll 
/// </summary>
public class GDI
{
    static private Point nullPoint = new Point(0,0);

    // Convert the Argb from .NET to a gdi32 RGB
    static private int ArgbToRGB(int rgb)
    {
        return ((rgb >> 16 & 0x0000FF)| (rgb & 0x00FF00) | (rgb << 16 & 0xFF0000));
    }
    static public void DrawXORRectangle(Graphics graphics, Pen pen, Rectangle rectangle)
    {
        IntPtr hDC = graphics.GetHdc();
        IntPtr hPen = Gdi32.CreatePen(0, (int)pen.Width, ArgbToRGB(pen.Color.ToArgb()));
        Gdi32.SelectObject(hDC, hPen);
        Gdi32.SetROP2(hDC, (int)Gdi32.DrawingMode.R2_NOTXORPEN);
        Gdi32.Rectangle(hDC, rectangle.Left, rectangle.Top, rectangle.Right,rectangle.Bottom);
        Gdi32.DeleteObject(hPen);
        graphics.ReleaseHdc(hDC);
    }

    static public void DrawXORLine(Graphics graphics, Pen pen, int x1, int y1, int x2, int y2)
    {
        IntPtr hDC = graphics.GetHdc();
        IntPtr hPen = Gdi32.CreatePen(0, (int)pen.Width, ArgbToRGB(pen.Color.ToArgb()));
        Gdi32.SelectObject(hDC, hPen);
        Gdi32.SetROP2(hDC, (int)Gdi32.DrawingMode.R2_NOTXORPEN);
        Gdi32.MoveToEx(hDC, x1, y1, ref nullPoint);
        Gdi32.LineTo(hDC, x2, y2);
        Gdi32.DeleteObject(hPen);
        graphics.ReleaseHdc(hDC);
    }
}
/// <summary>
/// Wrapper class for the gdi32.dll.
/// </summary>
public class Gdi32
{
    public enum DrawingMode
    {
        R2_NOTXORPEN = 10
    }

    [DllImport("gdi32.dll")]
    public static extern bool Rectangle(IntPtr hDC, int left, int top, int right, int bottom);

    [DllImport("gdi32.dll")]
    public static extern int SetROP2(IntPtr hDC, int fnDrawMode);

    [DllImport("gdi32.dll")]
    public static extern bool MoveToEx(IntPtr hDC, int x, int y, ref Point p);

    [DllImport("gdi32.dll")]
    public static extern bool LineTo(IntPtr hdc, int x, int y);

    [DllImport("gdi32.dll")]
    public static extern IntPtr CreatePen(int fnPenStyle, int nWidth, int crColor);

    [DllImport("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj);

    [DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObj);

}

/// <summary>
/// Provides utilities directly accessing the gdi32.dll 
/// </summary>
public class GDI
{
    static private Point nullPoint = new Point(0,0);

    // Convert the Argb from .NET to a gdi32 RGB
    static private int ArgbToRGB(int rgb)
    {
        return ((rgb >> 16 & 0x0000FF)| (rgb & 0x00FF00) | (rgb << 16 & 0xFF0000));
    }
    static public void DrawXORRectangle(Graphics graphics, Pen pen, Rectangle rectangle)
    {
        IntPtr hDC = graphics.GetHdc();
        IntPtr hPen = Gdi32.CreatePen(0, (int)pen.Width, ArgbToRGB(pen.Color.ToArgb()));
        Gdi32.SelectObject(hDC, hPen);
        Gdi32.SetROP2(hDC, (int)Gdi32.DrawingMode.R2_NOTXORPEN);
        Gdi32.Rectangle(hDC, rectangle.Left, rectangle.Top, rectangle.Right,rectangle.Bottom);
        Gdi32.DeleteObject(hPen);
        graphics.ReleaseHdc(hDC);
    }

    static public void DrawXORLine(Graphics graphics, Pen pen, int x1, int y1, int x2, int y2)
    {
        IntPtr hDC = graphics.GetHdc();
        IntPtr hPen = Gdi32.CreatePen(0, (int)pen.Width, ArgbToRGB(pen.Color.ToArgb()));
        Gdi32.SelectObject(hDC, hPen);
        Gdi32.SetROP2(hDC, (int)Gdi32.DrawingMode.R2_NOTXORPEN);
        Gdi32.MoveToEx(hDC, x1, y1, ref nullPoint);
        Gdi32.LineTo(hDC, x2, y2);
        Gdi32.DeleteObject(hPen);
        graphics.ReleaseHdc(hDC);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文