MainPage 〜きまぐれ ぷろぐらま語録〜
 

2024年4月
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23
24
25 26 27
28 29 30        

最近の記事
Blog移転

エアポート2010を見た

花椒油

Steve Jobs,1955-2011

鉄球に無数のとげが付いた武器

M55→M42(T)が欲しい

健康診断done

回転寿司のルール

相模湖リゾート・プレジャー・フ ..

過去ログ 【表示/最小化】
2011年10月
2011年 9月
2011年 8月
2011年 7月
2011年 6月
2011年 5月
2011年 4月
2011年 3月
2011年 2月
2011年 1月
2010年12月
2010年11月
2010年10月
2010年 9月
2010年 8月
2010年 7月
2010年 6月
2010年 5月
2010年 4月
2010年 3月
2010年 2月
2010年 1月
2009年12月
2009年11月
2009年10月
2009年 9月
2009年 8月
2009年 7月
2009年 6月
2009年 5月
2009年 4月
2009年 3月
2009年 2月
2009年 1月
2008年12月
2008年11月
2008年10月
2008年 9月
2008年 6月
2008年 5月
2008年 4月
2008年 3月
2008年 2月
2008年 1月
2007年12月
2007年11月
2007年10月
2007年 9月
2007年 8月
2007年 7月
2007年 6月
2007年 5月
2007年 4月
2007年 3月
2007年 2月
2007年 1月
2006年12月
2006年11月
2006年10月
2006年 9月
2006年 8月
2006年 7月
2006年 6月
2006年 5月

広告欄

 

Blogを移転させました。
新Blogは次のURLです。
https://kerokero.org/wp/




【WPF】InkCanvasにアンドゥ機能を追加
※続きがあります→翌日の記事

InkCanvasにアンドゥ機能が欲しくて、帰宅後に習作で作ってみた。

ちなみに、InkCanvasは線を描くとStrokesに線が追加されるので、
線を消す方向のアンドゥは、それを操作するだけで結構簡単。

一方で、消しゴム的に消去すると、既存の線が分裂して、
Strokesに再登録されるので、前述の方法だと破綻してしまう。
そのため、消しゴムモードを交えてのアンドゥが結構やっかいっぽい。

そこで、線が追加されたときのイベントと、
消しゴムで分断されたときのイベントを使って、
線分を力業で保存してアンドゥを実装してみた。

コアの部分のコードはこんな:
public class UndoInkCanvas : InkCanvas {
    /// <summary>
    /// アンドゥバッファ
    /// </summary>
    private List<System.Windows.Ink.StrokeCollection> UndoBufferList = new List<System.Windows.Ink.StrokeCollection>();
    /// <summary>
    /// 直前が描画だったか、消しゴムだったかの列挙体
    /// </summary>
    private enum LAST_STROKE_TYPE {
        STROKE,
        ERASER
    };
    /// <summary>
    /// 直前が描画だったか、消しゴムだったかの判断をするためのフラグ
    /// </summary>
    private LAST_STROKE_TYPE LastStrokeType = LAST_STROKE_TYPE.STROKE;
    /// <summary>
    /// 静的コンストラクタ
    /// </summary>
    static UndoInkCanvas() {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(UndoInkCanvas), new FrameworkPropertyMetadata(typeof(UndoInkCanvas)));
    }
    /// <summary>
    /// 通常のコンストラクタ
    /// </summary>
    public UndoInkCanvas() {
        this.StrokeCollected += new InkCanvasStrokeCollectedEventHandler(UndoInkCanvas_StrokeCollected);
        this.StrokeErased += new RoutedEventHandler(UndoInkCanvas_StrokeErased);
    }
    /// <summary>
    /// キャンバスのストロークを全消去します。
    /// </summary>
    public void ClearCanvas() {
        this.UndoBufferList.Clear();
        this.Strokes.Clear();
    }
    /// <summary>
    /// ストロークの取り消し
    /// </summary>
    public void UndoStroke() {
        if (this.UndoBufferList.Count() > 1) {
            //直前の描画結果を破棄
            this.UndoBufferList.RemoveAt(this.UndoBufferList.Count() - 1);
            //直前の描画前の状態を復活
            this.Strokes.Clear();
            foreach (var stroke in this.UndoBufferList.Last()) {
                this.Strokes.Add(stroke);
            }
        } else {
            //Undoリストが無いので、全部消去
            this.UndoBufferList.Clear();
            this.Strokes.Clear();
        }
    }
    /// <summary>
    /// ストロークが追加されたイベント
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void UndoInkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) {
        this.UndoBufferList.Add(this.Strokes.Clone());
        LastStrokeType = LAST_STROKE_TYPE.STROKE;
    }
    /// <summary>
    /// 消しゴムが実行されたイベント
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void UndoInkCanvas_StrokeErased(object sender, RoutedEventArgs e) {
        if (LastStrokeType == LAST_STROKE_TYPE.STROKE) {
            //直前が描画ならば、履歴の追加
            this.UndoBufferList.Add(this.Strokes.Clone());
        } else {
            //削除イベントが連続しているので、直前の描画結果を更新
            if (this.UndoBufferList.Count() > 0) {
                this.UndoBufferList[this.UndoBufferList.Count() - 1] = this.Strokes.Clone();
            }
        }
        LastStrokeType = LAST_STROKE_TYPE.ERASER;
    }
}

かなりエレファント。

もう少しエレガントな方法はないかなぁ・・・

とくに、消しゴムで何回も消しても1回のアンドゥで元に戻るのを、何とかしたいなぁ。

StylusUpイベントとかでやると出来るとは思うケド、
MouseUpやTouchUpでもやらないといけなくて、
もっとエレファントなコードになるだろうし・・・

※続きがあります→翌日の記事

00:24, Wednesday, Jan 26, 2011 ¦ 固定リンク ¦ 携帯


■コメント

■コメントを書く

※コメントの受け付けは終了しました

△ページのトップへ
 

最新のつぶやき

サイト内検索
カスタム検索

旅行関係の記事等
九州・広島旅行記 2009(かみちゅ!)
大阪出張(KANON)
大阪出張(ハルヒ)
三宅島旅行記'05
三宅島旅行記'08
三宅島旅行記'10
伊豆半島小旅行

最近のコメント

最近のトラックバック

IPv4枯渇時計

携帯で読む
   URLを携帯に送る





[Valid RSS]

Powered by CGI RESCUE