模仿MSpaints绘图方法

时间:2012-12-05 22:19:13

标签: c# winforms graphics drawing

对于图形练习和一些自我改进的类型,我决定基本上只是乱七八糟地尝试在winform中重新创建一些绘画功能。我有很多标准的工作,例如油漆可以,在光标周围绘制点,自由手绘和什么不是,但是我有点困惑,如何绘画中画动画。例如;

要画一条简单的线,我可以简单地在MouseUp和MouseDown事件上获得鼠标坐标,并使用图形类在两者之间画一条线。

然而,在MSpaint画线时,你点击第一个点后几乎可以“预览”该线,并且在将它拖到第二个点时,该线跟随光标,但我有点卡住了至于如何做到这一点?它是否涉及不断重新绘制线条和图形设备?如果有人可以给我一些提示/内在知识,我会在互联网上进行搜索,但却无法真正找到任何有用的东西,这真是太棒了。

2 个答案:

答案 0 :(得分:2)

非常现代的ControlPaint.DrawReversibleLine方法:)

Point? startPoint;
Point? endPoint;

private void Form_MouseDown(object sender, MouseEventArgs e)
{
    startPoint = PointToScreen(e.Location);
}

private void Form_MouseMove(object sender, MouseEventArgs e)
{
    if (!startPoint.HasValue)
        return;

    if (endPoint.HasValue)
        ControlPaint.DrawReversibleLine(startPoint.Value, endPoint.Value, Color.White);

    endPoint = PointToScreen(e.Location);
    ControlPaint.DrawReversibleLine(startPoint.Value, endPoint.Value, Color.White);
}

private void Form_MouseUp(object sender, MouseEventArgs e)
{
    startPoint = null;
    endPoint = null;
}

答案 1 :(得分:1)

Bitmap / raster软件使用两个内存缓冲区:一个是当前“持久”画布,其中包含用户明确修改过的像素,第二个是图形卡上的帧缓冲区,用于显示画布上的画布-screen。

使位图文档出现在屏幕上是通过简单地将内存中位图文档的原始字节复制到帧缓冲区来完成的(如果帧缓冲区具有与内存中位图不同的字节格式或颜色深度,则你需要执行转换。如果需要,GDI可以为你做这件事,但我们假设一切都是32位ARGB。

在WinForms中,帧缓冲区由传递到Graphics覆盖的Control.OnPaint参数公开。

您可以使用以下两种方法之一实现这些“预览”效果:

现代

今天使用的第一种方法,已经过去17年左右(从Windows 95开始)。每当需要更新屏幕时,就会将内存中的位图复制到帧缓冲区,例如单个鼠标移动(甚至1px)。然后在顶部绘制预览效果(例如用户在释放鼠标按钮后将绘制的线条)。一旦用户的鼠标再次移动,该过程就会重复,因此要更新预览。

你会有这样的事情:

public class PaintingCanvas : Control {

    private Bitmap _canvas = new Bitmap();

    private Boolean _inOp; // are we in a mouse operation?
    private Point _opStart; // where the current mouse operation started
    private Point _opEnd; // where it ends

    public override void OnPaint(PaintEventArgs e) {
        Graphics g = e.Graphics;
        g.DrawImage( _canvas ); // draw the current state

        if( _inOp ) {
            // assuming the only operation is to draw a line
            g.DrawLine( _opStart, _opEnd );
        }
    }

    protected override OnMouseDown(Point p) {
        _inOp = true;
        _opStart = _opEnd = p;
    }
    protected override OnMouseMove(Point p) {
        _opEnd = p;
        this.Invalidate(); // trigger repainting
    }
    protected override OnMouseUp(Point p) {
        using( Graphics g = Graphics.FromImage( _bitmap ) ) {
            g.DrawLine( _opStart, _opEnd ); // a permanent line
        }
        _inOp = false;
    }
}

1980年代Flashblack

在过去的日子里(想想:20世纪80年代),将位图从内存复制到帧缓冲区的速度很慢,所以一个令人惊讶的好黑客就是使用XOR绘画。该程序假定帧缓冲的所有权(因此没有重叠的窗口会导致它需要从内存中复制)。通过对线将覆盖的所有像素执行XOR来绘制预览线。这很快,因为对像素进行异或意味着可以恢复原始颜色而无需从内存中重新复制像素。直到最近,这种技巧还被用于计算机中以进行多种选择,突出显示或预览效果。

highlightOrPreviewColor = originalPixelColor XOR (2^bpp - 1)
originalPixelColor      = highlightOrPreviewColor XOR (2^bpp - 1)