|
5回目の投稿です。
はじめまして、ID非公開と申します。
私はflexGridやJavaAPIのことはわかりませんが、 TextBoxで無制限Undo/Redo機能を以前作成してみたことがあります。 その経験の範囲内でお答え致します。
用意するものは以下の2つです
1.入力操作を記録するためのクラス。
Public Class ActionRecord ' ' 以下の3つの情報があれば入力操作を完全に保存可能 ' Public Index As Integer ' カーソル位置 を保存 Public Deleted As String ' 削除された文字列 を保存 Public Inserted As String ' 入力された文字列 を保存 Public Sub New(ByVal index As Integer, ByVal deleted As String, ByVal inserted As String) Me.Index = index Me.Inserted = inserted Me.Deleted = deleted End Sub End Class
※ここで、1回の入力操作を1つのActionRecordインスタンスに対応させます。 例えば「ab」と続けて入力した場合には、 「a」の入力に対応するActionRecordインスタンス 「b」の入力に対応する 同上 をそれぞれ生成します。 全ての入力操作について逐一ActionRecordインスタンスを生成して保存しておけば、 完全なUndo/Redo機能を実現できます。
2.Undo操作とRedo操作の履歴を格納するためのList。
Private UndoList As New List(Of ActionRecord) Private RedoList As New List(Of ActionRecord)
※ここに、生成したActionRecordインスタンス達を順次格納します。 後述しますが、「リストの先頭に格納すること」がポイントです。
<詳細の説明>
1.入力操作が行われるたびに、それに対応するActionRecordインスタンスを生成します。
例えば「a」と入力した場合、 反転表示されたTextがあれば削除して、 カーソル位置に「a」を挿入。 という処理が行われます。 これに対応するActionRecordインスタンスは
Dim ar As New ActionRecord(Me.SelectionStart, Me.SelectedText, "a") ※ 念のための補足:ここでの「Me」はTextBoxのことです。
となります。反転表示の有無にかかわらずこの方法で対応することができます。
2.次に、これをUndoListの先頭に格納します。
UndoList.Insert(0, ar)
※ここで「先頭に格納すること」がポイントです。 なぜなら、Undo操作を行う場合に「先頭から取り出して、先頭を削除」を繰り返していけば、 操作履歴を新しいものから順番に取り出せるからです。
3.Undo操作の流れ
以下の処理を繰り返せばOKです。
Private LockObj As String="" ' ←この変数はどこか別の場所で宣言 SyncLock LockObj
Dim ar2 As ActionRecord = UndoList(0) ' ' ar2の情報を元にTextBoxのTextを復元する処理をここに書く ' UndoList.RemoveAt(0) RedoList.Insert(0, ar2) ' 今度はRedoListに格納(ここでも「先頭に格納」)
End SyncLock
※Redo操作の場合も、向きが逆になるだけで、考え方は全く同じです。
SyncLockブロックがないと、「Undoを連続実行」した際にテキストが正しく復元できません。 (詳しい理由は私にもわかりませんが、こうしないとうまくいかないようです)
4.補足
キーボード入力が行われる毎に、RedoListをクリアしてください。 そうしないとRedo機能が正しく動作しません。
TextBoxの場合は、以上の方法で無制限Undo/Redoを実現できます。 flexGridの場合はもっと複雑になると思いますが、 同様の考え方で対応していけば良いのではないかと思います。
参考文献
日経BPソフトプレス発行「プログラミングVisualBasic2005言語編(下)」、pp. 416 - 421 .
http://hp.vector.co.jp/authors/VA007799/viviProg/doc3.htm
以上です。
|