クローズボックスをクリック→名前を付けて保存ダイアログを表示→キャンセルをクリックした時終了しないようにするには?

解決


よっちゃん  2004-03-11 10:42:42  No: 7642

テキストエディタを作っているのですが、新規ファイルの編集後、クローズボックスをクリックすると名前を付けて保存ダイアログボックスを表示して保存をクリックで保存ができるようにはなったのですが、キャンセルをクリックした時、テキストエディタが終了しないようにすることはできるのでしょうか?どうすればよいでしょうか?


にしの  2004-03-11 18:15:40  No: 7643

メインフォームのOnCloseQueryイベントで、CanCloseをFalseにすれば終了しなくなります。
保存ダイアログを出すのも、こちらのイベントにしましょう。

ただし、新規ファイル編集後(未保存状態)、Windowsのログオフ/シャットダウン/再起動した場合には、OnCloseQueryは効きません。
この場合は、WM_QUERYENDSESSIONメッセージを取得して処理します。


よっちゃん  2004-03-12 00:46:19  No: 7644

にしのさんありがとうございます。私、数日前からDelphiを始めた初心者で、他のプログラミングも経験ありませんのでご容赦下さい。

現在、
・アクションリストにFileSave(上書き保存)、FileSaveAs(名前を付けて保存)を新規追加。
・メインメニューに上書き保存、名前を付けて保存を追加。
・FileSave、FileSaveAsのOnExecuteイベントにコードを記述。
上書き保存procedure TForm1.FileSaveExecute(Sender: TObject);はFileNameが無題の時FileSaveAs.Execute、そうでない時Lines.SaveToFile。
名前を付けて保存procedure TForm1.FileSaveAsExecute(Sender: TObject);はSaveDialog1.Execute…。
・メインメニューの上書き保存、名前を付けて保存のActionでそれぞれFileSave、FileSaveAsを選択。
・procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);はRichEdit1.Modifiedでメッセージボックス(はい、いいえ、キャンセル)を開き「キャンセル」はCanClose := False、「はい」はFileSave.Execute。
となっています。

保存ダイアログを出すのも、こちらのイベントにしましょう。ということは、メッセージボックス「はい」でFileSave.Executeではなく、FileSaveとFileSaveAsのコードをprocedure TForm1.FormCloseQueryにも書かないとダメということでしょうか?そしてSaveDialog1.Executeでない時CanClose := Falseを書き加えればいいのでしょうか?


にしの  2004-03-12 02:37:11  No: 7645

いいえ、Save, SaveAsのイベントはそれぞれ必要です。
閉じるときに、キャンセルされたら閉じない、という処理が必要なのですから。
Save, SaveAsではキャンセルされても問題ないと思いますが、閉じるときだけ必要になります。

保存用の関数を用意したほうが便利です。
以下がサンプルです。
# 動作チェックはしていません。間違いがあるかも。

function TForm1.FileSave(const AFileName: String): Boolean;
var
  FileName: String;
begin
  FileName := AFileName;
  // ファイル名が''であれば新規
  if FileName = '' then
  begin
    if SaveDialog.Execute then
    begin
      FileName := SaveDialog.FileName;
    end;
  end
  else
  begin
    //キャンセルされた
    Result := False;
    Exit;
  end;

  //ファイルに保存する
//****ここでファイル保存の記述をする****

  //正常に終了
  Result := True;
end;

FileSaveExecuteでは、ファイル名を引数にしてこの関数を呼ぶだけです。
FileSaveAsExecuteでは、''を引数にして呼びます。
FormCloseQueryでは、この関数を呼んだあと、戻り値を見てキャンセルされたら(Trueが返ってきたら)CanCloseをFalseにすれば閉じません。


にしの  2004-03-12 02:38:15  No: 7646

「いいえ」じゃなかった。
CloseQuery時にも必要です、と言いたかったんです。


たかみちえ  URL  2004-03-12 03:23:47  No: 7647

わたしがおすすめの方法は…。

・FileSave関数を作る(ファイル名があったら上書き保存 なかったらFileSaveAsを呼び出す)
・FileSaveAs関数を作る(ファイルの保存ダイアログを出して、保存する)

・CloseQueryイベントでは、FileSaveを呼び出す。

procedutre FormCloseQuery(略)
begin
  FileSave;
  CanClose := not Editor.Modified;
end;

  このようにすれば正常に保存されたらModifiedがFalseになるので、
CanCloseはTrue、結果フォームは閉じます。
保存されてなければ、ModifiedはTrueのまま(変更されてる状態)なので、
CanCloseはFalseになり、閉じません。
そもそもより変更がされていないときは、ModifiedはFalseのままなので、
もちろん閉じます。

※  FileSave(As)関数で保存が成功したとき、およびファイルを開く関数でファイルを開いたときには、
ModifiedをFalseにすることをお忘れなく!
  できれば保存と開く処理は全て最終的に同じルーチンを呼び出すようにすると望ましいです。
(ModifiedプロパティをFalseにして、必要なら保持しているファイル名を置き換えるというルーチンを)


たかみちえ  URL  2004-03-12 03:26:06  No: 7648

CloseQuery関数は
procedutre FormCloseQuery(略)
begin
  if Editor.Modified then FileSave;
  CanClose := not Editor.Modified;
end;
  のほうがいいですね。(変更がされてなければ、そのまま終了)


よっちゃん  2004-03-13 05:00:23  No: 7649

にしのさん、たかみちえさん、ありがとうがざいます。

とりあえず↓でできました。
  FileSave.Execute;
  CanClose := not RichEdit1.Modified;

私は関数を作るということが解りません。どこに、どう書けばいいのか、引数にして呼ぶとはどういうことなのか…。もう少し勉強します。

とりあえず終了しないようにできましたので、[[解決]]ということに…。

他にも教えてもらいたいことがあるのですが(リッチエディットを使用しているので、.rtfは書式付き、.txtは書式無しで保存…)、もう少し勉強して出直してきます。

お二方ともどうもありがとうがざいました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加