2016-07-10 9 views
1

取り消しおよびやり直し機能を備えた単純な描画アプリケーションを作成しようとしています。私はあなたがリストに描いているものを追加し、リストを呼び出してすべてを描くことができると仮定します。次に元に戻すと、最後に追加されたアイテムが削除され、すべてのアイテムが再び表示されます。問題は、リストに描いたものを追加してそのリストを元に戻すにはどうすればいいですか?複数のフリーハンドポリラインまたは曲線描画を描画する - 取り消し機能を追加する

私はビットマップの再描画メソッドを使用しています。 これは私が描く方法です:

Point start, end; 
    bool painting; 
    private List<PointF> myPoints = new List<PointF>(); 

    private void pnlMain_MouseDown(object sender, MouseEventArgs e) 
    { 
     start = e.Location; 
     painting = true; 
    } 

    private void pnlMain_MouseUp(object sender, MouseEventArgs e) 
    { 
     painting = false; 
    } 

    private void pnlMain_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (painting == true) 
     { 
      end = e.Location; 
      g.DrawLine(p, start, end); 
      myPoints.Add(e.Location); 
      pnlMain.Refresh(); 
      start = end; 
     } 
    } 

    private void btnUndo_Click(object sender, EventArgs e) 
    { 
     g.Clear(cldFill.Color); 
     if (myPoints.Count > 2) 
     { 
      myPoints.RemoveAt(myPoints.Count - 1); 
      g.DrawCurve(p, myPoints.ToArray()); 
     } 
     pnlMain.Refresh(); 
     //This works but you have to spam it to get rid of 
     //a line and does some weird connections. 
    } 
+0

描画する座標を 'List 'に集める必要があります。収集方法に関するコードについては、私の[コメントはこちら]をご覧ください(http://stackoverflow.com/questions/38280801/smoother-graphics-than-smoothingmode-antialias#38280801)!また、あなたは間違った方法でペイントします。あなたはGraphicsオブジェクトをキャッシュしているようです。これは間違っています!ペイントイベントのすべてを描く! – TaW

+0

はい、問題ありません。あなたが必要とするのは、あなたが必要とするすべてのコードを実装することです。(私がリンクしたコメントは、(http://stackoverflow.com/questions/38280801/smoother-graphics-than-smoothingmode-antialias#38280801)ボタンをクリックして 'curves.Remove(curves.Last));をクリックします。 pnlMain.Invalidate(); ' – TaW

答えて

4

あなたはList<List<Point>>の行を格納する必要があります。リストの各要素には、下、上、上を使用して描画する図の点が含まれています。描画する次の行は、リストの次の要素に格納されます。各元に戻すと、最後の図面が削除されます。

このコントロールのインスタンスをフォームに配置すると、描画が処理されます。また、取り消しを実行するには、Undoメソッドを呼び出します。

using System.Collections.Generic; 
using System.Drawing; 
using System.Linq; 
using System.Windows.Forms; 
public class DrawingSurface : Control 
{ 
    public DrawingSurface() { this.DoubleBuffered = true; } 
    List<List<Point>> Lines = new List<List<Point>>(); 
    bool drawing = false; 
    protected override void OnMouseDown(MouseEventArgs e) { 
     Lines.Add(new List<Point>()); 
     Lines.Last().Add(e.Location); 
     drawing = true; 
     base.OnMouseDown(e); 
    } 
    protected override void OnMouseMove(MouseEventArgs e) { 
     if (drawing) { Lines.Last().Add(e.Location); this.Invalidate(); } 
     base.OnMouseMove(e); 
    } 
    protected override void OnMouseUp(MouseEventArgs e) { 
     if (drawing) { 
      this.drawing = false; 
      Lines.Last().Add(e.Location); 
      this.Invalidate(); 
     } 
     base.OnMouseUp(e); 
    } 
    protected override void OnPaint(PaintEventArgs e) { 
     e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 
     foreach (var item in Lines) 
      e.Graphics.DrawLines(Pens.Black, item.ToArray()); /*or DrawCurve*/ 
    } 
    public void Undo() { 
     if (Lines.Count > 0) { this.Lines.RemoveAt(Lines.Count - 1); this.Invalidate(); } 
    } 
} 

  • このロジックを使用して、あなたは、単に他のList<List<Point>>を使用してREDOを実装することができます。 RedoBuffer.Add(Lines.Last());を使用して元に戻す前に最後の項目をコピーしてやり直しリストにコピーすれば十分です。次に、それぞれのredoコマンドに対して、最後のredoバッファ項目をLinesに追加して、それをやり直しバッファから削除するだけで十分です。マウスを1回押すごとに、やり直しバッファもクリアする必要があります。
  • お客様の要件に基づいてDrawLinesまたはDrawCurveのいずれかを使用できます。 DrawLinesはポリラインを描画し、DrawCurveはより滑らかなカーブを描画します。

  • Lines.Count > 0bool CanUndoのような特性にカプセル化し、コントロールの外部からアクセス可能にすることを好む。

  • これは単なる例であり、単にソリューションを拡張することができます。たとえば、List<List<Point>>の代わりにList<Point>LineWidthLineColorなどを含むShapeクラスを作成し、List<Shape>を使用してタスクを実行できます。

+0

これはとても良いクラスです!どのように私はクラスに話し、長方形や円を描くように言うことができるかの例を私に示してもらえますか? –

+0

この例を拡張するには、抽象的な 'Draw'メソッドを含む' Shape'クラスとメソッドを実装し、座標に必要なプロパティを含む 'Rectangle'や' Circle'のような派生クラスを作成できます。次に、描画するオブジェクトを格納するために 'List 'を使うことができます。図形を描画するには、描画する図形とこのフラグに基づいて、その図形に目的の図形を追加するフラグを設定する必要があります。それらをペイントするには、 'OnPaint'メソッドで各シェイプの' Draw'メソッドを呼び出します。 –

+0

これはほとんどすべてのアイデアです。シンプルですが、より多くのコードが必要です。また、さまざまな方法で行うことができますので、アプリケーションの作成を開始する場合は、実装に関連する質問を自由にしてください。この回答とコメントがあなたに役立つことを願っています:) –

関連する問題