タイトル【Carbon化シリーズ】Navigation Serviceでファイル保存ダイアログ(1)カテゴリーCarbon/CF, Carbon化
作成日2000/6/27 0:31:21作成者新居雅行
今回から3回に渡って、保存ダイアログボックスのNavigation Service対応を紹介することにするが、ここまでで見てきたファイルを開くダイアログボックスのNavigation Serviceを踏まえた内容となるので、場合によってはそちらも参照してもらいたい。

ファイルを開くときにはファイルの選択だけできればいいが、ファイルの保存ではファイル名の入力が必要になり、必然的に異なるデザインのダイアログボックスを表示しないといけない。そこで、Navigation Servicesでは、NavPutFileというAPIコールを用意しており、それによって、ファイル保存のダイアログボックスが表示される。パラーメータの引き渡しや取り出しなどは、NavGetFileの場合とは基本的に変わらない。また、イベント処理のコールバックルーチンを利用しないとモーダルなダイアログボックスになるのも同様である。ということで、別掲のDoSaveCommand関数を参照していただきたい。この関数は、TextDraw IVのソースでは、DoCommand.cにある。FileメニューのSaveを選択した時に、イベントループからこのDoSaveCommandが呼び出されて、実際の処理を行う。ファイルを開く時の処理だと、まだ文書内のデータ処理とは分離されているが、保存の場合はそういうわけにはいかないため、プログラムが少しややこしくなっている。その点も踏まえて、ソースを見てもらいたい。

プログラムの最初の部分は、書類のウインドウが存在するかを確かめ、さらに文書ごとの情報を保存している構造体へのハンドルを取得して、後の処理に備えている。NavPutFileでも、やはりNavDialogOptions型構造体のデータを、最初に指定しておく必要がある。とりあえずデフォルトでいいので、NavGetDefaultDialogOptionsを利用して構造体を初期化する。ただし、ダイアログボックスのファイル名の部分に最初から入力されている文字列はこのままだと「名称未設定」になる。これでも支障はないのだが、たとえば別の文字列にしたいという場合には、プログラムにあるように、NavDialogOptions型構造体のメンバーsavedFileNameに文字列として任意に文字を指定する。ここでは、Pascal文字列ではなくC文字列としてしている点には注意が必要だ。NavDialogOptions型構造体は、NavPutFileの3つ目の引数として指定する。

保存するフォルダを指定するダイアログボックスでは、最初に表示されるフォルダを指定できる。そこで、そのフォルダは無条件に「書類」フォルダにしたいとしよう。その場合には、FindFolderでまずは「書類」フォルダへのファイル参照を得ておく。FindFolderの2つ目の引数にkDocumentsFolderTypeを指定すると「書類」フォルダを検索できる。FindFolderの結果から「書類」フォルダのFSSpec構造体を作成し、さらに、AECreateDescで、FSSpecのディスクリプタを構成しておく。これをNavPutFileの1つ目の引数に指定する。
NavPutFileでは合計7つの引数を指定する。2つ目にはダイアログボックスでの選択結果を取得するためのNavReplyRecord型構造体へのポインタを指定するのは、NavGetFileと同様だ。4つ目の引数にはイベント処理プロシージャへのユニバーサルポインタを指定する。これもNavGetFileと同様だ。イベント処理のプロシージャはシステム側からコールバックされるものであるが、その基本的な形式はNavGetFileと同様である。ここでは、NavGetFileで使用した“特になにもしないイベント処理関数”をそのまま指定した。

一方、NavPutFileでは、5つ目と6つ目の引数にファイルタイプとクリエイタを指定する。これらは、ファイルのフォーマットを指定するポップアップメニューで出てくる項目名を決定する。ここではTextDrawの文書のタイプとクリエイタを指定したが、そうすることで、文書のFinder情報の「種類」と同じ文字列が、ダイアログボックスのファイルフォーマットのポップアップメニューで項目として設定されるのである。7つ目の引数にはユーザーデータを指定するが、これを使った例は2回後に出てくる。

さて、NavPutFileの呼び出し後には2つ目の引数に指定したNavReplyRecord型構造体でユーザのダイアログボックスでの反応がすべて分かるようになっているのだが、それはNavGetFileと同様だ。その構造体のvalidRecordというメンバと、NavPutFileの戻り値がエラーでないことを確認することで、正しくファイルが指定されたことが分かる。なお、NavReplyRecord型構造体のメンバreplacingから、既存のファイルと同じファイル名を指定したことも分かる。
指定したファイルに関する情報は、NavReplyRecord型構造体のselectionメンバにディスクリプタのリストの形式で入力されている。ファイルを開く場合には複数のファイルが指定されたことを仮定しないといけなかったが、NavPutFileだと1つのファイルの指定しかないはずなので、AEGetNthPtrでディスクリプタのリストの最初の項目をFSSpec型として取り出す。これが、ダイアログボックスで選択したファイルのファイル名やフォルダなどの情報が含まれているFSSpec型構造体である。そして文書の内容を、指定したファイルに保存しているのが、SaveToFile関数である。その後、文書情報の構造体を更新したり、ファイル名をウインドウのタイトルに設定する行が続いている。
最後に、NavDisposeReplyを使ってNavReplyRecord型構造体を破棄すると共に、AEDisposeDescを使って作成したディスクリプタを破棄している。

以上のように、NavPutFileの使い方も、一部を除いてNavGetFileとあまり違いはない。実際には次のようなダイアログボックスが表示される。フォーマットのポップアップメニューでは、TextDrawのネイティブな文書フォーマットを示す文字列と、「ひな形オプション」の選択肢がある。

◇表示された保存するファイルを指定するダイアログボックス


「ひな形オプション」を選択すると、書類かひな形かを選択するダイアログボックスが表示される。ダイアログボックスでひな形を選択したかどうかは、NavPutFile実行後にNavReplyRecord型構造体のisStationaryメンバで参照できるが、TextDrawのプログラムはそこまではきちんと処理を組み込んでいない。ひな形対応は、Save Asで組み込んだので、Carbon化シリーズの2回後の記事で紹介する。いずれにしても、ステーショナリに対応するくらいは、NavPutFileは特にカスタマイズらしいことをしなくてもすむということは、今後のアプリケーション設計では知っておくべきことと言えるだろう。
関連リンクInside Carbon: Navigation Services