Macintosh Developer Online (MDOnline)


2001年7月3日発行号 - Quartzのプログラミング



YahooBBにさっそく申し込んでいたら、本申し込みOKのお知らせが、昨日の深夜にやってきました! もちろん、即座に本申し込みをしました。うちは、さいたま市のはずれです。旧浦和市で、新しいサッカースタジアムがそれほど遠くはないところですけど、こうしたネットワークサービスはけっこう対象外になっていたことが多く、半ばあきらめていました。だけど、えらいスピードで申し込みにたどり着けました。古くは、ODNの専用線がこちらの電話局までこなかったり、最近ではSpeedNetのエリア外になっていたりとはみだし領域だし、テレビの工事にきたおじさんは「産業道路よりこっちは街じゃないしなぁ」と言われるし(ローカルねたですみません)、ケーブルテレビが来たのが唯一の救いだったのですが、ADSLの勢いは半端じゃないというところでしょうか。実は、以前にも言ったように、ケーブルテレビが「ルータ不可」という体制に不満があるので、消費者としてとるべき唯一の抵抗として「解約」をしようとしているわけです。そこで、第一弾として、まずはアナログ電話の取りだしを2階の私の部屋にしたのですが、工事はあっさり終わり、おじさんと雑談する時間がありました。このあたりは電話局の密度が希薄なため町中といろいろ事情が違うみたいです。けっこう多くの家庭で、半分光ファイバー状態なんだそうです。道ばたにちょっとでかい程度の箱があって、実は電話局からそこまでは光ファイバーで結合されていて、その箱ってのが交換機だそうです。そこから家庭は銅線だそうですが、イメージ的には、道ばたの箱が昔だと電話局みたいなのだそうです。で、何と、心配なことに、うちも、途中まで光ファイバーなんだそうです。で、どうしてもADSLを通したいという家庭には、その道ばたの箱をバイパスして、電話局から直接銅線で配線したりするそうなんです。そういうわけで、ちょっと心配なのですが、とりあえずYahooBBの申し込みをしたので、NTTの調査結果を待ちたいと思います。その工事のおじさんによると、最近、電話局からけっこう離れたところにADSLを引いたのだけど、だめだったという経験があるそうです。ちなみにローカルネタで申し訳ないのですが、浦和市民病院あたりらしく、電話局からだと、5〜6kmくらいあるんじゃないかと思います。そうなると線の引き回しが長過ぎて、ADSLのリンクが取れず、導入をあきらめてもらうしかなかったそうです。やっぱり、いなかは不利ってことでしょうね。うちは、電話局から、2〜3kmほどだと思うので、大丈夫だと思うのですけどね。もっとも、半分光ファイバーでも関係なく使えるとかだとうれしいですが、どうなることやら。
(新居雅行 msyk@mdonline.jp


小池邦人のプログラミング日記》2001/7/3<Navigation Service 3.0を使う その4>

今回は、Navigation Service 3.0でのファイル保存ダイアログの話しです。Mac OS XでNavigation Service 3.0を使えば、ダイアログは親ウィンドウのタイトルバーから降りてくるSheet Windowとして表示できます。また、保存される画像ファイルには32文字以上のファイル名を付けられるように、処理ルーチンを改良してみます。

さっそく、ファイル保存のための各種ルーチンを追跡してみます。ファイルメニューから「保存...」や「別名保存...」が選択されると、まずはsaveImageWindow()ルーチンが呼ばれます。また、編集済み画像が保存されていない状態で、画像ウィンドウを閉じようとしたりアプリケーションを終了しようとしたりする時にも、このルーチンが呼ばれることになります。

 

この時点でユーザによるファイル名の入力が必要であれば、ファイル保存ダイアログを表示する必要があります。chkSysOSX()によるチェックで、アプリケーションの起動環境がMac OS Xと判断されれば、navMyPutFile()の代わりにnavMyPutFileX()ルーチンが実行されます。

 

まず最初に、NavGetDefaultDialogCreationOptions()でディフォルトのNavDialogCreationOptions構造体を得て、必要なパラメータを各メンバーに代入します。初期ファイル名(opt.clientName)やクライアント名(opt.clientName)はパスカル文字列ではなく、CFStringCreateWithPascalString()によりUnicode文字列を指し示すCFStringRefに変換してから代入します。ファイル保存ダイアログをSheet Windowとして表示させるためには、構造体のparentWindowメンバーに親ウィンドウのWindowRefを、modalityメンバーに「kWindowModalityWindowModal」を代入しておきます。

navMyPutFileX()の2番目の引数(kind)は、ファイル保存ダイアログをExport用に転用するための切り替えパラメータです。kind==1ならば、Export用のEventコールバックルーチンと、ダイアログの下に表示されるメッセージの文字列(opt.message)が用意されます(今回はExport用ダイアログについては詳しく言及しません)。構造体の準備ができたら、NavCreatePutFileDialog()で実際にダイアログを作成するのですが、その時の5番目の引数(inClientData)には親ウィンドウのWindowRefを渡すようにします。これにより、後述するEventコールバックルーチン内で、それを参照できるようになります。返されたNavDialogRef(dpr)をNavDialogRun()に渡すと、ファイル保存ダイアログがタイトルバーから降りてきます。

 

ダイアログが正常に表示されたら、setWNavDref()で各ウィンドウ毎に確保されているプライベート構造体へ、ダイアログのNavDialogRefを保存しておきます。

 

ここで、Mac OS XでのSheet Windowの挙動について、いくつかの注意項目をまとめておきます。まずは、Modal Dialogとは異なり、使わないメニューアイテムをハイライト表示に変える処理は自動では行われません。そのために、navMyPutFileX()ではdisableQuitMenu()ルーチンを使い「作業終了」アイテムを強制的にハイライトにしています。作業終了が繰り返されて、ファイアル保存の処理が重複してしまうのを避けるためです。Sheet Window表示後のメニューのメンテナンスは、menteMenu()ルーチンで行なわれます。

 

menteMenu()では、getWNavDref()でNavDialogRefの存在を調べ、親ウィンドウ上にSheet Windowが表示されているかどうかで処理を切り分けてます。メニューのメンテナンスについては、Event Handler内でCarbon EventのkEventCommandUpdateStatusを受けとり対処する方法もあるのですが、今回は旧方法をそのまま継続して使用してみました。

次の問題点は、現状のMac OS XではSheet Windowが降りても、親ウィンドウ側にはDeactivated Event(kEventWindowDeactivated)が送られてこない事です。Sheet Windowを引き上げた時には、ちゃんとActivate Event(kEventWindowActivated)が来るのにです??? そのため、navMyPutFileX()ではactControls()を使い強制的に親ウィンドウのスクロールバー(コントロール)をハイライトに切り替えています。また、Sheet Windowを表示した状態で親ウィンドウを後ろに回し、再度フロントへと切り替えると、ディフォルトのEvent Handlerが働いて親ウィンドウのスクロールバーがActiveになってしまいます。仕様なのかバグなのかは判断付きかねますが、Sheet Windowを表示している親ウィンドウの状態遷移については、Apple自身も整理しきれていないようです。加えて、現在のMac OS XのCarbon Event Managerは、ウィンドウに対するActivate Event(kEventWindowActivatedとkEventWindowDeactivated)を一度に2回送ってきます(笑)これらは絶対にバグでしょう。

navMyPutFileX()の処理から抜けると、Eventコールバックルーチンに制御が渡りますので、そちらに「保存」ボタンが押された時の処理を実装します。Navigation Service 3.0で利用するFilterやEventコールバックルーチンのエントリーポイントは、アプリ起動時に実行するsetUpNavi()でインストールしていることを前回説明しました。この内、ファイル保存ダイアログで使うEventコールバックルーチンは、navSaveEventProc()です。

 

ファイル保存ダイアログのNavDialogRefは、parm->contextに入っており簡単に参照することができます。また親ウィンドウのWindowRefの方は、3番目の引数であるNavCallBackUserDataに入っています。

引数で得たNavEventCallbackMessage(sel)が「kNavCBUserAction」と一致すれば、ユーザがダイアログ上のコントロールをクリックしたことになります。この時にparm->userActionも調べ、それが「kNavUserActionSaveAs」と一致していれば「保存」ボタンが押された事になります。NavDialogGetReply()でNavReplyRecord構造体(ファイル保存場所情報が含まれている)を得て、それをwriteImageWindowX()ルーチンに渡して画像ファイルを保存します。また、ユーザによりダイアログが閉じられた時には、NavEventCallbackMessageに「kNavCBTerminate」が入ってきます。NavDialogDispose()を呼び出してダイアログのワークエリアを開放し、プライベート構造体に保存しておいたNavDialogRefも削除してしまいます。getWNavFlag()で得たフラグ情報(こちらもプライベート構造体に保存されている)は、ファイル保存後の後処理を判断するのに使います。ウィンドウを閉じる時や作業終了時に、アラート表示ルーチンでフラグをセットしておけば、Sheet Windowを閉じた後に、親ウィンドウを閉じたりアプリを終了したりする処理を実行することができます。

ファイル保存を担当しているwriteImageWindowX()ルーチンは、以前に解説したwriteImageWindow()をNavigation Service 3.0用に改良した物です。

 

AEGetNthPtr()を使い、NavReplyRecord構造体よりファイル保存場所を示すFSRefを得たら、makePicture()でPICTデータを作り、savePictureFileX()ルーチンで実際にファイルへ書き出します。

 

savePictureFileX()ルーチンは、以前説明したsavePictureFile()を、32文字以上のファイル名に対応させるために改良した物です。現在のFile ManagerではCFStringRefを直接扱えるAPIはありませんので、先んじてCFStringGetCharacters()でバイト配列(UniChar)とバイト数(UniCharCount)に展開してから利用します(面倒くさい)。保存の前には、FSMakeFSRefUnicode()で同じ名称の消去すべきファイルがあるかどうかを調べ、存在していればFSDeleteObject()で消去します。引き続き、FSCreateFileUnicode()でファイルを作成し、返されたFSSPecを馴染みのAPIに渡して、ファイルオープンと画像データの書き込みを行います。FSCreateFileUnicode()はFSpCreate()とは異なり、ファイルタイプもクリエータも設定できませんので、ファイルを閉じた後にFSpSetFInfo()を使い追加設定しておくことを忘れないでください。

今回でNavigation Service 3.0の話しは一段落です。次回は、Mac OS Xでプリントアウトのための「用紙設定ダイアログ」と「プリントダイアログ」を、Sheet Windowとして表示させる方法を解説したいと思います。
[小池邦人/オッティモ]

関連リンク:オッティモ
カテゴリ:Carbon/CF, ユーザインタフェース, 小池邦人のプログラミング日記


Mac OS XのCore Graphicsのサンプルプログラムとドキュメントについて

サンプルプログラムとして、Core Graphics(Quartz 2D)の機能を使ったものが2つ新たに掲載された。Core Graphicsは、Mac OS Xに搭載された、基本的なグラフィックス描画を行うシステム機能である。CarbonあるいはCocoaから利用できるようになっているが、Carbonから使う場合にはMach-O形式のバイナリである方が便利だ。従来のMac OSではQuickDrawが基本グラフィックス機能を提供しており、Mac OS Xでも利用は可能だが、より高機能なCore Graphics機能の利用が今後は中心になると考えられる。
公開された2つのサンプルは、主に、Current Transform Matrix(CTM)を利用して画像を描画するというもの。実際の描画をCTMで記述した処理を施した結果として行うことができ、回転や変型などした結果を比較的簡単に描画できるというものである。

◇CTMDemo 1.0
http://developer.apple.com/samplecode/Sample_Code/Graphics_2D/CTMDemo.htm

このサンプルプログラムを実行すると、起動時に画像ファイルを選択するダイアログボックスが表示される。画像を選択すると、その画像が大きくなったり小さくなったり、あるいは円軌道上を移動したりといったアニメーションを見ることができる。CTMの定義とそれを適用した描画の部分がポイントとなるだろう。また、アルファチャンネルの処理といった部分も参考になると思われる。

◇CTMClip
http://developer.apple.com/samplecode/Sample_Code/Graphics_2D/CTMClip.htm

CTMClipは、CTMDemoと基本的は同じだが、描画領域に対してClipCGContextToRegionというAPIを利用し、描画をウインドウ全体ではなく、一部分に制限するといった機能を付加したものである。

以上のサンプルはCarbonアプリケーションである。タイマーイベントはCarbon Eventを使っているが、その他のイベントは従来方式である。ただし、グラフィック描画の部分とは切り離されているので、その部分は無視すればいいだろう。
なお、Quartz 2Dに関しては、以下のページにある2つのPDFファイルが資料として公開されている。「Quartz Primer」は、14ページの文書でQuartzの諸機能をまとめたものである。また、Carbonアプリケーションから利用についてはプログラムとともに解説されている。CFMベースのアプリケーションからQuartzを使う方法も掲載されているが、単にAPIコールするだけでなくフレームワークのロードなどが必要になりやや面倒なことが分かる。もう1つの文書「Drawing With Quartz 2D」は、比較的詳しい文書であるが、70ページの内容である。描画のパラメータや結果についての説明もあるが、APIの敢然な解説までは含まれていない。しかしながら、サンプルプログラムは比較的豊富に掲載されている。

◇Quartz 2D
http://devworld.apple.com/techpubs/macosx/CoreTechnologies/graphics/Quartz2D/quartz2d.html

以上のページ以外にはTechnical Q&Aに文書がいくつかあるものの、主だったドキュメントがとりあえずは見つからないので、後はヘッダファイルということになるだろう。Core Graphics関連のヘッダは、上記のサンプルプログラムだと、ApplicationServices.hに移動すれば、そこにCoreGraphics.hヘッダのインクルードを行っているところがある。さらに移動するとたくさんのヘッダがインクルードされているが、CGContext.hあたりが主要な部分だ。これらのヘッダではAPIの定義部分でいちおうの説明がある。なお、Appleの開発者向けドキュメントのサイトには、「Quartz Compositing」という項目もあるがどのページにもリンクはされていない。いずれにしても、Quartzに注目している人は、ドキュメントの公開動向にも注意を払っておくのがよさそうだ。

カテゴリ:アップルからの開発資料, グラフィックス


AppleWorks 6.2の英語版が正式にリリース、アップデートはフリー

統合文書作成ソフトのAppleWorks 6のMac OS X対応正式版がリリースされていた。これまでは、英語版のPublic Preview版のみが公開されていたが、Ver.6.2としてMac OS X対応正式版としてリリースされた。従来バージョンのAppleWorks 6からはフリーでアップデートでき、14MBほどのアップデータをダウンローすることでアップデートが可能だ。ただし、今回リリースされたVer.6.2は英語版のみであり、アップデータを含めて日本語版のAppleWorksには対応していない。新しい機能としては、Word 2001やExcel 2001のファイルフォーマットでの読み込みや書き出しに対応していることであるが、とにかくMac OS Xネイティブで稼動するというのがいちばんの変更点だろう。なお、AppleWorksのページではPDFファイルに印刷できるというメリットを記載しているが、これはMac OS Xのプリント機能にあるもので、AppleWorksに特別に組み込まれた機能ではない。
日本語版も早く用意してほしいという要望も持ってしまうところだ。いずれにしてもこの時期までかかっての正式版というのは、Carbon対応だからといって簡単にはMac OS Xネイティブなアプリケーションとしてリリースできるわけではないということを図らずも示したものと言えなくはないだろうか(もちろん、作業の都合上…という理由もあるのかも知れないのだが)。

関連リンク:AppleWorks
カテゴリ:文書作成アプリケーション


Core Graphicsの描画によりカレントパスはクリアされる

Core Graphicsでパスを何度も使って描画できるかという問いに対する解答がTechnical Q&Aに掲載されている。パスについては描画機能を使うとクリアされるようになっており、CGContextSaveGStateを使ってもカレントパスは保存されない。同一パスの描画を行うには、パスを改めて作りなおす必要がある。

関連リンク:QA1047:Drawing a Path Multiple Times
カテゴリ:Technical Q&A, グラフィックス


CoreGraphicsの状態はAPI呼び出しにより変更することもある

Core GraphicsのAPIを使った後に、Core Graphicsの状態が変化しているという問いに答えたTechnical Q&Aの文書が掲載された。たとえば、CGContextFillRectWithWidthといったAPIは呼び出し後はカレントパスがクリアされ、線の幅が変化するなど、状態は変化するのが仕様となっている。もし、状態を保持したければ、CGContextSaveGStateを使い、CGContextRestoreGStateでもとに戻すという処理を組み込まなければならない。

関連リンク:QA1045:Unexpected CG state changes
カテゴリ:Technical Q&A, グラフィックス


CGContextの境界を取得する方法について

Technical Q&Aに、CoreGraphicsのCGContextに関する境界についての文書が掲載された。本来はCGContextには境界という考え方はないが、ウインドウやあるいはオフスクリーンのビットマップには境界が存在することになる。CreateCGContextForPortによってCGContexを作った場合には、GetPortBoundsを利用して境界を取得することができる。

関連リンク:QA1048:CGContext Bounds
カテゴリ:Technical Q&A, グラフィックス


TIL》Mac OS Xでソフトウエアアップデート後に起動に時間がかかるようになる場合の対処

Mac OS Xでソフトウエアアップデートを行った後に、起動に時間がかかる場合があることについての文書が掲載された。起動時、Macのロゴマークが出た後、起動のプロセスに入るまでに長い時間がかかってしまうようになってします。そうした場合の対処法が手順で示されている。Mac OS 9.1のCD-ROMで起動して、起動ディスクの選択を行う手順が記載されている。

関連リンク:Mac OS X 10.0: Reselecting Startup Disk May Be Necessary Following Update
カテゴリ:Knowledge Base(旧TIL), Mac OS X