begin { はじめに
これは Delphi Advent Calendar 2017 8 日目の記事です。初心者向けチュートリアルとして Delphi Starter Edition でメモ帳クローンを作ってみたいと思います。
そもそも Delphi とは
ひょっとしてここから説明しなければ?本当に知らない人のためにざっくりと説明すると以下のようになります。
- Pascal。
- ...を魔改造した Turbo Pascal が先祖。
- ...を Windows アプリケーション作成に対応させた IDE (統合開発環境) が Delphi。
- Turbo Pascal for Windows なんてのもあったけど話が複雑になるので割愛
- 言語そのものも Delphi と呼んだりする (言語は Object Pascal)。
- 上位版ではマルチプラットフォーム対応 (Windows 64bit, macOS, Android, iOS, Linux)。
- なんだかんだで今年で 22 周年!
歴史的な経緯については Wikipedia を参照してみてください。
Delphi Starter Edition とは
機能限定版の Delphi で Delphi XE (2011 年) にラインナップされました。当時は有償だったのですが、2016 年の Delphi 10.1 Berlin より無償化され、2017/12 現在の最新版は 10.2 Tokyo となっています。
何が機能限定なのかと言いますと、
- ライブラリのソースコードが付属しない
- DB 関連コンポーネントが使えない
- 一部の IDE の機能が使えない
- 32bit Windows アプリケーションのみ作成可能
大きくはこんなところです。
Delphi Starter Edition のインストール方法に関してはエンバカさんの記事がありますのでそちらをご覧ください。
インストーラの途中でオプションを選択する画面がありますが、Samples と Help は必ずチェックを入れてインストールしてください。
この記事では Delphi Starter Edition がインストールされているものとして話を進めます。
追記 (2018/07/19)
Delphi のフル機能が使える Delphi Community Edition がリリースされました。Windows 32bit に加え、Windows 64bit / macOS / iOS / Android の開発が行えます。
現在、Starter Edition は Community Edition で置き換えられていますが、記事は当時の状況のままにしておきたいので、お手数ですが記事中の Starter Edition
を Community Edition
に読み替えて頂けると幸いです。
プロジェクトを作るよ!
まずは Delphi を起動します。起動直後の画面が以下のようになります。各部の詳細についてはおいおい紹介します。
さて、Delphi には、2つのフレームワークがあります。
- VCL (Visual Component Library)
- FMX (FireMonkey)
前者は従来からある Windows に特化したフレームワークで、後者はマルチデバイスアプリケーション用のフレームワークです。
今回はメモ帳のクローンを作るという目的ですから、[ファイル | 新規作成 | VCL フォームアプリケーション - Delphi] で Delphi アプリケーションを新規作成します。
私の環境には C++Builder Starter Edition も入っていますのでメニューがちょっと多いです。もちろん C++Builder Starter Edition も無償なので一緒にインストールしておくと便利ですよ 1。
プロジェクトを新規作成すると、ちょっと画面が変化しましたね。
[ファイル | プロジェクトに名前を付けて保存] で一旦プロジェクトを保存します。
デフォルトの保存先は C:\Users<アカウント名>\Documents\Embarcadero\Studio\Projects になります。どこでも構わないので、NOTEPAD_CLONE というサブフォルダを作成し、ここにプロジェクトを保存する事にします。
最初は Unit1 に名前を付けて保存 というファイル保存ダイアログが出ていると思うので、frmuMain.pas という名前で保存します。これはメインのソースコードファイルになります。Pascal のファイルなので拡張子は *.pas となります。
次に Project1 に名前を付けて保存 というファイル保存ダイアログが出るので、notepad_clone.dproj という名前で保存します。これは Delphi のプロジェクトファイルとなります。Delphi のプロジェクトファイルなので拡張子は *.dproj となります。このプロジェクト名が実行ファイルの名前になります。
保存が終わったら プロジェクトマネージャ を確認してみましょう。デフォルトでは IDE の右上にあるはずです。
⊞ になっている箇所はマウスでクリックすると展開されます。デフォルトの状態では以下のような構成になっています。
- プロジェクト名 (EXE 名)は notepad_clone
- デバッグビルド (Debug)
- Windows 32bit アプリケーション (Win32)
- ファイルは frmuMain が一つ
何はともあれこの状態で 〔F9〕キー またはツールバーにある 実行ボタン を押してみましょう。
コンパイルの進捗ダイアログが表示され...
何もないですが、フォーム (ウィンドウ) が表示されたと思います。この時、IDE は
デバッグ実行 状態になっています。
✖ を押してフォームを閉じるか [実行 | プログラムの終了] でプログラムを終了させると、デバッグ実行が終了します。デバッグ実行が終了したら、プロジェクトファイルのあるフォルダを覗いてみましょう。プロジャクトマネージャにあるプロジェクト名を右クリックすると [エクスプローラーで表示] がありますのでこれを選択し、プロジェクトの場所をエクスプローラーで開きます。
このような構成になっていると思います。
生成されているファイルの詳細は以下のドキュメントを確認してください。
さて、Win32 フォルダを開くと、debug フォルダがあり、その中には notepad_clone.exe ができています。プロジェクトマネージャで指定された通りですね。ではこれをダブルクリックして実行してみましょう。
ちゃんと実行ファイル (EXE) ができていますね!
このように Windows アプリケーションを実に簡単に作る事ができるのが Delphi の特徴です。
外観を作るよ!
さて、何もない所から頼りなく始めます(?)。IDE の画面中央に表示されているのがフォームデザイナです。ここに コンポーネント と呼ばれる部品を貼り付ける事ができます。エディットボックスやボタン等の コントロール もコンポーネントの一種です。
フォームデザイナの状態で 〔F12〕 を押すと、コードエディタになります。
しばらくはフォームデザイナで作業を行いますので、間違ってコードエディタにしてしまった場合にはもう一度〔F12〕を押してフォームデザイナに戻してください。
プロジェクトマネージャからも切り替えられます。.pas をダブルクリックするとコードエディタ、.dfm をダブルクリックするとフォームデザイナになります。
コンポーネントの配置
コンポーネントは右下にある ツールパレット から持ってくることができます。例えば [Standard] タブにはこのようなコンポーネントが用意されています。
”T~” という命名ですが、この接頭辞は クラス を表しています。例えば TEdit は Windows のエディットコントロールを Object Pascal 言語のクラスでラッピングしたコンポーネントです。
ここにある TMemo をフォームデザイナに貼り付けてみましょう。貼り付ける方法は 3 つあります。
- ツールパレットにある TMemo をフォームデザイナの任意の場所へドラッグ&ドロップ
- ツールパレットにある TMemo をクリックしてからフォームデザイナの任意の場所をクリック
- ツールパレットにある TMemo をダブルクリック
貼り付ける場所を指定しないでいいのならダブルクリックが最も簡単です。とにかく貼ってみます。
貼り付けられた TMemo は Memo1 という名前になっています。オブジェクト (インスタンス) の名前が Memo1 という事になります。これは IDE 左下の オブジェクトインスペクタ で確認できます。
Name というのがこの TMemo 型オブジェクトの Name プロパティ となります。プロパティとはオブジェクトの属性を表すものです。ここでオブジェクトの名前を変更する事ができますが、既に貼られているコンポーネントと同じ名前にする事はできません。
用語に混乱してきましたか?ちょっと整理しますね。
- コントロール: その名の通り、制御するもの。GUI 部品など。
- コンポーネント: Object Pascal で使える部品。コントロールのようにビジュアルなコンポーネントだけでなく、非ビジュアルなコンポーネントもある。
- クラス: フィールドやメソッド、プロパティなどの構造を定義したもの。クラス型。
- プロパティ: クラスの構成要素の一つ。属性。
- フィールド: クラスの構成要素の一つ。定数や変数。メンバ変数とも。
- メソッド: クラスの構成要素の一つ。関数や手続き。
- オブジェクト: クラスの実体。インスタンス。
メモ (複数行エディット) は Windows のコントロールで、それを Object Pascal のクラスでラッピングしたものが TMemo。これはコンポーネントであり、フォームデザイナに貼る事ができます。フォームデザイナに貼られた TMemo 型のオブジェクトが Memo1 となります。オブジェクトの名前は Name プロパティで変更可能です。
続けましょう。フォームに貼ったメモコントロールをマウスでクリックすると選択状態になり、コンポーネントの8方向に青い点 (グラブハンドル) が表示されます。
グラブハンドルでない部分をマウスでドラッグすればコンポーネントを移動でき、グラブハンドルを持ってドラッグすればコンポーネントの大きさを変更する事ができます。コンポーネントの移動とリサイズはフォームに表示されているグリッド (点) の単位で行われますが、〔Alt〕キーを押しながらドラッグすれば、1 ドット単位で移動/リサイズできます。その他の操作方法は以下のようになります。
ショートカット | 動作 |
---|---|
マウスで領域選択 | 複数のコンポーネントを選択します |
〔Ctrl〕+ マウスで領域選択 | 既に選択されている親コンポーネント内にある子コンポーネントを選択します。 |
〔Ctrl〕+ マウスクリック | コントロールを追加で選択します (複数選択)。 |
〔Ctrl〕+ カーソルキー | 選択されたコントロールを 1 ドット単位で移動します。 |
〔Ctrl〕+〔Shift〕+ カーソルキー | 選択されたコントロールをグリッド単位で移動します。 |
〔Shift〕+ カーソルキー | 選択されたコントロールを 1 ドット単位でリサイズします。 |
〔Tab〕 | コンポーネント間を移動します (選択の切り替え)。 |
〔Esc〕 | 既に選択されている子コンポーネントの親コンポーネントを選択します。 |
〔Delete〕 | 選択されているコンポーネントを削除します。 |
〔Ctrl〕+〔C〕 | 選択されているコンポーネントをクリップボードにコピー。 |
〔Ctrl〕+〔V〕 | クリップボードにコピーされたコンポーネントを貼り付け。 |
ではこの Memo1 を画面いっぱいに広げてみてください。コンポーネントの移動/リサイズはオブジェクトインスペクタからも行えます。
Left / Top プロパティでコンポーネントの位置を、Width / Height プロパティで幅と高さを変更する事ができます。
ここまでできたら〔F9〕を押して実行してみてください。
メモ (複数行エディット) コントロールに文字を入力する事ができるようになりましたね。でもウィンドウの右下を引っ張ってリサイズすると...
んーうまくありませんね。ウィンドウのリサイズにコンポーネントのサイズが追従しないようです。メモコントロールはウィンドウ内で最大化して欲しいですね。このような場合には Align プロパティを変更します。
プロパティを変更する際はフォームを閉じてデバッグ状態を解除しておきます。
alNone になっているのを alClient に変更します。文字を入力して変更してもいいのですが、右側に ▼ マークのボタンが出ていますね。このようなプロパティは値を選択できます。ボタンを押すか値をダブルクリックしてみてください。
何やら出てきましたね。このように一部のプロパティにはプロパティエディタが用意されている事があり、プロパティエディタによって直感的に値を変更できる事があります。今回の場合、真ん中の大きいボタンが alClient です。Align プロパティの詳細については以下のトピックを参考にしてください。
Memo1 の Align プロパティを alClient に変更したら〔F9〕を押して実行してみてください。
今度はリサイズしても大丈夫なようです!
メニューの追加
さて、とりあえず見た目はそれっぽいものができたので、メニューを追加します。本物のメモ帳 (notepad) を観察してみると上部にメニューがありますよね。これを実装します。
メニューを追加するにはツールパレットから TMainMenu をフォームデザイナに追加します。TMainMenu は非ビジュアルコンポーネントなのでダブルクリックして追加するといいでしょう。
TMainMenu を追加するとこんな感じになります。
TMainMenu は非ビジュアルコンポーネントなのでただの四角いアイコンです。このアイコンをダブルクリックすると TMainMenu のコンポーネントエディタが起動してメニューを編集できるのですが、とりあえず今はこのままにしておきます。
フォームデザイナでフォームを選択します。「Memo1 が邪魔でフォームを選択できない」?そんな時は〔ESC〕キーを何度か押しましょう。どの選択状態であっても何度か〔ESC〕キーを押せばフォームを選択できます。
それ以外の方法として、左上の [構造] ペインで Form1 を選択しても構いませんし、
オブジェクトインスペクタの上部にあるコンボボックス (インスタンスリスト) で Form1 を選択しても構いません。
そして、オブジェクトインスペクタで Menu プロパティをみてみると、MainMenu1 が関連付けられているのが分かりますね。
続いてツールパレットから TActionList を追加します。これも非ビジュアルコンポーネントです。
この TActionList ですが、何をするものかと言うと機能をアクションという単位で実装して管理するリストです。アイコンをダブルクリックするとコンポーネントエディタが開きます。
左上のアイコンを押すか、〔Ins〕キーを押してアクションを新規作成してみます。
Action1 が追加されましたね。コンポーネントエディタで Action1 を選択するとオブジェクトインスペクタでも Action1 が選択されます。各プロパティを以下のように変更しましょう。
プロパティ | 値 |
---|---|
Caption | 新規(&N) |
Category | File |
Name | acNew |
Shortcut | Ctrl+N |
TActionList コンポーネントエディタのコンポーネントエディタも変化するはずです。
同様にメモ帳の [ファイル(F)] メニューにある項目をすべて追加しましょう。
Action (Name) | Caption | Category | ShortCut |
---|---|---|---|
acNew | 新規(&N) | File | Ctrl+N |
acOpen | 開く(&O)... | File | Ctrl+O |
acSave | 上書き保存(&S) | File | Ctrl+S |
acSaveAs | 名前を付けて保存(&A)... | File | |
acPageSetup | ページ設定(&U)... | File | |
acPrint | 印刷(&P)... | File | Ctrl+P |
acExit | メモ帳の終了(&X) | File |
- キャプションの () 内の文字はアクセラレーターキーと呼ばれるもので、アクセラレーターキーは &を付けて指定します。英語だと &New のような記述になり、N の下にアンダーバーが付きます。日本語版 Windows ではメニューが翻訳されるとそのような記述ができないため、アクセラレーターキーは慣習的に () 内に記述する事になっています。
- アクセラレーターキーはアンダーバーが付いたキーを押せばメニューが選択されるという意味で、例えばメモ帳ですと、〔Alt〕キーを単独で押した後に〔F〕、〔O〕と入力すると [開く(O)...] メニューが選択された事になり、ファイルオープンダイアログが開きます。
- キャプションの ... は 次に何かのウィンドウがある という意味です。"..." がないメニューの機能は即実行されます。これも慣習なのですが、海外のアプリケーションが翻訳された場合にはこの慣習が無視される事が多いです。
- ショートカットはその名の通りショートカットです。〔Ctrl〕+〔S〕を押せばメニューを開かなくてもそのメニュー (機能) が実行されます。
- (余談) 古い Windows のメモ帳は 64KB 以上のファイルを開けませんでした。
- (余談) 古い Windows のメモ帳は〔Ctrl〕+〔F〕で検索できませんでした。
今度はフォームデザイナ上の MainMenu をダブルクリックし、TMainMenu のコンポーネントエディタを起動します。
まだメニューが何もない状態ですね。オブジェクトインスペクタに移動し、この名前のないメニューを [ファイル (F)] にします。Caption にキャプションを指定すれば、Name プロパティは自動で設定されます (F1 等)。
コンポーネントエディタもこのように変化したと思います。
ではこの [ファイル(F)] メニューに機能を追加していきましょう。
[ファイル(F)] メニューの下の何もない所を選択し、オブジェクトインスペクタを開き、Action プロパティのドロップダウンリストから acNew を選択します。
するとコンポーネントエディタにメニューが追加されます。
同様にすべてのアクションをメニューに割り当てていきましょう。
ん?本物のメモ帳には区切り (セパレーター) がありますね。これはどうしたらいいのでしょうか?
コンポーネントエディタを開き、区切りを入れたい場所の下にあるメニューアイテムを選択した状態で〔Ins〕キーを押しましょう。
空白が挿入されたので、オブジェクトインスペクタに移動し、Caption に - (ハイフン) を入力します。
セパレーターが作成されました。
同様に、もう1か所にもセパレーターを挿入します。
これで OK ですね。
- メニューの並びはドラッグ&ドロップで入れ替えられます。
- 間違って追加したメニューアイテムは〔Del〕キーで削除されます。
- メニューアイテムを削除してもアクションが削除されるわけではありません。
この時点で〔F9〕を押して実行すると、とりあえずメニューが表示されますが、コードが記述されていないのでメニューがすべてグレーアウトしていますね。
...そうなんです、実はここまで1行もコードを書いていないのです。
// 続く
長くなったので後編に続きます。
-
残念ながら Community Edition では Delphi と C++Builder を同居させられません。 ↩