レインボーアップルが白抜きになってしまった・・・
個人的にはやっぱり六色の方がいいと思う
アップル・ジャパンのホームページはこちら
Macintosh関連情報入手にはこっちもいいかも
この文書はすでに歴史的なものになっているので役に立たないと思われるけれども記念に残しておく
Macintosh
The Macintosh C Programming with MPW
Macintosh C Programmingを勉強中。MPWというすばらしいもののおかげでお金の問題は解決!
でもPowerBookのハードディスク容量も足りなくなってきた・・・
はたして作品を公開できるのか?!
(一応あるゲームを作ったのだが、どうしようか?)
About MPW...
MPW (Macintosh Programmer's Workshop) とは何か?MPWは、Appleが提供する「無料」の開発環境です。
Macintoshの開発環境と言えばMetroWorksのCodeWarriorが主流ですが、結構お値段が張るので(アカデミック版は半額になりますがマニュアルがオンラインマニュアルのみです。)お遊びでプログラムをやるにはちょっと・・・と思う方々もいらっしゃるでしょう。そんな方々のためにあるのがMPWです。
注意:ソフト自身は無料とはいえ、20MB近いファイルをダウンロードするので電話代、接続料等がかなりかかります。
とはいえど、安かろう、悪かろうでは?? ご安心を、性能は高いのです(多分・・・)。が、CodeWarriorなどと違ってユーザーインターフェースがとっつきにくい形なのは確かです。UNIXのshellやWindowsのMS-DOSモードに近いものがあります(というより、もともとMPWもMS-DOSもUNIXのshellを参考につくられたものです)。しかし、Macintoshのソフトだけあってメニューバーやダイアログを使った入力も可能です。一方でエイリアスやスクリプトの使用等、UNIXのshellのようなことも可能です。
コンパイルできる言語はC, C++, Pascal, アセンブラです。
MPWでのプログラミングに必要なもの
最低限、以下の2つは必要です。- MPW-GM (Golden Master)
- ResEdit
ResEditはAppleの普通の ftpサイトにあります。どちらもDiskCopyというソフトで圧縮されているので展開にもそのソフトが必要になります。これもAppleの普通のftpサイトにあります(なお、MacOS 8.1のインストールCDの中にも入っていました)。ダウンロードしたファイルはまず Stufflt Expanderで展開して、次にDiskCopyで展開します。すると「ディスクイメージ」が作成されるので、これの中身をハードディスクに用意した新規フォルダに全部コピーすればOKです。
なお、MPW-GMのとなりにMPW-PRというのがありますが、こちらはMPW-GMをアップデートするためのものです。このアップデートの方法は「Introduction to MPW」に書かれています。(GMはGolden Masterの略、PRはPreReleaseの略です。)
Hello, MPW World !!
とりあえず、お決まりのプログラム(Hello World)の作り方です。これをやってみれば一応MPWの使い方のアウトラインが分かるでしょう。最初に書いたとおり、ここではC言語を使用します。C言語についてお勉強したい方は、いろいろ書籍がでていますのでそちらをあたると良いでしょう。1. まず、プログラム用にフォルダを一つ作っておきます。
2. MPWの中の「MPW Shell」を起動します。
3. はじめて起動すると、Helpの出し方が延々と書かれているWorkSheetが開くと思います。このWorkSheetがコンパイルなどの命令を入力し、その結果が出力されるウィンドウです。
4. 重要:MPW Shellは「Returnキー」と「Enterキー」を区別します。「Returnキー」は単純に改行するだけです。「Enterキー」は入力された文字列をShellへの命令と認識して実行します。(なお、Optionキーを押しながらReturnキーを押す = Enterキーを押す)
5. Helpの出し方はとりあえずいらないので「コマンド+A(またはEditメニューからSelect All)」「DELキー(またはEditメニューからClear)」で消してしまっても良いでしょう。また見たくなったら「Help」と入力し、「Enterキー」を押せば同じものが表示されます。
6. さて、はじめにすることは作業ディレクトリの設定です。「Directoryメニュー」から「Set Directory」を選びます。するとフォルダを選択するダイアログが出るので1. で作成したフォルダを選択し、Directoryボタンをクリックします。(なお、ソースファイルをダブルクリックしてMPW Shellを起動した場合には、ディレクトリは自動的にそのソースファイルのあるフォルダにセットされます。)
7. 次に「コマンド+N(またはFileメニューからNew)」を入力します。ファイル名はHello.cとします。すると新しいウィンドウが開きます。これがソース入力用のウィンドウです。他のテキストエディタ(Simple Text等)でソースを書いておき、それを読み出すことも可能です。この場合は「コマンド+O(またはFileメニューからOpen)」を入力し、そのファイルを開きます。
8. 次のソースを入力します。(注意:記号\はMPW Shellで入力するとバックスラッシュ=右下がりの斜線で表示されます。)
#include<stdio.h>
void main()
{
printf("Hello, MPW World !! \n");
}
9. 入力を終えたら保存します。「コマンド+S(またはFileメニューからSave)」を入力します。
10. 続いてMakeFile(コンパイルの条件等を記述してあるファイル)を作成します。「BuildメニューからCreate Build Command」を選びます。そして、ダイアログに次のものを入力していきます。
- Program Name: Hello
- Source Filesボタンを押して、開いたダイアログでHello.cを選択し、Addボタンを押す。そしてDoneボタンを押す。
- Program TypeはSIOW App.を選びます。これは1つデフォルトのウィンドウを開いてそこで入力、出力を行うもので文字の入力、出力等のみのアプリケーションに使用できます。(SIOWはSimple Input/Output Windowの略です。)
- Targetは使っているMacintoshに合わせて選んで下さい。PowerPCをCPUとするMacintoshで動かすならPowerPC onlyを、68kをCPUとするMacintoshで動かすなら68k onlyを選んで下さい。(FAT Binaryを選べばどちらでも動きますがプログラムの容量が大きくなります。)
- Targetで68k onlyかFAT Binaryを選んだならRuntime ModelからModel Nearを選びます。(これは小さなプログラムを作る場合に指定します。)
- CreateMakeボタンをクリックします。
11. いよいよコンパイルです。「コマンド+B(またはBuildメニューからBuild)」を入力します。作成するプログラム名を聞いてくるのでHello(10.のダイアログで入力したProgram Name)と入力します。
12. 無事コンパイルが終了すればHelloというアプリケーションができているはずなので、実行すると良いでしょう。コンパイルエラーが出た場合はMPWのフォルダが正しくインストールされているか、作業用Directoryが正しく設定されているか、プログラムが間違いなく入力されているかをチェックして下さい。(なお68KではFile was not needed for linkという警告が出ますが気にしなくてもよいです。)
おまけ:アップルメニューからAbout MPW...を選んでみましょう。感動もの・・・
ToolBox
さて、とりあえずコンパイルはできるようになったけれども、普通のMacintoshのソフトとは大分違う(まるでテキストエディタのような)ものができてしまいました。これでは市販されているような、いかにもMacintoshっぽいアプリケーションを作るにはちょっと無理がありそうです。「Macintoshっぽいアプリケーション」をつくるにはどうしたらよいのでしょう?普通の「Macintoshっぽいアプリケーション」が(目や耳に感じられる範囲内で)どんなものから構成されているかを考えてみますと、次のようなものが挙がると思います。
- ウィンドウ(クローズボックスやスクロールバー、サイズボックスなどを含む)
- そこに表示されるグラフィックやアイコン
- ダイアログ(テキストエディタやボタンを含む)
- メニューバー(アップルメニューを含む)
- サウンドなど
- そして操作はマウスとキーボードで行う。
例えばウィンドウに限っても、ウィンドウのどこにクローズボックスがあるのか、サイズボックスがあるのか、スクロールバーがあるのか、ウィンドウには何が描かれているのか、それぞれをクリックしたら何が起きるか、ドラッグしたらどうなるか、サイズボックスでウィンドウのサイズを変えるなら画面の大きさより大きくなったり、作業できないほど小さくなったりしてはいけないし、そのためには今のウィンドウの大きさを常に管理しなければならないし、他のアプリケーションのウィンドウがクリックされたらどうするか、といったようにです。
また、それぞれのプログラマーによって違うものが作られてしまっては、使う側には不便です(たとえば作ったプログラマーによってクローズボックスの位置が右上だったり左下だったり、メニューバーが左にあったり下にあったり)。アプリケーションがどれも同じような操作で使えるというのがMacintoshの魅力でもあるわけですから。
そこでAppleはこれらの管理を行うためのルーチンを(Macintosh内部のROMとして)提供しており、それを使用することを推奨しています。これがMacintosh User Interface ToolBox(普通は略して単にToolBox)というものです。そしてFinderをはじめとするアプリケーションは実際にToolBoxを使用してウィンドウを開いたり、メニューバーを管理したりしているわけです。
ToolBox には数千のルーチンがあります。これらはInside Macintoshという本またはCD-ROMに解説されています(一部はアップルのサイト上にもあります:英語ですが)。が、はじめからこれに手を出すのは極めて無謀ですので、まずは書籍等を参考にすることをお勧めします。(このページでもある程度は解説する予定ではありますが・・・)
リソースエディタ ResEdit
リソースとは先に挙げたウィンドウ、グラフィック、アイコン、ダイアログ、メニューバー、サウンドなどといったユーザーインターフェースを構成するものをリソースと言います。ToolBoxを使う場合に避けられないのがリソースの作成・編集です。そしてリソースの作成・編集を行うためのアプリケーションがResEditです。アピアランス機能拡張をResEditで編集してゴミ箱の絵柄を変えたりする人もいます(私もその一人ですが)。また英語ソフトの文字列リソースを翻訳した日本語に置き換えることで日本語化したりすることもできます(実際はそんなに簡単な話でもないが)。まあ、そういうふうにアプリケーションの外観を作成・修正するのがResEditです。Macintoshっぽいアプリケーションの作成
さて、Macintosh Programmingの本題はここからです。結局のところMacintoshの アプリケーションの中身は次のようなものになります。- アプリケーションはリソースとプログラム(ソースコード)からなる。
- ウィンドウやグラフィック、文字列などのリソースは基本的にResEditで用意する。
- プログラムはMPWで書く。
- 用意したリソースはプログラムから呼び出す。
- またプログラムはマウスのクリックなど(イベントといいます)がいつ、どこで起こったかを検出する。
- またプログラムはイベントを検出したらそれに応じたToolBoxを呼び出す。例えばウィンドウのクローズボックスがクリックされたら、プログラムはウィンドウを閉じるToolBoxを呼び出す。
また、リソースとプログラムは独立に作成することができます。つまりリソースを全く作らないで、プログラムだけを先に完成させたり、その逆が可能です。ただし、プログラムから呼び出したリソースが存在していない場合、プログラムは実行してもクラッシュしてしまうので注意が必要です。
MacintoshっぽいHello, World !
今度もHello, Worldですが、前回のようにMPWが提供してくれるSIOWは使用しません。つまり我々が独自にウィンドウを用意し、そこにHello, Worldを書き込みます。また、このウィンドウの表示と消去はマウスクリックを合図にします。プログラムは次のようになります。- 初期設定
- マウスのクリックを待つ
- ウィンドウを表示
- Hello, Worldと書き込む
- マウスのクリックを待つ
- ウィンドウを消去しプログラムを終了
リソースの準備
必要なリソースが明らかなので先にこちらを作ってしまいます。1. まず、プログラム用にフォルダを一つ作っておきます。
2. 「ResEdit」を起動します。
3. びっくり箱(?)ピエロの起動画面が表示されます。クリックするとこれは消え、自動的にファイルを開くダイアログが立ち上がります。
4. ここでNewボタンを選んで、先ほど作ったフォルダの中にMacHello.rsrcを作成します。(.rsrcはこれがリソースファイルであることを明示する拡張子です。)するとMacHello.rsrcという名前のウィンドウが開きます。
5. まず最初に「ResourceメニューからCreate New Resource(またはコマンドキー+K)」を選びます。ダイアログが表示されるのでResource Typeの中から「WIND」を選択します。(直接入力しても可。ただし必ず大文字で。)WINDはウィンドウの情報を持つResource Typeです。
6.するとウィンドウについて設定するウィンドウが2つ(WINDs from MacHello.rsrcとWIND ID=128 from MacHello.rsrc)開くのでWIND ID=128 from MacHello.rsrcウィンドウで設定を行います。
- まず、ウィンドウ上に並んでいるのがウィンドウの形式です。このアプリケーションではズームボックスやサイズボックスは不要なので、それらのない左から2番目を選びます。クリックするとそれが反転表示になって選ばれたことが分かります。
- ウィンドウの左下にはウィンドウの初期位置と大きさの設定があります。ここはそのままでいいでしょう。
- ウィンドウの右上にはウィンドウの色の設定があります。せっかくなので色を付けてみます。Customラジオボタンを選択すると下に現在の色の設定が表示されます。それぞれの長方形をクリックすると色を選ぶパレットが表示されるので好きな色をクリックして下さい。なお、クリックすると警告(英語)が表示されますが、これは新しくwctbリソースを作りますがよいですか?という意味です。wctbはウィンドウの色の情報を持つリソースタイプです。
- ウィンドウの右下には2つのチェックボックスがあり、ウィンドウを最初から(このリソースをプログラムから呼び出したときから)見えるようにするかとクローズボックスを使うかという設定があります。ここでは両方のチェックをはずしておきます。マウスのクリックがあるまで表示させないためと、マウスのクリックで閉じさせるのでクローズボックスはいらないためです。
8. WINDs from MacHello.rsrcウィンドウを閉じます。次に4.で開いたMacHello.rsrcウィンドウを最前面(アクティブ)にします。WINDとwctbの2つのリソースが表示されているはずです。
9. 「ResourceメニューからCreate New Resource(またはコマンドキー+K)」を選びます。ダイアログが表示されるのでResource Typeの中から「STR#」を選択します。(直接入力しても可。ただし必ず大文字で。)STR#は文字列の情報を持つResource Typeです。
10.すると文字列について設定するウィンドウが2つ(STR#s from MacHello.rsrcとSTR# ID=128 from MacHello.rsrc)開くのでSTR# ID=128 from MacHello.rsrcウィンドウで設定を行います。
- まず、1) *****という部分をクリックします。そこが長方形で囲まれるので 「ResourceメニューからInsert New Field(s)(またはコマンドキー+K)」を選びます。The Stringというテキスト入力ボックスが表示されるので、そこにHello, World !!と入力します。
12. さらにもう一度だけ「ResourceメニューからCreate New Resource(またはコマンドキー+K)」を選びます。ダイアログが表示されるのでResource Typeの中から「SIZE」を選択します。(直接入力しても可。ただし必ず大文字で。)SIZEはプログラムの大きさの情報を持つResource Typeです。(Finderの情報を見るコマンドで表示される、最小サイズと推奨サイズを設定します。)
13.すると設定するウィンドウが2つ(SIZEs from MacHello.rsrcとSIZE ID=128 from MacHello.rsrc)開くのでSIZE ID=128 from MacHello.rsrcウィンドウで設定を行います。
- まず32 Bit Compatibleという項目を探し、その1のラジオボックスをクリックします。
- 一番下にある二つの入力ボックスがプログラムの推奨サイズと最小サイズです。とりあえず両方65536と入力しておきます。これでプログラムは64Kバイトになります。(1Kバイト=1024バイトなので1024x64=65536)
16. SIZEs from MacHello.rsrcウィンドウを閉じます。次に「FileメニューからSave(またはコマンドキー+S)」を選んで保存します。
以上でリソースの設定は終わりです。なお、手順12-15(SIZEリソースの設定)はやらなくてもプログラムは動くのですが、Finderから情報を見るコマンドでアプリケーションの使用メモりの大きさの設定ができなくなってしまいます。
Program of MacHello
次が、プログラムソースです。1. MPW Shellを起動します。
2. 作業ディレクトリをMacHello.rsrcの入っているフォルダに設定します。(「Directoryメニュー」から「Set Directory」を選んで設定します。)
3. ファイル名MacHello.cで新規ソースファイルを作成します。(「Fileメニュー」から「New」を選ぶ。)
4. 以下のソースを入力して保存します。(長い)
#include<MacWindows.h>
#include<Dialogs.h>
#include<Strings.h>
#include<Fonts.h>
#define REMOVE_EVENTS 0
#define SLEEP_TICKS 0L
#define MOUSE_REGION 0L
#define WINDOW_ID 128
#define IN_FRONT (WindowPtr)-1L
#define STR_ID 128
#define HELLO_STR_ID 1
void init_toolbox( void );
void wait_mouse_click( void );
void draw_window( void );
QDGlobals qd;
WindowPtr one_window;
EventRecord one_event;
void main()
{
init_toolbox();
one_window = GetNewCWindow ( WINDOW_ID, nil, IN_FRONT );
wait_mouse_click();
draw_window();
wait_mouse_click();
DisposeWindow( one_window );
}
void init_toolbox()
{
InitGraf( &qd.thePort );
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs( nil );
FlushEvents( everyEvent, REMOVE_EVENTS );
InitCursor();
}
void wait_mouse_click()
{
Boolean proceed;
proceed = false;
while(proceed == false)
{
WaitNextEvent( everyEvent, &one_event, SLEEP_TICKS, MOUSE_REGION );
if( one_event.what == mouseDown )
proceed = true;
}
}
void draw_window()
{
Str255 hello_str;
SetPort( one_window );
ShowWindow( one_window );
GetIndString ( hello_str, STR_ID, HELLO_STR_ID );
MoveTo (30,30);
DrawString ( hello_str );
}
コンパイル
1. まずリソースファイルをMPWが理解できる形に翻訳します。これはリソースファイルを更新するたびに行う必要があります。「DeRez MacHello.rsrc > MacHello.r」と入力し、「enterキー」を押します。(もしくは「DeRez」と入力し、「optionキー+enterキー」を押しダイアログを表示させて、そこでDecompileファイル名とOutputファイル名を設定する方法もあります。)2. 次にMakeFileを作成します。「BuildメニューからCreate Build Command」を選びます。そして、ダイアログに次のものを入力していきます。
- Program Name: MacHello
- Source Filesボタンを押して、開いたダイアログでMacHello.cとMacHello.rを選択し、Addボタンを押す。そしてDoneボタンを押す。
- Program TypeはApplicationを選びます。
- Targetは使っているMacintoshに合わせて選んで下さい。PowerPCをCPUとするMacintoshで動かすならPowerPC onlyを、68kをCPUとするMacintoshで動かすなら68k onlyを選んで下さい。(FAT Binaryを選べばどちらでも動きますがプログラムの容量が大きくなります。)
- Targetで68k onlyかFAT Binaryを選んだならRuntime ModelからModel Nearを選びます。(これは小さなプログラムを作る場合に指定します。)
- CreateMakeボタンをクリックします。
3. いよいよコンパイルです。「コマンド+B(またはBuildメニューからBuild)」を入力します。作成するプログラム名を聞いてくるのでMacHelloと入力します。
これでコンパイルされるはずです。68KではFile was not needed for linkという警告が出ますが気にしなくてもよいです。
注:実行すると、まずマウスクリックを待っているのですが、ここでデスクトップや他のアプリケーションのウィンドウをクリックしてしまうと制御が他のアプリケーションにうつってしまいます(メニューバー上とかでクリックすれば大丈夫)。その場合はアプリケーションメニューからMacHelloを選んで制御を戻してやって下さい。
ソースコード解説
#includeMPWではすべてのヘッダファイルを明示的にincludeしなければなりません。プリコンパイラヘッダを作成する方法もあるのですが、いまいちどこのファイルを取り込めばいいのかよく分からないというのもあってまだやっていません。
- MacWindows.hはウィンドウを扱うToolBox関数を集めています。MacTypes.h(Macintosh独自の変数型や定数を定義している)やQuickDraw.h(QuickDraw関係の関数を定義)やEvnets.h(マウスクリック等のイベントを扱う関数を定義)のようなウィンドウに関連するものも内部でincludeされていますので、このファイルをincludeしておけば大抵の関数が使えるようになります。
- Dialogs.hはダイアログを扱うToolBox関数を集めています。が、このプログラムではInitDialogs()以外使われていません。PowerPC onlyでコンパイルするとなぜか不要でした。
- Fonts.hはフォントを扱うToolBox関数を集めています。が、このプログラムではInitFonts()以外使われていません。PowerPC onlyでコンパイルするとなぜか不要でした。
- Strings.hは文字列を扱うToolBox関数を集めています。
ここでは種々のToolBox関数が使用する定数とリソースのIDを定義しています。
init_toolbox();
ToolBox関数を初期化します。ToolBoxを使用するプログラムには、このルーチンが必要です。関数の呼び出しもここに書かれている順番で行う必要があります。nil, everyEventは定数としてヘッダファイルの中で定義されています。QDGlobal型(これもヘッダファイルの中で定義されています)この型も構造体qdはQuickDrawからdefaultの定数が渡されてきます。なお、nilは0を指すポインタで、普通C言語ではNULLと記述されます(これはMacintoshの開発言語がPascalだったことの名残です。NULLも使用できます。)。
one_window = GetNewCWindow ( WINDOW_ID, nil, IN_FRONT );
GetNewCWindow()はWINDOW_IDのIDを持つWINDリソース(とwctbリソース)を(まだ読み出されていなければ)読み出して、そのデータを保持する WindowPeek型構造体を作成します。そしてその構造体へのポインタをone_windowに格納します。なお、第2引数はこの構造体のメモリ上での作成位置を指定するものですが、ここではnilを渡してMacintoshにその位置の指定を任せます。また第3引数はその作成したウィンドウを最前面に置くかどうかを指定するもので、IN_FRONT=(WindowPtr)-1Lなら最前面へ、(WindowPtr)0Lなら最前面以外に置かれます。なお、GetNewCWindow()はWINDリソースが最初から見えるように指定してある場合には表示も行います。
wait_mouse_click();
マウスクリックがあるまで何もしないで待ち続ける関数です。核になる関数が
WaitNextEvent( everyEvent, &one_event, SLEEP_TICKS, MOUSE_REGION );です。この関数はイベントが起こったかどうかを調べるためのものです。第1引数は調べるイベントの種類でここではeveryEventです(なお、起こったイベントの種類が第1引数と一致すると返値がtrueになります。)。第2引数はEventRecord型構造体で、ここにどんなイベントがいつどこで起こったのかが格納されます。第3因数はWaitNextEvent実行時にどれだけバックグラウンドで他のアプリケーションを実行する時間を確保するかを1/60秒単位で指定します。ここでは0Lなので必要最小限ということになります。第4引数はある画面領域を指定しそこからマウスポインタ出た場合にイベントを発生させるというものですが、通常は特に領域指定しませんので、0Lを与えます。なお、定数 everyEventと型宣言EventRecordはヘッダファイルの中で定義されています
if( one_event.what == mouseDown )で構造体 one_eventの要素whatにマウスボタンが押されたイベントが入っていたらブール代数型の変数proceedをtrueにしてループを抜けます。なお、型宣言Booleanや定数true、falseはヘッダファイルで定義されています。
draw_window();
まず、Str255 hello_str(これはヘッダファイルでの定義によりchar hello_str[256]と等価です。)でウィンドウに書く文字列用の配列を確保します。
次にSetPort( one_window )で猫画するウィンドウを先にGetNewCWindowで呼び出したウィンドウに指定します。さらにShowWindow( one_window );で今まで見えなかったウィンドウを表示します。GetIndString ( hello_str, STR_ID, HELLO_STR_ID );は配列hello_strにIDがSTR_IDのSTR#リソースの中のHELLO_STR_ID番目の文字列をコピーします。MoveTo (30,30);はウィンドウでの猫画位置をウィンドウの左上角から左から30ピクセル、上から30ピクセルの位置に移動します。DrawString ( hello_str );は先ほど移動した猫画位置からhello_strに格納されている文字列を猫画します。
DisposeWindow( one_window );
DisposeWindow()はGetNewCWindowで確保したウィンドウを閉じ、その情報を解放します。
より詳しい情報が得られるサイトへのリンク
- より詳しいMPWの使い方はこちらへ
- より詳しいToolBox関数の仕様についてはこちらへ
- AppleによるToolBox関数の技術文献はこちらへ(日本語版:ときどき笑える)
- フリーウェア開発者の金字塔「Project GNU」のホームページとその日本語解説
GNUは直接はMacintoshのプログラムとは関係ないですが、その理念はすばらしい。