
ナッキー |
今回はテンプラ揚げる…じゃなかった、テンプレートを使うんでしたよね。それを使うと、フォームが簡単に作れるみたい。どうやって使うのか、しっかり教えてもらおうっと。 |
|
|

高橋先生 |
メインフォーム以外のフォームは「サブフォーム」っていうんだ。テンプレートを使って作るときは、形が限定されているから、何にでも使えるわけじゃない。それでもよければテンプレートは便利だね。 |
|
|
バージョン情報ダイアログを作る
早速フォームを作るのかしら?フォームを作ってからメニューを実装するってこと?そうすると、完成まで、あとどれくらい作業があるのかな?教えて、高橋先生!
高橋先生:メニューで実装されていないのは[サイズ変更(S)...]メニューと[バージョン情報(A)...]メニューだけだね。簡単なのは[バージョン情報(A)...]メニューのほうだから、先に作ろう。作業はバージョン情報ダイアログを作成、[バージョン情報(A)...]メニューを実装、次にサイズ変更ダイアログを作成、[サイズ変更(S)...]メニューを実装すれば、完成だ。今回作るのは、フォームの中でもダイアログボックスという種類だよ。 |
ナッキー:いよいよ完成なのね。やったー。長い道のりだったけど、がんばった甲斐があったわぁ。 |
高橋先生:…まだ、できてないって。喜ぶのが早すぎるよ。まずはテンプレートを使ったダイアログボックスの作成方法を紹介しよう。テンプレートは「オブジェクトリポジトリ」に入っている。「新規作成」ダイアログボックスで、オブジェクトリポジトリの一覧から1つを選択して、[OK]ボタンをクリックしたら出来上がり。 |
ナッキー:前から聞こうと思っていたんですけど、「テンプレート」って何かしら? |
高橋先生:テンプレートはひな型みたいなものだよ。テンプレートを使うと、ある程度できた状態からフォームなどの作成を始めることができる。コンポーネントも少し配置されているから、足りないコンポーネントを追加して、プロパティ設定すれば完成だ。また、付属のボタンコンポーネントをクリックすると、フォームが閉じることもある。このように機能まで付いていることもあるよ。 |
ナッキー:へぇ、コンポーネントやコンポーネントのイベントハンドラまでついているのね。 |
高橋先生:はじめから付属しているコンポーネントは削除してもいいし、ほかのコンポーネントを追加してもいいよ。イベントハンドラも独自に作ったら、そちらを優先する。今回、先に作るバージョン情報ダイアログは、コンポーネントをそのまま使うから削除しないでね。 |
|
コンポーネントまで配置してあるなんて便利ね。すぐに作ってみようっと。それには、まずプロジェクトを開きます。Turbo Delphiを起動して、画面中央の「ホームページ」で「Drawing.bdsproj」を選択。もし一覧に表示されていなければ、ツールバーの[プロジェクトを開く(Ctrl+F11)]ボタンをクリックします。「プロジェクトを開く」ダイアログボックスから「Drawing.bdsproj」を探します。
テンプレートを使ってバージョン情報ダイアログを作成します。ツールバーの[新規作成]ボタンをクリックして、「新規作成」ダイアログボックスを表示します。

図01 [新規作成]ボタン
項目カテゴリで「Delphi ファイル」を選択し、表示されたアイコン一覧から「バージョン情報ダイアログ」を選択して[OK]ボタンをクリックします。

図02 新規作成ダイアログボックス
「バージョン情報ダイアログ」用のユニットのコードエディタが表示されますので、フォームデザイナに切り替えます。
わぁ。本当に画面ができているのね。バージョン情報ダイアログのコンポーネントは、テンプレートのものをそのまま使用して、プロパティだけ変更します。
AboutBox(フォーム)
カテゴリ名 |
プロパティ名 |
設定値 |
その他 |
Name |
frmAboutBox |
|
|
|
ProductName(ラベル 「製品名」)
カテゴリ名 |
プロパティ名 |
設定値 |
ローカライズ対象 |
Caption |
お絵かきソフト |
|
|
|
Version(ラベル 「バージョン」)
カテゴリ名 |
プロパティ名 |
設定値 |
ローカライズ対象 |
Caption |
バージョン0.1 |
|
|
|

