1

グラフィックスの演習やいくつかの自己改善のようなものについては、基本的にはただい​​じって、WinForm内でペイントの機能の一部を再現することにしました。ペイント缶、カーソルの周りにドットを描く、フリーハンドで描くなど、標準的なものがたくさんありますが、ペイントが描画中のアニメーションをどのように行うかについては少し戸惑っています。例えば;

単純な線を描くには、MouseUpイベントとMouseDownイベントでマウス座標を取得し、graphicsクラスを使用して2つの間に線を引くことができます。

ただし、MSpaintでは、線を描画しているときに、最初の点をクリックした後、線のほぼ「プレビュー」が表示され、2番目の点にドラッグしている間、線はカーソルに追従しますが、方法については少し行き詰まっています。これは行われますか?線とグラフィックスデバイスを絶えず再描画する必要がありますか?誰かが私にいくつかのヒント/内部知識を与えることができれば素晴らしいでしょう、私はインターネットの周りを検索しましたが、本当に役に立つものを見つけることができません。

4

2 に答える 2

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;
}
于 2012-12-05T23:20:50.283 に答える
1

ビットマップ/ラスターソフトウェアは2つのメモリバッファを使用します。1つはユーザーが明示的に変更したピクセルを含む現在の「永続化」キャンバスで、もう1つは画面上にキャンバスを表示するために使用されるグラフィックカードのフレームバッファです。

ビットマップドキュメントを画面に表示するには、メモリ内のビットマップドキュメントの生のバイトをフレームバッファにコピーするだけです(フレームバッファのバイト形式または色深度がメモリ内のビットマップと異なる場合は、次のようにする必要があります。変換を実行します。GDIは必要に応じてこれを実行できますが、すべてが32ビットARGBであると仮定しましょう。

WinFormsでは、フレームバッファはオーバーライドGraphicsに渡された引数によって公開されます。Control.OnPaint

これらの「プレビュー」効果は、次の2つのアプローチのいずれかを使用して実装できます。

モダン

最初のアプローチは今日使用されており、過去17年ほど(Windows 95以降)使用されています。インメモリビットマップは、マウスを1回動かす(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年代のフラッシュブラック

昔(1980年代を考えてください)、メモリからフレームバッファへのビットマップのコピーは遅かったので、驚くほど良いハックはXORペイントを使用していました。プログラムはフレームバッファの所有権を引き継ぎます(したがって、ウィンドウが重なってもメモリからコピーする必要はありません)。プレビューラインは、ラインがカバーするすべてのピクセルのXORを実行することによって描画されます。ピクセルをXORすると、メモリからピクセルを再コピーしなくても元の色を復元できるため、これは高速です。このトリックは、最近まで、さまざまな種類の選択、ハイライト、またはプレビュー効果のためにコンピューターで使用されていました。

highlightOrPreviewColor = originalPixelColor XOR (2^bpp - 1)
originalPixelColor      = highlightOrPreviewColor XOR (2^bpp - 1)
于 2012-12-05T22:54:51.913 に答える