● ToolBox API徒然草(2007/05/13)

  このニュースは、MOSAの会員にのみ配布されているデベロッパー向けの
  デジタルマガジンMOSADeNのに掲載された記事です。ほぼ一ヶ月遅れで
  ここに掲載されて行きます

 〜 Carbonモダンアプリケーションへの道(その14) 〜


今回からCarbonのファイルシステムについて解説します。こちらもテキストやグラフィックスに負けず劣らず、時代と共に変貌してきた経緯があります。はたしてファイルシステムは、どの程度モダン化されたのでしょうか?

ファイルシステムの話を始める前に、前回解説した印刷関連の内容に訂正があります。前回「CFArrayCreate()とPMSessionSetDocumentFormatGeneration()の手続きを加えないとCoreGraphics APIでの描画が印刷に反映されない」「Mac OS X 10.5では修正して欲しい」と書いたのですが、MOSAメンバの方からご連絡が有り、この「呪文」は、すでにMac OS 10.4で解消されていることが判明しました(笑)。ご連絡、有り難うございました。

具体的には、前回最後のサンプルの「呪文的」手続き箇所とPMSessionBeginDocument()をPMSessionBeginCGDocument()に置き換え、引き続いてPMSessionGetGraphicsContext()をPMSessionGetCGGraphicsContext( )に置き換えればOKとなります。すべてを正しく書き直すと以下の様になります。大変すっきりしましたね。ちなみに、両APIはヘッダファイルのPMApplication.hに定義されています。



ただし、PMSessionBeginCGDocument()とPMSessionGetCGGraphicsContext()は、Mac OS X 10.4以降でしか使用できませんので、Mac OS X 10.3も動作環境対象となっているアプリケーションでは、前回のソースコードを使うしか手はありません。御注意ください。また試した結果、SetPortTextFont()やSetPortTextSize()など、CGrafPortの参照が必要な描画関連APIは、引数のCGrafPtrにNULLを渡せば正常に動作するようです。

ところで、PMSessionGetCGGraphicsContext()でCGContextRefを得てCoreGraphics APIで描画を行う場合、用紙矩形領域の左下が原点(PostScript同等)となります。通常プリンタの印刷可能形領域は用紙矩形領域よりも狭いですので、原点付近に描画した文字や画像は途切れてしまう可能性があり、注意が必要です。

これとは異なり、QuickDraw環境では用紙矩形領域ではなく印刷可能領域の左上が原点となります。用紙矩形領域をPMGetAdjustedPageRect()で得て、その矩形を考慮して描画すれば、ちゃんと用紙内に印刷結果を納めることができます。CoreGraphics環境では、描画する前に、用紙矩形領域の原点まで座標系を平行移動させておくと便利かもしれません。

話をファイルシステムに戻しましょう。ファイルシステムを考える上で、まず最初に確認しておくべきことは、ファイルを参照するための「リファレンス」に何を使うかと言う事です。Mac OS 9の時代であればFSSpec構造体(今でも使えるが...)がそれに相当していましたが、現在ではFSRef構造体を使うことが強く推奨されています。

ヘッダファイルのFiles.hを参照すると、FSSpec構造体は以下の様な構造体メンバを持っていることが分かります。



このうちStrFileNameはStr63と同一で、具体的にはStr63[64]と定義されていますから、ファイル名は63バイト以内でしか管理できません。またファイル名のエンコーディングはShift-JISに固定されておりユニコード文字列の扱いも不可です。続いて、FSRef構造体の方を調べてみると、以下のように定義されています。



構造体サイズが80バイトであることは理解できますが、その中身がどのように利用されているのかはオープンにされていません。

現在、FSSpec構造体を引数で渡すファイルアクセス関連APIは、すべてDEPRECATED指定となっています。例えば、ファイル作成に使うFSpCreate()や削除に使うFSpDelete()などもそのうちの一つです。ただし、古いアプリケーションの特定の便宜を図るために、FSSpec構造体をFSRef構造体へコンバートするFSpMakeFSRef()などの一部のAPIは、DEPRECATED指定にはなっておらず、そのまま継続して使用することが可能です。

extern OSErr FSpMakeFSRef(const FSSpec *source, FSRef *newRef)

File.hに定義されているファイルシステム関連のAPIでなくても、FSSpec構造体でファイルを参照するAPIはDEPRECATED指定のものが多いので注意してください。そうしたAPIについては、FSRefで参照する代用APIが必ず存在しています。例えば、Folder.hにはシステムで管理しているフォルダを探し出すAPIが定義されていますが、一昔前にはFindFolder()を利用していました。



このAPI、FSSpec構造体を渡す必要はないのでDEPRECATED指定にはならず生き残っていますが、代わりとしてFSRef対応のFSFindFolder()というAPIがちゃっと存在しています。



例えば、システム起動ボリュームにあるデスクトップフォルダのFSRefを得たい場合には、以下のように記述してやればOKです。

FSRef fsref;

FSFindFolder( kOnSystemDisk,kDesktopFolderType,kCreateFolder,&fsref );

CoreFoundation中には、特定のファイルやフォルダを参照するために、FSRefではなくてCFURLRefを用いるAPIがあります。例えば、アプリケーションバンドルのResourcesフォルダ内にアクセスするためにはCFBundleCopyResourceURL()を利用しますが、このAPIはファイル参照用としてCFURLRefを返してきます。しかし、CFURLRefのままだとファイルアクセスが面倒ですので、CFURLRefをSFRefに変換するCFURLGetFSRef()というAPIがCFBundle.hに用意されています。CFStringRefで名称を指定したResourcesフォルダ内ファイルのFSRefを得るには、以下の様に処理します。



次回は、FSRefで参照したファイルやフォルダ(ディレクトリ)への基本的なアクセス(作成、書き込み、読み込み、削除など)について調べてみたいと思います。

copyright 2007 Ottimo, Inc. All rights reserved
無断転載・引用禁止