図03 バージョン情報ダイアログ
バージョン情報ダイアログが完成したら、保存します。ツールバーの[すべて保存]ボタンをクリックします。バージョン情報ダイアログのファイル名は「FormABOUT.pas」とします。
バージョン情報ダイアログを呼び出す
「バージョン情報(A)...」メニューを実装するのよね。メソッドなんかを使えばすぐにできそうだけど、どうなんだろう?教えて、高橋先生!
高橋先生:そう簡単にはいかないんだ。FormDrawingユニットには、FormABOUTユニットのことがわからないからね。 |
ナッキー:わからないって、どういうことですか? |
高橋先生:FormDrawingユニットにFormABOUTユニットのことが何も書かれていないということだよ。コンポーネントを使っても、Type節に自動的に登録されるし、宣言をしないと変数は使えない。同じように、ユニットでも「使いますよ」ということを、どこかに記述する必要があるんだ。 |
ナッキー:じゃあ、var節とか? |
高橋先生:ユニット用は「uses節」だ。フォームのType節の上にあったと思うから、確認してみよう。コードエディタで、上のほうにあるよ。 uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ExtCtrls; これらは、主にコンポーネントを使うためにあるユニットだから、コンポーネントを配置したときに、自動的にuses節に追加される。 |
ナッキー:じゃあ、ここにFormABOUTユニットも追加すればいいのね。 |
高橋先生:だめだめ、特に必要がない場合は、ここには書かないで。 |
ナッキー:えーっ?uses節に書くって、言ってたのにー |
高橋先生:説明すると、頭がグルグルすると思うけど聞く? |
ナッキー:聞く、聞く、聞きます。 |
高橋先生:以前、「第9回お絵かきソフトをつくろう」でインターフェース部と実装部の話したよね。インターフェース部は、ほかのフォームからも参照できる部分。実装部は、ほかのフォームからは参照できない部分ということだった。このことが大前提。そして、さっき紹介したuses節はどこにあったと思う? |
ナッキー:えーっと、たしかインターフェース部でしたよね。 |
高橋先生:そうだね。ということは、ほかのフォームから参照することができるuses節なんだ。ユニットの「UnitA」と「UnitB」と「UnitC」で紹介しよう。 unit UnitA;
interface
uses Windows, SysUtils, UnitB;
//UnitAでは、Windows, SysUtils, UnitBが使える
…
implementation
… このコードをUnitCが参照すると、インターフェース部のuses節にあるWindowsユニットとSysUtilsユニット、UnitBのこともUnitCに筒抜けになるということになる。ここまではいい? unit UnitC;
interface
uses UnitA;
//UnitCでは、Windows, SysUtils, UnitB, UnitAが使える
…
implementation
… |
ナッキー:そうなんですか?インターフェース部のuses節に書くと、参照するUnitCにまで参照されちゃうんだ。 |
高橋先生:そういうこと。WindowsユニットとSysUtilsユニット、UnitBは、使っているUnitA以外に、UnitAを参照しているUnitCにも参照される。そのとき、参照されるのはユニットのインターフェース部だ。 |
ナッキー:実装部は参照されないんですものね。 |
高橋先生:ここまでのことを踏まえて、もしもUnitBがUnitAを参照したらどうなると思う? unit UnitB;
interface
uses UnitA;
//UnitBでは、UnitA, Windows, SysUtils, UnitBが使える
…
implementation
… |
ナッキー:うーん。WindowsユニットとSysUtilsユニット、UnitAが使えるようになる、でいいんじゃないのかな。 |
高橋先生:UnitAは、UnitBを参照していなかった? |
ナッキー:参照していたけど、UnitBから参照しているんだからいらないんじゃないかな。 |
高橋先生:でも、参照しているよね。参照しようとするんだよ。そうすると、UnitBのインターフェース部のuses節にUnitAがあるから、UnitAを参照する。そして、UnitAはインターフェース部のuses節にUnitBがあるから、UnitBを参照する。またまた、UnitBは… |
ナッキー:やっぱり、頭がグルグルしてきました。これじゃあ、参照が終わりになりません。 |
高橋先生:そうなんだ、参照が循環して終われないので、これを「循環参照」という。だからコンパイルが通らない。必要がある場合以外、インターフェース部のuses節には作ったユニットを追加しないほうがいい。 |
ナッキー:じゃあ、どこに書けばいいんですか? |
高橋先生:実装部だよ。簡単な方法があるんだ。メニューバーの「ファイル(F)|ユニットを使う(U)...」をクリックすると、「ユニットの使用」ダイアログボックスが表示される。ここで、追加したいユニットを選択して[OK]ボタンをクリックすると、実装部にuses節が追加される。直接実装部にuses節を書いてもいいよ。

