模仿微软油漆绘制方法



对于图形练习和一些自我完善的东西,我决定基本上只是四处乱搞,并尝试在winform中重新创建绘画的一些功能。我有很多标准的东西要做,例如油漆罐,在光标周围画点,徒手画等等,但我有点困惑于油漆是如何绘制中期动画的。例如

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

然而,在MSpaint上绘制直线时,单击第一个点后,您几乎可以"预览"直线,将其拖动到第二个点时,直线会跟随光标,但我有点不知道该如何完成?它是否涉及不断重绘线条和图形设备?如果有人能给我一些提示/内心的知识就太好了,我在网上搜索了一下,但真的找不到有用的东西。。

通过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;
}

位图/光栅软件使用两个内存缓冲区:一个是当前"持久化"画布,其中包含用户明确修改的像素;另一个是图形卡上的帧缓冲区,用于在屏幕上显示画布。

只需将内存中位图文档的原始字节复制到帧缓冲区即可使位图文档显示在屏幕上(如果帧缓冲区的字节格式或颜色深度与内存中位图不同,则需要执行转换。如果需要,GDI可以为您执行此操作,但假设所有内容都是32位ARGB)。

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

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

现代

第一种方法在今天使用,并且已经使用了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;
}
}

20世纪80年代Flashblack

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

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

相关内容

  • 没有找到相关文章

最新更新