【问题标题】:Erase old lines after ControlPaint.DrawReversibleLine在 ControlPaint.DrawReversibleLine 之后擦除旧行
【发布时间】:2019-10-10 14:59:10
【问题描述】:

在 ControlPaint.DrawReversibleLine 和 DrawReversibleFrame 之后擦除旧行时遇到问题。我确实擦除了,但屏幕(用户控件和图片框)在 Mouse_Move 时保留了旧行。如何彻底清除旧线?

我在 stackoverflow 上搜索过这些东西,所有答案都相似,但对我的情况不起作用。

//a picturebox1 on usercontrol.
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    //...other code
    ControlPaint.DrawReversibleLine(HorizontalSelectionPT1, HorizontalSelectionPT2, Color.Red); //erase old Horizontal line
    ControlPaint.DrawReversibleLine(VerticalSelectionPT1, VerticalSelectionPT2, Color.Red); //erase old vertical line
    Point point = PointToScreen(base.Location);
    HorizontalSelectionPT1 = new Point(point.X, Cursor.Position.Y);
    HorizontalSelectionPT2 = new Point(point.X + base.Width, Cursor.Position.Y);
    VerticalSelectionPT1 = new Point(Cursor.Position.X, point.Y);
    VerticalSelectionPT2 = new Point(Cursor.Position.X, point.Y + base.Height);
    ControlPaint.DrawReversibleLine(HorizontalSelectionPT1, HorizontalSelectionPT2, Color.Red); //Draw new line
    ControlPaint.DrawReversibleLine(VerticalSelectionPT1, VerticalSelectionPT2, Color.Red); //Draw new line

    //draw selected frame                    
   ControlPaint.DrawReversibleFrame(pbCanvas.RectangleToScreen(rectangle_0), Color.Black, FrameStyle.Dashed); //erase old frame
   rectangle_0.Width = e.X - rectangle_0.X;
   rectangle_0.Height = e.Y - rectangle_0.Y;                    
   ControlPaint.DrawReversibleFrame(pbCanvas.RectangleToScreen(rectangle_0), Color.Black, FrameStyle.Dashed); //Draw new frame

   //...other codes
}

几乎没有截屏,我使用了相机。

【问题讨论】:

  • 您需要以与最初绘制相反的顺序“撤消”先前的输出。所以 DrawReversibleFrame() 必须是第一个。当控件重新绘制自身时,您必须撤消它,使用 Paint 事件来了解这一点。
  • 以上代码中所有可反转的线条和边框都是用Mouse_Move绘制的。
  • 该评论不太可能帮助我们帮助您。请避免使用 ControlPaint。而是使用 Paint 事件来绘制线条,在 MouseMove 事件处理程序中调用 Invalidate() 以强制重绘。
  • 您的解决方案工作时有一点点闪烁。我在 Paint 事件中将 ControlPaint 用于可逆线和帧。
  • 顺便说一句,我的颜色是红色,但为什么线条是“蓝色”?

标签: c# image paint picturebox


【解决方案1】:

我已将所有 ControlPaint.DrawReverseFrame 替换为 GDI32 API 以解决擦除旧线问题。无论我尝试使用 ControlPaint.DrawReversibleLine 都会产生不良效果或闪烁。

   private static int ArgbToRGB(int rgb)
   {
    return ((rgb >> 16 & 0x0000FF) | (rgb & 0x00FF00) | (rgb << 16 & 0xFF0000));
    }

    public enum PenStyles
    {
        PS_OLID = 0,
        PS_DASH = 1,
        PS_DOT = 2,
        PS_DASHDOT = 3,
        PS_DASHDOTDOT = 4,
        PS_NULL = 5,
        PS_INSIDEFRAME = 6,
        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 GDIDrawingMode
    {
        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            
    }
[DllImport("gdi32.dll", CharSet = CharSet.Auto, EntryPoint = "Rectangle", ExactSpelling = true, SetLastError = true)]
public static extern bool GDIDrawRectangle(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);

public static void DrawXORRectangle(Graphics graphics, Color penColor, Rectangle rectangle)
    {            
        IntPtr hDC = graphics.GetHdc();
        IntPtr hPen = CreatePen((int)PenStyles.PS_DOT, 1, ArgbToRGB(penColor.ToArgb()));
        IntPtr hOldPen = SelectObject(hDC, hPen);
        SetROP2(hDC, (int)GDIDrawingMode.R2_NOTXORPEN);
        GDIDrawRectangle(hDC, rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom);
        SelectObject(hDC, hOldPen);
        DeleteObject(hPen);
        graphics.ReleaseHdc(hDC);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多