図04 ユニットの使用ダイアログボックス |
ナッキー:なんだ、簡単な方法があるなら早く言ってくださいよ。あー頭がグルグルした。 |
|
循環参照はちょっと難しかったけれど、インターフェース部に闇雲に追加しちゃだめだってことはわかったわ。では、簡単な方法でuses節を追加します。画面上部の「FormDrawing」のタブをクリックして画面を切り替えます。表示はコードエディタのままでいいので、メニューバーの[ファイル(F)|ユニットを使う(U)...]をクリックします。「ユニットの使用」ダイアログボックスが表示されたら、「FormABOUT」ユニットを選択して[OK]ボタンをクリックします。実装部の1行目にuses節が追加されました。
implementation
uses FormABOUT;
{$R *.dfm}
これで、コードでフォームを表示することができるのね。
高橋先生:フォームを表示するときには「ShowModal」メソッドを使う。これは、モード付きでフォームを表示するメソッド。モード付きフォームの特徴は、表示したフォームが閉じるまで、ほかのフォームを手前に表示することはできないということだよ。 |
ナッキー:じゃあ、ShowModalメソッドを使うだけでいいんだ。 |
|
では、バージョン情報ダイアログを表示できるようにコードを記述します。フォームデザイナでMainMenu1をダブルクリック、もしくはマウスの右ボタンクリックで[メニューデザイナ(Y)...]を選択します。メニューデザイナで、[ヘルプ(H)|バージョン情報(A)...]メニューを選択します。オブジェクトインスペクタ、イベントページで「入力」カテゴリの「OnClick」をダブルクリックします。コードエディタに切り替わったら、太字部分を追加します。
procedure TfrmMain.A1Click(Sender: TObject);
begin
frmAboutBox.ShowModal;
end;
コードの記述ができたら、保存して実行します。ツールバーの[すべて保存]ボタンで保存して、[実行]ボタンで実行テストします。メインフォームが表示できたら、メニューバーで[ヘルプ(H)|バージョン情報(A)...]メニューを選択します。これで、作成したバージョン情報ダイアログが表示できます。

図05 バージョン情報ダイアログ表示
やりました!新しいフォームをちゃんと表示できたわ。あ、でも何にもコーディングしてないけど、[OK]ボタンをクリックしたらフォームが閉じちゃった。
高橋先生:テンプレートだから、あらかじめできているんだ。テンプレートのすべてのボタンが完成しているわけではないけれど、テンプレートをうまく使えば効率よくプログラムを作ることができるよ。もし独自の処理をしたいときには通常どおりにコードを書けばいいよ。 |
|
サイズ変更ダイアログを作る
バージョン情報ダイアログは完成!この調子でサイズ変更ダイアログも作っちゃおう。
高橋先生:さすがに、バージョン情報ダイアログほど簡単には作れないな。でもテンプレートを使うよ。 |
ナッキー:じゃあ、ちょっとだけ難しくなるのね。 |
高橋先生:今度使うのは「標準ダイアログ(縦並び)」テンプレート。ボタン二つと飾り枠が付いている。サイズを設定したいのだから、ほかに幅と高さを入力できるエディットが必要だね。数値を入力してもらうときは、上下ボタンで数値の増減が制御できるといいね。それから、それぞれにラベルが付いていると親切だろう。 |
ナッキー:ちょっと待って。エディットもラベルも今までに出てきたけど、上下ボタンって何かしら? |
高橋先生:小さな黒い三角の印が付いていて、[▲]で数が増えて[▼]で数が減るボタンだよ。数値を設定する場面では見たことがあるんじゃないかな? |
ナッキー:あー、あるある。ん?でもエディットと上下ボタンって別なの? |
高橋先生:そうなんだ。別のコンポーネントだよ。上下ボタンは「TUpDown」コンポーネントだ。その「Associate」プロパティに、関連させたいコンポーネントを登録して使うんだ。普通はエディットと組み合わせて使う。あとは、配置してもらってから説明するよ。 |
|
えー、なんかちょっと心配だけど、とにかく画面を作成するところから始めます。ツールバーの新規作成ボタンをクリックして、新規作成ダイアログボックスを表示します。項目カテゴリで「Delphi ファイル」を選択し、表示されたアイコン一覧から「標準ダイアログ(縦並び)」を選択して、[OK]ボタンをクリックします。画面をフォームデザイナに切り替えます。
わぁ、さっきのバージョン情報ダイアログとは違う画面が作成できました。枠飾りは「TBevel」コンポーネントっていうんですって。この中にTLabelとTEditを2つずつ配置します。画面右下のツールパレットの「Standard」カテゴリから「TLabel」と「TEdit」を上下に2つずつ配置します。さらにツールパレットの「Win32」カテゴリで「TUpDown」コンポーネントを探して、2つずつ配置します。TEditの右横あたりにそれぞれ適当に並べます。
TUpDownコンポーネントはそのままにしておいて、ほかのコンポーネントのプロパティを先に設定しておきます。
フォーム名には「OKCANCEL」の後ろに連番がついて、「OKCANCEL1」や「OKCANCEL2」となります。手順によって番号が異なりますが、ここでは「OKCANCEL1」として説明を進めます。 |
|
OKCANCL1(フォーム)
カテゴリ名 |
プロパティ名 |
設定値 |
その他 |
Name |
frmSizeDlg |
ローカライズ対象 |
Caption |
サイズ変更 |
|
|
|
Label1(ラベル)
カテゴリ名 |
プロパティ名 |
設定値 |
ローカライズ対象 |
Caption |
幅 |
|
|
|
Label2(ラベル)
カテゴリ名 |
プロパティ名 |
設定値 |
ローカライズ対象 |
Caption |
高さ |
|
|
|
Edit1(エディット)
カテゴリ名 |
プロパティ名 |
設定値 |
その他 |
Name |
edtWidth |
|
|
|
Edit2(エディット)
カテゴリ名 |
プロパティ名 |
設定値 |
その他 |
Name |
edtHeight |
|
|
|

