内部構造>自動保存
2000/10/15
サクラエディタの自動保存は指定された間隔で上書き保存を呼び出すだけのものです.
クラス名はCPassiveTimerですが,ファイル名はCAutoSave.(cpp|h)です.なぜなら,このクラス自身は時間の経過を管理するだけでファイルの保存とは無関係だからです.
このクラスは指定された時間が経過したら決められた動作をするものですが,自分ではWindowsのタイマーを管理しません.CheckActionメソッドが呼び出されたときにのみ経過時間をチェックします.
自動保存の間隔は分単位で精度は要求されていないため,既にファンクションキー表示やDrag&Dropで使っているタイマーを利用しています.
DWORD nLastTick; // 最後にチェックしたときの時刻 int nInterval; // Action間隔 (分) bool bEnabled; // 有効かどうか
計測の開始時にGetTickCountで得られた値をnLastTickに保存しておき,CheckActionが呼ばれたときにGetTickCountで得られた値とnLastTickとの差分を計算してnIntervalを越えていないか確認します.
TickCountの値は49日でカウンタが一周してしまいますが, unsignedな変数を使っているので,結果が負数になることはありません.
タイマーで定期的に呼び出される箇所でこのメソッドを定期的に呼び出します.SetIntervalで設定された時間が経過しているとtrueが,まだ経過していなければfalseが返ります.呼び出し元では戻り値がtrueの時に何かを行うようにすれば定期実行が可能になります.
規定時間が経過してtrueを返したときは,そこから新たに計測を開始します.
タイマーの有効/無効を設定します.設定値の読み出しは IsEnabledで行います.
無効に設定されているときはCheckActionで必ずfalseが返ります.また,false→trueに設定を変更すると内部カウンタがリセットされてそこから時間のカウントが始まります.というよりも,リセットされたときと現在との差分しか見ていないので途中まで経過した時間の続きからという器用なことは出来ないのです.
実際にCPassiveTimerを使ってどのように自動保存が行われているかを説明します.
CEditDocクラスの1要素としてCPassiveTimerクラスのm_cAutoSaveが宣言されています.
共有データの値をm_cAutoSaveに設定するCEditDoc::ReloadAutoSaveParamがCEditDocのコンストラクタから呼び出されます.また,設定の変更メッセージ(MYWM_CHANGESETTING)を受けたときにはCEditWnd::DispatchEventから呼び出されます.
CEditDoc::ReloadAutoSaveParamでは間隔を設定してタイマーを有効にします.
コンストラクタでタイマーを有効にしてしまうと
1. 共有メモリに正しいデータが入っていない
1. 他のオブジェクトが初期化される前に呼び出されてしまう
といった危険性があるように思えますが,CEditWndが生成される前にWinMainで設定の読み出しが行われていることと,規定時間経過後の実行はCEditWndのタイマーメッセージが来て初めて行われることから,このような問題は起こらないと信じています.(弱い(^^ゞ)
定期的なタイマー呼び出しにより,CEditWnd::OnTimerが呼び出されます.この中からCEditDoc::CheckAutoSaveが呼ばれます.
CEditDoc::CheckAutoSaveではm_cAutoSaveのCheckActionを呼び出して戻り値をチェックします.戻り値がtrueのときは自動保存を一旦DisableにしてからSaveFileを呼び出し,保存終了後に再びEnableにします.保存時にDisableにするのは保存時にダイアログボックスが表示された状態で所定の時間が経過することによってSaveFileが二重に呼び出されるのを防ぐためです.