0

Visual-C ++で作成しようとしているかなり大きなアプリケーションがあり、現在、元に戻す/やり直し機能を追加しようとしています。

かなりの量のイベント(ボタンのクリック、ラベルのテキストの変更など)があるので、すべての関数にコードを追加せずに元に戻す/やり直す方法を見つけたいと思います。たとえば、行われたすべてのイベントを読み取り、それを自動的に保存できるクラスが必要です。次に、元に戻す/やり直しイベントで、最新のアクションを保存することができます。

それが不可能な場合、私は他の方法を気にしません。

何か助けはありますか?

4

3 に答える 3

2

元に戻すとやり直しの2つの操作を表すクラスを宣言します。また、そのクラスの2つのベクトルを作成します。

元に戻る/やり直しを適用する操作ごとに、そのクラスのインスタンスを元に戻るベクターにプッシュします。元にしたい操作と同じ数の派生クラスが必要です。

たとえば、ボタンをクリックして背景を緑色にペイントする場合、undo metdhoが背景を前の色にペイントするクラスインスタンスを作成し、そのredoメソッドが背景を緑色にペイントして、undoベクトルに詰め込みます。元に戻すとき-最後のクラスインスタンスをポップし、その元にメソッドを呼び出します。これにより、背景が前の色にペイントされます。次に、それをREDOベクトルにプッシュします。

REDOを実行するときは、クラスインスタンスのREDOベクトルを一番上にポップし、そのREDOメソッドを呼び出すと、元に戻るベクトルに戻されます。

いくつかのコーナーケース(境界)があります、あなたは遭遇したときにそれらに取り組むでしょう.. :-)

于 2012-04-28T21:20:24.687 に答える
1

すべてのイベントは、ある種のキューを通過しますか?デフォルトでは、c ++にはこのようなキューはありません(Windows OSレベルのイベントキューがありますが、c ++-cliではすでに管理されて使用できない可能性があり、これが問題に密接にマッピングされているかどうかを示していません)、いくつかの可能性があります私が知らない他の構成。

中央キューがある場合は、イベントが通過するときにイベントをキャプチャし、各アクションを元に戻す方法を知っているだけです。中央キューが存在しない場合は、元にできる各関数を変更して、ある種の元にできるオブジェクトを作成し、それをある種の元にできるキューに保存する以外に簡単な方法はありません。

大きな中央作業キューのない純粋な.netまたはC++環境では、元に戻すためのメソッド/メンバー関数と、作業をやり直し/実行するためのメソッド/メンバー関数を実装する、エントリを元に戻すクラスを作成します。ただし、元に戻す機能の場合、これは.netデリゲートまたはacスタイルの関数ポインター、および引数のリストである可能性があります。アクションundo/redoクラスを作成する場合、それは、doおよびundo関数へのポインター/委任、および最初に呼び出されたときの引数のリストを格納するテンプレートまたはジェネリックである可能性があります。

これらを実行して、実行されたアクションを元に戻すことができます。それらはある種のキューコンテナに挿入されます。コンテナの種類は、順序を維持するほど長くは重要ではないようです。アプリケーションに最適なstd、.net、またはその他のコンテナを選択する必要があります。古いものは、不要になったときに破棄できます。実行時に、キューに最後に挿入されたエントリは、一貫性を維持するために削除する必要があります。

If you also need redo functionality, then your queue of actions done must be iterable, and it would be easiest to use the class that was and action had a method/member function that could undo/redo the desired actions. You would have and iterator, pointer, index or marker of some kind indicating how far back you have undone. Every time an undo is requested you must move the marker backward (earlier chronologically) and execute the undo command at that point in the queue. If a redo is requested then the current item indicated executes its redo instruction and then the iterator is advanced forward (chronologically) through the queue, or ignored (I presume) if you are at the forward-most item in the queue.

ディープエンドから抜け出したい場合は、アプリをアクションキューの中心に置くことができます。このアプローチを実装する機能を変更する必要はないかもしれません。ユーザーインターフェイス(私は、APIと同じくらい簡単にできると思います)を機能させ、アクション(実行と元に戻すことをサポートする)をキューに挿入してから、キューに実行を指示します。副作用がわかっていて元に戻せる場合は、既存の機能を変更する必要はありません。ただし、直接呼び出すのではなく、すべての呼び出し元を変更してアクションを実行する必要があります。また、元に戻す操作を行う対応する呼び出し元を作成する必要があります。

于 2012-04-28T21:43:04.450 に答える
1

私は小さな実験ライブラリでそのようなことを達成しようとしました:https ://github.com/d-led/undoredo-cpp 。これには、 CodeChordsの男性が提案TransactionStoreしたものと同様の実装が含まれています。アクションにオブジェクトの構築または破棄が含まれる場合に備えて、元に戻すことができる各オブジェクトに実際に機能を追加し、オブジェクトの存続期間にも注意を払う必要がある場合があります。

于 2012-08-27T07:53:25.480 に答える