図06 サイズ変更ダイアログコンポーネント配置
あとは、TUpDownコンポーネントね。さっそく教えてもらおう。
高橋先生:ここで、TUpDownコンポーネントの「Associate」プロパティを設定してもらう。すると、関連付けるコンポーネントの高さに合わせて、隣にぴったりくっつくんだ。 |
ナッキー: Associateプロパティに設定するだけで、サイズ変更と配置までしてくれるんですね。それなら簡単だわ。 |
高橋先生:注意してほしい点が3つある。まず、1つ目。外観は1つのコンポーネントになったように見えるけれど、あくまで2つのコンポーネントだから気をつけてね。エディットと関連付けても、エディットを移動したときに一緒には移動してくれない。そういうときは、複数選択で移動してみよう。 2つ目の注意点。たとえばエディットと関連付けたとき、エディットのTextプロパティの値が「0」になる。実行中に上下ボタンをクリックすることで、エディットのTextプロパティの値が増減する。Textプロパティの数値とTUpDownコンポーネントの「Position」プロパティの値がリンクするようになっている。しかし、エディットはあくまでエディットなので、半角数値以外の値も受け付けてしまうんだ。そのため、今回はTextプロパティの値を使って、「StrToIntDef」関数で数値に変換できない値のデフォルト値をもたせよう。 3つ目の注意点。TUpDownコンポーネントには最大値が「100」と最小値が「0」がデフォルト値になっている。範囲が狭いので、使うときに適当な範囲に設定しなおす必要がある。最大値は「Max」プロパティ、最小値は「Min」プロパティで設定できるよ。 |
ナッキー:うーん。1つのコンポーネントに見えるけど、別々のコンポーネントってことね。それにみかけが変わっても、コンポーネントの性質が変わるってわけじゃないんですね。 |
|
では、プロパティを設定します。フォームデザイナの画面でUpDown1コンポーネントを選択します。画面左下のプロパティページで「リンク」カテゴリ、「Associate」プロパティの[▼]プルダウンボタンをクリックして「edtWidth」を選択します。edtWidthのTextプロパティが「0」に変わって、UpDown1が右隣に並んで配置されました。ほかにMaxプロパティとMinプロパティを設定します。最大値は「640」、最小値は「1」にしておきます。初期値としてPositionプロパティに、幅を「640」、高さを「480」とします。
UpDown1(上下ボタン)
カテゴリ名 |
プロパティ名 |
設定値 |
リンク |
Associate |
edtWidth |
その他 |
Max |
640 |
その他 |
Min |
1 |
その他 |
Position |
640 |
|
|
|
UpDown2(上下ボタン)
カテゴリ名 |
プロパティ名 |
設定値 |
リンク |
Associate |
edtHeight |
その他 |
Max |
480 |
その他 |
Min |
1 |
その他 |
Position |
480 |
|
|
|
プロパティが設定できたら保存しておきます。ツールバーの[すべて保存]ボタンをクリックして保存します。「OKCANCL1に名前をつけて保存」ダイアログボックスが表示されたら「FormPaintSize.pas」と名前をつけて保存します。
これで、サイズ変更ダイアログは完成ね。次はメニューから呼び出せば完成かな。
サイズ変更ダイアログの値を取得する
バージョン情報ダイアログは「ShowModal」メソッドで表示できたけど、今度のサイズ変更ダイアログも同じでいいのかな?
高橋先生:表示するだけならそれでいいんだけど、今回は設定のダイアログボックスだったよね。サイズ変更ダイアログを閉じるボタンには[OK]ボタンと[キャンセル]ボタンがあった。[OK]ボタンを押したときに設定を有効に、[キャンセル]ボタンを押したときには設定を無効にしよう。モード付きでフォーム表示すると戻り値を持つことができる。戻り値をセットするところまでは、テンプレートを使ったので自動的に入ってくる。[OK]ボタンを押したときには「mrOK」が戻り値になるので、If文で調べよう。 |
ナッキー:テンプレートを使うと、いろいろなことが自動でされるのね。バージョン情報ダイアログは「ShowModal」メソッドの戻り値を調べなかったけど、今度は調べて見るのかあ。そのあと、幅や高さを設定すればいいのかしら? |
高橋先生:幅や高さの値は、サイズ変更ダイアログにあったエディットのTextプロパティが、フォームを閉じても残っている。デフォルトでは、サブフォームが閉じても非表示になるだけなんだ。だからコンポーネントの値を調べることもできるよ。 |
ナッキー:フォームを閉じちゃったら、なくなるのかと思っていました。違うフォームにあるコンポーネントのプロパティも調べられるのなら設定も簡単ですね。 |
高橋先生:簡単といえばそうだけど、コンポーネントを参照するときフォーム名を入れるのを忘れないでね。 |
ナッキー:プロパティの値を見るのに、フォーム名も必要なんですか? |
高橋先生:コードの中では、すべてのコンポーネントは、同じユニット内のフォームのメンバだってことが前提で、フォーム名を書かずにすんでいるんだ。違うユニットにあるフォームのメンバの場合は、そのことを書かないとわからないんだ。コードを書く前に、バージョン情報ダイアログでもしてもらったように、「ユニットの使用」ダイアログボックスで、uses節に「FormPaintSize」を追加することも忘れないでね。 それから、ペイントボックスのサイズを小さくしても、全体が白くて境界線がわからないのでsbxDrawスクロールボックスの「Color」プロパティを元の値「clBtnFace」に戻しておこう。 |
|
では、コードより先にスクロールボックスのプロパティ設定をします。画面上部の「FormDrawing」タブをクリックして、画面を切り替えます。フォームデザイナで「sbxDraw」を選択して、プロパティページで「表示」カテゴリの「Color」プロパティに「clBtnFace」を選択しておきます。これでペイントボックスとスクロールボックスの区別がしやくなります。
次に、uses節にユニットを追加します。FormDrawingユニットを表示していることを確認して、[ファイル(F)|ユニットを使う(U)...]メニューをクリックします。「ユニットの使用」ダイアログボックスの一覧から「FormPaintSize」を選択して、[OK]ボタンをクリックします。設定できたら、コードエディタで、実装部のuses節を確認します。太字部分が追加されています。
implementation
uses FormABOUT, FormPaintSize;
{$R *.dfm}
uses節にユニットが追加できたら、イベントハンドラを作成します。フォームデザイナでMainMenu1をダブルクリック、もしくはマウスの右ボタンクリックで[メニューデザイナ(Y)...]を選択します。メニューデザイナで、[編集(E)|サイズ変更(S)...]メニューを選択します。オブジェクトインスペクタ、イベントページで「入力」カテゴリの「OnClick」をダブルクリックします。幅と高さは変数に入れておくので、数値が入れられる変数を2つ用意しておきます。また、白く塗りつぶすため「クリア」メニューで使った「TRect」型の変数も用意します。コードエディタに切り替わったら、太字部分を追加します。
procedure TfrmMain.S2Click(Sender: TObject);
var
intW: Integer;
intH: Integer;
r : TRect;
begin
end;
サイズ変更ダイアログをモード付きフォームとして表示して、戻り値が「mrOk」かどうか調べるIf文を記述します。そして、サイズ変更ダイアログで入力した幅と高さを、それぞれ変数に代入します。太字部分を追加します。
procedure TfrmMain.S2Click(Sender: TObject);
var
intW: Integer;
intH: Integer;
begin
if frmSizeDlg.ShowModal = mrOk then
begin
intW := StrToIntDef(frmSizeDlg.edtWidth.Text, 640);
intH := StrToIntDef(frmSizeDlg.edtHeight.Text, 480);
end;
end;
次にビットマップオブジェクトを破棄して、変数に代入したサイズで作り直します。そして、ビットマップオブジェクトを白く塗りつぶします。太字部分を追加します。
procedure TfrmMain.S2Click(Sender: TObject);
var
intW: Integer;
intH: Integer;
r : TRect;
begin
if frmSizeDlg.ShowModal = mrOk then
begin
intW := StrToIntDef(frmSizeDlg.edtWidth.Text, 640);
intH := StrToIntDef(frmSizeDlg.edtHeight.Text, 480);
if Assigned(bmpBuf) then
begin
FreeAndNil(bmpBuf);
end;
bmpBuf := TBitmap.Create;
bmpBuf.PixelFormat := pf32bit;
bmpBuf.SetSize(intW, intH);
r.Left := 0;
r.Top := 0;
r.Right := intW;
r.Bottom := intH;
bmpBuf.Canvas.Brush.Color := clWhite;
bmpBuf.Canvas.FillRect(r);
end;
end;
最後にペイントボックスのサイズを設定してから、ビットマップオブジェクトの内容を「Repaint」メソッドで描画します。フォームのタイトルバーには「無題」と表示します。保存メニューの「Enabled」プロパティを「True」に設定します。太字部分を追加します。
unit FormDrawing;
interface
(中略)
implementation
uses FormABOUT, FormPaintSize;
{$R *.dfm}
procedure TfrmMain.A1Click(Sender: TObject);
begin
frmAboutBox.ShowModal;
end;
procedure TfrmMain.C1Click(Sender: TObject);
var
r: TRect;
begin
r.Left := 0;
r.Top := 0;
r.Right := bmpBuf.Width;
r.Bottom := bmpBuf.Height;
bmpBuf.Canvas.Brush.Color := clWhite;
bmpBuf.Canvas.FillRect(r);
pbxDraw.Repaint;
S1.Enabled := True;
end;
procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if MessageDlg('終了しますか?', mtConfirmation, [mbOK, mbCancel], 0) = mrOk then
CanClose := True
else
CanClose := False;
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
preX := -1;
preY := -1;
bmpBuf := TBitmap.Create;
bmpBuf.PixelFormat := pf32bit;
bmpBuf.SetSize(640, 480);
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
// ReportMemoryLeaksOnShutdown := True;
if Assigned(bmpBuf) then
FreeAndNil(bmpBuf);
end;
procedure TfrmMain.O1Click(Sender: TObject);
begin
if OpenPictureDialog1.Execute then
begin
if Assigned(bmpBuf) then
FreeAndNil(bmpBuf);
bmpBuf := TBitmap.Create;
bmpBuf.LoadFromFile(OpenPictureDialog1.FileName);
bmpBuf.PixelFormat := pf32bit;
pbxDraw.Width := bmpBuf.Width;
pbxDraw.Height := bmpBuf.Height;
pbxDraw.Repaint;
Caption := Application.Title + ' - ' + OpenPictureDialog1.FileName;
end;
end;
procedure TfrmMain.pbxDrawMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GetKeyState(VK_LBUTTON) < 0 then
begin
pbxDrawMouseMove(Sender, Shift, X, Y);
S1.Enabled := True;
end;
end;
procedure TfrmMain.pbxDrawMouseLeave(Sender: TObject);
begin
stbMain.Panels[0].Text := '';
stbMain.Panels[1].Text := '';
end;
procedure TfrmMain.pbxDrawMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
w: Integer;
c: TColor;
begin
stbMain.Panels[0].Text := 'X = ' + IntToStr(X);
stbMain.Panels[1].Text := 'Y = ' + IntToStr(Y);
if GetKeyState(VK_LBUTTON) < 0 then
begin
if sbtnHoso.Down then
w := 5
else
w := 20;
c := shpColor.Brush.Color;
pbxDraw.Canvas.Pen.Mode := pmCopy;
pbxDraw.Canvas.Pen.Width := w;
pbxDraw.Canvas.Pen.Color := c;
pbxDraw.Canvas.MoveTo(preX, preY);
pbxDraw.Canvas.LineTo(X, Y);
bmpBuf.Canvas.Pen.Mode := pmCopy;
bmpBuf.Canvas.Pen.Width := w;
bmpBuf.Canvas.Pen.Color := c;
bmpBuf.Canvas.MoveTo(preX, preY);
bmpBuf.Canvas.LineTo(X, Y);
end;
preX := X;
preY := Y;
end;
procedure TfrmMain.pbxDrawPaint(Sender: TObject);
begin
pbxDraw.Canvas.CopyMode := cmSrcCopy;
pbxDraw.Canvas.Draw(0, 0, bmpBuf);
end;
procedure TfrmMain.S1Click(Sender: TObject);
begin
if SavePictureDialog1.Execute then
begin
bmpBuf.SaveToFile(SavePictureDialog1.FileName);
Caption := Application.Title + ' - ' + SavePictureDialog1.FileName;
S1.Enabled := False;
end;
end;
procedure TfrmMain.S2Click(Sender: TObject);
var
intW: Integer;
intH: Integer;
r : TRect;
begin
if frmSizeDlg.ShowModal = mrOk then
begin
intW := StrToIntDef(frmSizeDlg.edtWidth.Text, 640);
intH := StrToIntDef(frmSizeDlg.edtHeight.Text, 480);
if Assigned(bmpBuf) then
begin
FreeAndNil(bmpBuf);
end;
bmpBuf := TBitmap.Create;
bmpBuf.PixelFormat := pf32bit;
bmpBuf.SetSize(intW, intH);
r.Left := 0;
r.Top := 0;
r.Right := intW;
r.Bottom := intH;
bmpBuf.Canvas.Brush.Color := clWhite;
bmpBuf.Canvas.FillRect(r);
pbxDraw.Width := intW;
pbxDraw.Height := intH;
pbxDraw.Repaint;
Caption := Application.Title + ' - ' + '無題';
S1.Enabled := True;
end;
end;
procedure TfrmMain.shpColorMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if ColorDialog1.Execute then
shpColor.Brush.Color := ColorDialog1.Color;
end;
procedure TfrmMain.X1Click(Sender: TObject);
begin
Close;
end;
end.
[サイズ変更(S)...]メニューが完成したら、保存して実行します。ツールバーの[すべて保存]ボタンで保存して、[実行]ボタンで実行テストします。実行できたら「お絵かきソフト」の[編集(E)|サイズ変更(S)...]メニューをクリックして、サイズ変更ダイアログを表示します。縦横のサイズを「200」程度にして[OK]ボタンをクリックします。左上に白い四角が表示されます。

図07 完成図
ナッキー:これで、お絵かきソフトが完成なんですね。長かったけどいろんな色を使って遊べたので、楽しかったなぁ。 |
高橋先生:描画の部分はお絵かき以外には、使えないように思うかもしれないけれど、好きな場所に文字を書くのにも使えるんだよ。コンポーネントだと表示される位置が決まっていることが多いからね。描画以外にも使える機能が盛りだくさんだったね。ナッキーもよくがんばったと思うよ。 |
ナッキー:サブフォームが使えるようになったら、新しいプログラムを考えるのが楽しくなりますね。よいしょ、よいしょ。 |
高橋先生:ところで、なんで荷造りしているの? |
ナッキー:え?春だから、ちょっと旅行にでも行こうかと。 |
高橋先生:Turbo Delphiの機能はまだまだ紹介したいんだよ。いっぱいあるんだから。勝手に行ってもらっちゃこまるな。 |
ナッキー:そうですかぁ?じゃあ、「これから春休みにしますので、よろしくお願いしまーす。4月にまた会いましょうねー。」 |
高橋先生:次は、データベースなんだ!けっこう大変なんだよー。あれ?もう行っちゃったの?戻ってきたら厳しくいくぞ! |
|