2006-09-12
目次
MOSA理事コラム 第7回 「Macと書籍と私」
小林 正明 株式会社毎日コミュニケーションズ
今朝は両のふくらはぎが攣ってしまい、泣きながら目覚めました。開けっ放しの窓から入ってくる涼しい秋風さんのお陰です。季節の変わり目。皆様もお身体をご自愛ください。
さて、世の中は早くも年末商戦に向け準備が進んでいる状況です。アップルさんもまた然り。おそらく本コラムの配信日には、米アップルPRが「期待してくれてよい」と太鼓判を押すだけのことはある何かが発表になっていることでしょう。それがなんなのかは今現在まったくわかりませんが、そう言われたらもうただただページを空けてお待ち申し上げるほかありません。ありがとうアップルさん!
前置きはこのぐらいにして申し遅れましたがわたくし、Macプラットフォームの月刊誌『Mac Fan(マックファン)』で編集をしております小林正明と申します。コバヤシマサアキ。正しく明るい子に育てと両親が名付けてくれました。ちなみに姉はキヨミです。清く美しく。名は体を表わすと言いますが、子は思うにままならないものです。
すみません、本題行きます。
Macの知識とスキルに関しては自信を持ってNOといえるほど低レベルな私ゆえ、モサ会員の皆様を前にしてプログラミングに関する能書きを垂れることはできません。なので今回は「Macと書籍と私」をテーマに話を進めたいと思います。
私の雑誌編集歴は今年で丸8年。その間、他社を渡り歩いたわけでも、他誌を渡り歩いたわけでもなく、幸か不幸かずっとMac Fanに携わってきました。その間、何冊かのムックや雑誌を並行した経験はあれど、書籍の編集経験は一度もなし。人間、未経験なことに対する欲求は何歳になってもあるものです。10月から弊社の来期がスタートしますが、来期こそは是非ともその経験をしたい。そして、どうせやるなら初打席初ホームラン! みたいな夢もあったりするわけです。ちなみに弊社の今期ベストセラーは『おいでよ!どうぶつの森』攻略本。そろそろ60万部に届く勢いです。えー、まあそれは無理として、今期、180点ほどの書籍が刊行された中で、コンピュータ関連でのベストセラーは『30日でできる OS自作入門』の●万4000部。これを越せるであろうテーマ選びが目標です。
そんな折、なんの因果か私の手元に一冊の翻訳本話が舞い込んできました。Mac OS Xに関するかなりディープでしかも開発者のバイブルにもなりうるであろう書籍です。残念ながら書名は大人の事情で明かせませんが、とりあえず来月の湘南セミナーに持っていこうと思います。厚さが10センチほどあるので翻訳には一年がかりになりそうですが、ご興味のある方はこっそり「どんな本?」と私に声をかけてください。お見せします。ご意見頂戴できますと幸いです。「翻訳したい」もよし「コレは売れないよ」と耳打ちしてくれるもよしです。丸坊主にヒゲ面でメガネの風貌。イケメンと言われたことは、不本意ながらありません。
ビバ!ベストセラー、アミーゴ!Macintosh!
【プロフィール】
小林正明(こばやしまさあき)
1968年生まれ。2003年8月よりMac Fan編集長。川崎溝ノ口近辺で真剣に「良い土地を安く」探しています。現金はほとんどありません。
「Wonderful Server Life」 第18回 田畑 英和
〜DNS編〜
前回から「サーバ管理」を使ってDNSサービスを設定する方法を解説していますが、今回はゾーンの設定について解説します。今回は以下のような架空のドメインを使って実際の設定の流れをみていきたいと思います。
・解説用の架空ドメイン
ドメイン:example.com
・DNSサーバの名前とIPアドレス
名前:server.example.com
IPアドレス:192.168.0.1
◇ゾーンの設定
前回解説しましたように、DNSのゾーンを編集するには「サーバ管理」からサーバに接続し、「DNS」>「設定」>「ゾーン」の順でクリックしてゾーンの編集画面を表示します。
初期状態ではゾーンは存在しませんので、まずはゾーンを新規に追加します。「ゾーン」画面の左下の「+」ボタンをクリックすると新規にゾーンを作成することができます。「+」をクリックするとゾーンの編集画面が表示されますので、ここでは次のようにパラメータを入力します。
・ゾーンの設定パラメータ
ゾーン名:example.com.
サーバ名:server
サーバのIPアドレス:192.168.0.1
・ゾーンの編集画面
http://homepage.mac.com/htabata/MXS10.3/img/DNS/DNS_04.png
「ゾーン名」はドメインの名前を入力しますがここでは最後に「.」を付けて入力します。DNSの名前空間はゾーンのツリー階層で構成されていますが、最後の「.」により「com」がトップレベルのドメインとして認識されます。
「サーバ名」はDNSサーバ(つまり今設定を行っているサーバ)のホスト名を入力します。初期設定の解説で、MacOS X ServerはDNSのホスト名をDNSサーバを参照することにより動的に設定すると説明しました。ですので、ここでホスト名を手入力するのは矛盾しているようにも思えます。しかし自分自身をDNSサーバとして参照するようにすればよいわけです。つまり、自分自身のサーバ上で稼働しているDNSサービスを利用してホスト名を動的に設定するのです。「サーバのIPアドレス」では、サーバマシンに割り当てたIPアドレスを指定します。ここで指定したIPアドレスが「サーバ名」と対応付けられます。
設定パラメータではそのほかに、「管理者のメールアドレス」や「ゾーンの有効期間」を設定します。DNSサーバはほかのサーバの情報をキャッシュする仕組みを備えていますが、「ゾーンの有効期間」でキャッシュにデータが存在する期間を指定することができます。
ゾーンの追加を完了させるには最後に右下の「保存」ボタンをクリックします。追加したゾーンの情報は/var/named/にゾーンデータファイルとして保存されます。今回の例ですと次のようなゾーンデータファイルが保存されます。
・正引き用のゾーンデータファイル
/var/named/example.com.zone
・逆引き用のゾーンデータファイル
/var/named/db.192.168.0
ちなみにMac OS X Serverが提供するDNSサービスにはBINDを使用しています。BINDとはBerkeley Internet Name Domainの略で、その名のとおりバークレーでBSDのために開発されたDNSの実装です。このBINDはもっとも普及しているDNSの実装であり、ゾーンデータファイルはBINDによって参照されます。Mac OS X Serverの場合「サーバ管理」を使えばゾーンデータファイルを直接編集することなくDNSの管理ができるようになっています。
逆に、BINDの知識があればゾーンデータファイルを直接参照することにより、「サーバ管理」がどのようにパラメータを管理しているかも分かるということになります。またBINDは/etc/named.confを設定ファイルとして参照します。この設定ファイルにはDNSのゾーンに関する情報などが書き込まれています。
ゾーンの編集画面は「一般」と「コンピュータ」の2つに分かれています。「一般」ではさきほど説明したゾーンの編集を行います。
DNSサーバはゾーン単位で複数のコンピュータのホスト名とIPアドレスの対応関係を管理します。「コンピュータ」画面では、ゾーン内で管理しているコンピュータの一覧を確認できます。ゾーンを追加した直後ではDNSサーバのみが登録された状態になります。このコンピュータの一覧画面では各コンピュータのホスト名とIPアドレスが表示されます。
・ゾーン内のコンピュータ一覧
http://homepage.mac.com/htabata/MXS10.3/img/DNS/DNS_05.png
さて、これで1台(サーバ自身)のコンピュータのみを登録したDNSサーバの設定が完了しました。あとは「サーバ管理」のツールバーから「サービスを開始」をクリックすると、DNSサービスを開始することができます。つまり、ネットワークを経由してほかのマシンからの名前解決のリクエストを受け付ける事ができるようになったわけです。
自分自身をDNSサーバとして参照する場合には、ネットワークのDNS設定を確認し(自分自身をDNSサーバとして設定しているか)、ここで一度サーバを再起動します。そして再起動後に「ターミナル」を使って、ホスト名がDNSを参照することにより動的に設定されたことを確認します。ホスト名の確認を行うには”hostname”コマンドを使用します。今回の例ですと以下のような出力結果になればOKです。
・hostnameコマンドの使用例
% hostname
server.example.com
さて、今回はDNSのゾーンを設定する方法を解説しました。次回はゾーン内にコンピュータを追加する方法を解説いたします。
つづく
小池邦人のCarbon API 徒然草(2006/09/08)
〜 Carbonモダンアプリケーションへの道(その3) 〜
自作アプリケーションのメイン処理の中心として活躍していたAPIが突然消えてしまったら、デベロッパーは途方にくれてしまいます。そうした事態を避けるために、Apple社は何年かかけて少しずつ代用APIを準備してきました。今回は、そうした代用APIを取り上げ調査してみたいと思います。
その規模がちょうど良いので、まずは「Drag Manager」という割と渋めの箇所から攻めてみることにしましょう(笑)。Drag Mangerは、あらゆる種類のオブジェクト(ファイル情報、アイコン、画像など)のドラッグ&ドロップの仕組みを提供しているマネージャです。Finderでアイコンをドラッグして別の場所へドロップする場合なども、Drag ManagerのAPIが利用されています。随分と昔から存在しているAPI群ですが、関連ヘッダファイルのDrag.hを調べてみると、DEPRECATED指定されているAPIはたったひとつだけです。
この事から、Drag ManagerはMac OS X 10.4以降でも生き残るようなのですが、今ひとつ最新のCarbon Eventの仕組みとマッチしていない感じもあります。また、ファイル情報をドラッグ&ドロップで渡す場合に、必ずFSSpec構造体を使う仕組みとなっており、未だにFSRefに対応していません。この様に、生き残る事自体に対して色々と疑問点は残りますが、これもシステムの進化の「都合」のひとつなのでしょうか(笑)。
Drag Managerで、唯一DEPRECATED指定を受けたAPIは、以下のSetDragImage()です。通常Mac OS Xでは、画像データをドラッグする時に「半透明の画像」が表示されますが、それを作成するためのAPIです。
OSErr SetDragImage(
DragRef inDrag,
PixMapHandle inImagePixMap,
RgnHandle inImageRgn,
Point inImageOffsetPt,
DragImageFlags inImageFlags );
APIに渡す引数の中に、QuickDrawで使っていたPixMapHandleやRgnHandleがあるので、まあDEPRECATEDとなっても仕方がないでしょう。これの代用APIとして、Mac OS X 10.2から追加されたのがSetDragImageWithCGImage()です。画像データとして、PixMapHandleの代わりにCoreGraphicsで用いるCGImageRefが利用されています。
OSStatus SetDragImageWithCGImage(
DragRef inDrag,
CGImageRef inCGImage,
const HIPoint * inImageOffsetPt,
DragImageFlags inImageFlags );
ちなみに、ImageWellコントロールに貼り付けたPicture画像をPixMapHandleに変換してからSetDragImage()に渡すルーチンは、以下のようになります。
short createImageMyDrag( WindowRef window,DragReference dref,ControlRef chd,
RgnHandle rgn,GWorldPtr *gptr )
{
Rect srt,drt,frt;
short chk,err=1;
PicHandle pict=NULL;
GWorldPtr cptr;
GDHandle ghd;
PixMapHandle phd;
Point pt1;
GetGWorld( &cptr,&ghd );
SetPortWindowPort( window );
if( IsControlActive( chd ) ) // ImageWellコントロールはアクティブか?
{
GetControlBounds( chd,&drt ); // コントロールの矩形枠を得る
pt1.h=drt.left; // ドラッグ開始座標の設定
pt1.v=drt.top;
LocalToGlobal( &pt1 ); // 矩形枠の左上をグローバル座標へ変換
if( ! getMyControlWellPict( chd,&pict ) ) // 表示画像のPicHandleを得る
{
OffsetRect( &drt,-drt.left,-drt.top );
getPictureBounds( pict,&srt ); // PICT画像のフレーム枠
OffsetRect( &srt,-srt.left,-srt.top );
fitRect( 1,&drt,&srt,&frt ); // 矩形枠調整用の自作ルーチン
if( ! NewGWorld( gptr,32,&drt,NULL,NULL,0 ) ) // GWorldを作成
{
phd=GetGWorldPixMap( *gptr ); // GWorldのPixMapHandleを得る
SetGWorld( *gptr,NULL ); // 描画対象をGWorldに
LockPixels( phd ); // PixMapHandleをロック
EraseRect( &drt ); // 白色でペイントする
DrawPicture( pict,&frt ); // PICT画像を描画する
UnlockPixels( phd ); // PixMapHandleをアンロック
SetGWorld( cptr,ghd );
RectRgn( rgn,&drt ); // GWorld矩形枠のRegionを作成
err=SetDragImage( dref,phd,rgn,pt1,kDragDarkTranslucency );
} // ドラッグ用半透明画像として登録
}
}
return( err );
}
SetDragImage()にはPicHandleを直接渡すことはできませんので、NewGWorld()でオフスクリーン(GWorld)を作成し、そこにPicture画像を描画することで、PixMapHandleを得ています。GWorldPtrとRgnHandleはドラッグ終了後に削除する必要がありますので、引数で受け取るようになっています。上記ルーチンをSetDragImageWithCGImage()を用いる方法に書き直すと、以下のように簡単になります。
short makeDragCGImage( WindowRef window,DragReference dref,ControlRef chd,
Point pt )
{
CGImageRef image=NULL;
short err=1;
HIPoint hpt;
Rect drt;
if( IsControlActive( chd ) ) // ImageWellコントロールはアクティブか?
{
GetControlBounds( chd,&drt ); // コントロールの矩形枠を得る
hpt.x=(float)drt.left-pt.h; // クリック位置を矩形枠相対で渡す
hpt.y=(float)drt.top-pt.v;
if( ! getMyControlWellCGImage( chd,&image ) ) // 画像のCGImageRefを得る
err=SetDragImageWithCGImage(dref,image,&hpt,kDragDarkTranslucency);
}
return( err );
}
GetImageWellContentInfo() APIを用いれば、ImageWellコントロールから画像データを得ることが可能です。引数で渡すControlButtonContentInfo構造体のControlContentTypeの設定内容により、得られる画像データとしてPicHandleやCGImageRefなどを選択することができます。当然、これらの画像データは、先んじてその形式でImageWellコントロールに付加されている必要があります。そちらの作業には、SetImageWellContentInfo() APIを用います。
struct ControlButtonContentInfo {
ControlContentType contentType;
union {
SInt16 resID;
CIconHandle cIconHandle;
Handle iconSuite;
IconRef iconRef;
PicHandle picture;
Handle ICONHandle;
CGImageRef imageRef;
} u;
};
GetImageWellContentInfo()とこの構造体を用い、ImageWellコントロールからPicHandleを得るためのgetMyControlWellPict()ルーチンは以下の様になります。
short getMyControlWellPict( ControlRef chd,PicHandle *pict )
{
ControlButtonContentInfo info;
*pict=info.u.picture=NULL;
info.contentType=kControlContentPictHandle; // 画像タイプはPicHandle
if( ! GetImageWellContentInfo( chd,&info ) )
{
if( info.contentType==kControlContentPictHandle )
*pict=info.u.picture;
}
if( *pict )
return( noErr );
return( 1 );
}
同様に、CGImageRefを得るgetMyControlWellCGImage()ルーチンは以下の通りです。
short getMyControlWellCGImage( ControlRef chd,CGImageRef *image )
{
ControlButtonContentInfo info;
*image=info.u.imageRef=NULL;
info.contentType=kControlContentCGImageRef; // 画像タイプはCGImageRef
if( ! GetImageWellContentInfo( chd,&info ) )
{
if( info.contentType==kControlContentCGImageRef )
*image=info.u.imageRef;
}
if( *image )
return( noErr );
return( 1 );
}
ところで、ヘッダファイルのControls.hでは、ControlButtonContentInfo構造体のメンバの一部の使用(pictureやiconSuiteなど)を「推奨しない」と言っていません。つまり、ImageWellコントロールへのPicHandleの出し入れは、QuickDrawが消えてもそのまま残るのでしょうか? この辺の方針が明確でないのが若干困りものですね。また、Drag Managerでは、SetDragImageWithCGImage()同様に、Mac OS X 10.2から3つ、10.3からは2つのAPIが追加されています。こうした最新APIを利用する場合には、アプリケーションのターゲットとなるOSバージョンが幾つなのかについても、ちゃんと気にとめておく必要があります。注意しましょう!
今回はDrag Managerについて代用APIを調査してみましたが、今回の例題と同じような状況はCarbon Frameworkの広範囲に及んでいます。次回も代用APIの調査を継続してみたいと思います。
つづく
SqueakではじめるSmalltalk入門 第69回 鷲見 正人
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。
前回、ウインドウメニューに独自のメニュー項目を追加しているワークスペースを解析して、どのようにしてそれを実現しているのかを調べました。具体的には、#addModelItemsToWindowMenu:というメソッドの起動を介して、パラメータとして渡されるメニューモーフ(a MenuMorph)にメニュー項目を追加するメッセージを送る…という手続きをとります。実際に、作成中のGUIビルダでも同じことを試して検証してみましょう。
▼GuiBuilderクラスに#addModelItemsToWindowMenu:を追加
まず、クラス「GuiBuilder」をブラウズしているブラウザをアクティブにします。他のウインドウに埋もれて見つけにくいときは、デスクトップをshiftキーを押しながらクリックしてウインドウ一覧メニューをポップアップさせてそこから探すか、新しいブラウザを開きます(GuiBuilderとどこかに入力してcmd + Bか、新しいブラウザを開いてクラスカテゴリペインからcmd + FでGuiBuilderを検索)。
アクティブにしたブラウザで、クラスGuiBuilderが選択されていることをきちんと確認してから、メソッドカテゴリペインの黄ボタンメニューから「new category…」→「new…」を選択し、Workspaceに倣ってカテゴリ「menu commands」を新しく作ります。引き続き、コードペインに次のように入力(あるいは、このメールからコピー&ペーストして)後、accept(cmd + S)すればコンパイル完了です。
addModelItemsToWindowMenu: aMenu
aMenu addLine.
aMenu add: 'inspect model' target: self action: #inspect.
aMenu add: 'inspect window' target: aMenu defaultTarget action: #inspect
[fig.A]メソッド#addModelItemsToWindowMenu:のコンパイル
メソッド定義が無事完了したら、GUIビルダウインドウのウインドウメニューをポップアップしてみてください。新しくGuiBuilderに定義した、この#addModelItemsToWindowMenu:がうまく機能していれば、「inspect model」「inspect window」という二つのメニュー項目が追加されているはずです。
[fig.B]追加された区切り線と二つの項目の確認
追加された新しいメニュー項目を選択すると、上のメニュー項目の定義どおり、モデル(self)、あるいは、GUI ビルダウインドウ(a SystemWindow)にinspectが送信され、それぞれのインスペクタが起動します。なお、メニュー項目の追加は動的に行なわれる(つまり、メニューは、呼び出しごとに新しく作られる)ため、GUIビルダのウインドウを作り直す必要はありません。
同じ方法で、GUIウィジェットを追加したり、削除するためのメニュー項目を設けてやれば、GUIビルダを機能させることができそうです。
▼ウインドウメニューにモデルが独自の項目を追加する仕組み
なるほど、#addModelItemsToWindowMenu:に追加したいメニュー項目についての記述をすれば、そのとおりになるのは分かった。しかし、システムウインドウが、いつ、どのようなタイミングでこのメソッドを起動するのかについても知りたい…という勉強熱心な方のために、それを調べる方法についてざっと補足します。
もはや、だいぶ慣れてきていただいているところとは思いますが、システムについて生じた疑問は、システム自身に尋ねて答えを得る…というのが、Smalltalkでの鉄則です。今回は、ウインドウメニューをポップアップするときクリックするボタンに、そのカラクリを聞いてみることにいたしましょう。
まず、ウインドウメニューボタンをコマンドクリックの繰り返し(あるいは、shift+コマンドクリック)でモーフとして選択し、ハローを表示させます。
[fig.C]ウインドウメニューボタンモーフの選択
次に、右手上から二番目のデバッグハローをshiftキーを押しながらクリックしてインスペクタを呼び出してください。
[fig.D]ウインドウメニューボタンモーフのインスペクタ
インスタンス変数「actionSelector」に、このボタンをクリックしたときに送信されるメッセージに含まれるセレクタ、つまり、起動するメソッド名が関連づけられています。この場合、#offerWindowMenuです。次に、「offerWindowMenu」の部分をダブルクリックで選択して、browse it(cmd +B)か、implementors of it(cmd + m)します。これで、ボタンを押したときの振る舞いを記述したメソッドの定義をブラウズできます。その内容は次のようなものです。
SystemWindow >> offerWindowMenu
| aMenu |
aMenu := self buildWindowMenu.
model ifNotNil:
[model addModelItemsToWindowMenu: aMenu].
aMenu popUpEvent: self currentEvent in: self world
まずデフォルトのメニューを作り、モデルが指定されていれば(nilでなければ)それにメニュー項目の追加作業を委譲(くだんの#addModelItemsToWindowMenu:を起動)し、最後に、そうして出来上がったメニューをポップアップしている様子が見て取れますね。さらに、関連メソッドであるSystemWindow >> #buildWindowMenuをブラウズすることで、デフォルトのメニュー項目がどのように作られているのかについても観察できるはずです。メニュー項目の日本語化の方法を知ることができますので、ぜひ、チャレンジしてみてください。
次回は、システムウインドウにGUIウィジェットを追加する具体的な方法を考えます。
バックナンバー:
ニュース・解説
今週の解説担当:木下 誠
———————————————————————-
Cocoaアプリケーションをアクセシビリティ対応にする
———————————————————————-
Cocoaアプリケーションでのアクセシビリティ対応を説明したドキュメント、「Enabling Accessibility in Your Cocoa Application」が公開されました。
Cocoaでは、NSAccessibilityプロトコルと、NSObjectの非形式プロトコルに、アクセシビリティのためのメソッドが定義されています。カスタムコントロールでも、これらが持つメソッドを実装することで、アクセシビリティ対応となります。
開発作業では、つい後回しにされがちな分野ですが、ぜひ対応すべき項目であることを、開発者の方々は心に留めておきましょう。
Enabling Accessiblity in Your Cocoa Application
http://developer.apple.com/ue/accessibility/accessibilityincocoa.html
———————————————————————-
新iMac発表およびDeveloper Note公開
———————————————————————-
新しいiMac (September 2006)が発表されましたね。注目は、Intel Core 2 Duoプロセッサの搭載と、さらに画面が大きくなった24-inchモデルの追加です。
早速、「iMac Developer Note」も公開されました。これを見ると、17から20-inchモデルと、24-inchモデルでは、結構差があることに気づきます。24-inchは、単に画面が大きいだけではなく、iMacの中の上位モデルと見るべきでしょう。
また、これに合わせて、「RAM Expansion Developer Note」も更新されています。こちらでは、今回のモデルを、「iMac with SuperDriver」と「iMac with Combo Drive」に分けており、前者の最大メモリサイズは3 GB、後者は 2 GBとなっています。
iMac Developer Note
http://developer.apple.com/documentation/HardwareDrivers/Conceptual/iMac_0609_SuperDrive/index.html
RAM Expansion Developer Note
http://developer.apple.com/documentation/HardwareDrivers/Conceptual/HWTech_RAM/index.html
◇MOSAからのお知らせと編集後記は割愛します◇