title: Apollo チュートリアル
Author: NISHIO Mizuho
mailto: mzh@portnet.ne.jp


1. ダイアログ
  各種ダイアログの紹介をします。

1.1. その1(メッセージダイアログ)
  これから紹介するPhi::message_dlgはDelphiのMessageDlgにあたるメソッドです。スクリプトは下のようになります。

  %href: ./rb/dialog1.rb dialog1.rb%

--ruby
001  require 'phi'
002  require 'dialogs'
003  
004  def show_ok_msg(msg)
005    Phi::message_dlg(msg, Phi::MT_INFORMATION, [Phi::MB_OK], 0)
006  end
007  
008  form = Phi::Form.new(:form1, 'フォームです')
009  button = Phi::Button.new(form, :button1, 'hoge')
010  button.align = Phi::AL_CLIENT
011  
012  button.on_click = proc do
013    result = Phi::message_dlg( 'メッセージダイアログです。',
014      Phi::MT_CONFIRMATION, [Phi::MB_OK, Phi::MB_YES, Phi::MB_NO,
015       Phi::MB_CANCEL], 0)
016    case result
017    when Phi::MR_OK
018      Phi::message_dlg('OKのボタンが押されました。', Phi::MT_INFORMATION,
019        [Phi::MB_OK], 0)
020      
021    when Phi::MR_YES
022      result2 = Phi::message_dlg('はいのボタンが押されました。',
023        Phi::MT_ERROR, [Phi::MB_ALL, Phi::MB_ABORT, Phi::MB_RETRY,
024        Phi::MB_IGNORE, Phi::MB_YES_TO_ALL, Phi::MB_NO_TO_ALL], 0)
025      case result2
026      when Phi::MR_ALL
027        show_ok_msg('すべてのボタンが押されました。')
028      when Phi::MR_ABORT
029        show_ok_msg('中止のボタンが押されました。')
030      when Phi::MR_RETRY
031        show_ok_msg('再試行のボタンが押されました。')
032      when Phi::MR_IGNORE
033        show_ok_msg('無視のボタンが押されました。')
034      when 9
035        #when Phi::MR_NO_TO_ALL
036        # Phi::MR_NO_TO_ALLはありません(result2には9が入ります)
037        show_ok_msg('すべていいえのボタンが押されました。')
038      when 10
039        #when Phi::MR_YES_TO_ALL
040        # Phi::MR_YES_TO_ALLはありません(result2には10が入ります)
041        show_ok_msg('すべてはいのボタンが押されました。')
042      end
043  
044    when Phi::MR_NO
045      Phi::message_dlg('いいえのボタンが押されました。', Phi::MT_WARNING,
046        [Phi::MB_OK], 0)
047  
048    when Phi::MR_CANCEL
049      Phi::message_dlg('キャンセルのボタンが押されました。',
050        Phi::MT_CUSTOM, [Phi::MB_OK], 0)
051    end
052  end
053  
054  form.show
055  Phi.mainloop
--

  このスクリプトを実行すると、%href: img/dialog1.png このような% ウィンドウがあらわれます。

1.1.1. 解説
  このスクリプトはボタンが押されると、メッセージダイアログが表示され、表示されたダイアログのボタンを押すと、また別のダイアログが現れます。
 
  2行目の require 'dialogs' はダイアログを扱う際に必要になるおまじないです。必ず require 'phi' の後に書くようにしてください。

  4〜6行はRubyのメソッド定義です。内容については後で説明しますが、ここではdef show_ok_msg(msg) とすることで引数を一つとる show_ok_msg というメソッドを定義することができることを覚えておいてください。

  8〜10行は起動時に表示されるフォームやボタンを生成しています。

  12〜52行はボタンが押された時のアクションを定義しています。

  13〜15行は今までなら1行で記述していた部分を3行に分けています。Rubyではパーサーが文法の区切りをある程度認識してくれますので、このように記述することが可能です。この部分では Phi::messge_dlg を呼び出してメッセージダイアログを表示させています。

  Phi::message_dlg の引数は4つで、第1引数はメッセージダイアログに表示させる文字、第2引数はメッセージダイアログの種類を表す定数、第3引数はボタンを表す定数の組み合わせ( Array のオブジェクト)、第4引数はヘルプボタンがある時に表示するヘルプの番号になります。従って、13〜15行が実行されると、「メッセージダイアログです。」というメッセージが表示される4つのボタンを持つダイアログが現れます。

  Phi::message_dlgの第2引数に取ることのできる値は下の5つです。定数にあわせて外見やタイトルバーに表示される文字が変化するので、サンプルスクリプトを実行して確認してみてください。

  * Phi::MT_CONFIRMATION(確認)
  * Phi::MT_CUSTOM(アプリケーション名)
  * Phi::MT_ERROR(エラー)
  * Phi::MT_INFORMATION(情報)
  * Phi::MT_WARNING(警告)


  第3引数に下の定数を組み合わせたもの(Arrayのオブジェクト)を代入することでダイアログのボタンを変更することができます。例えば、「はい」と「いいえ」のボタンをダイアログに表示させたい場合は、 Phi::message_dlg の第3引数に [Phi::MB_YES, Phi::MB_NO] を代入します。

  * Phi::MB_ABORT(中止)
  * Phi::MB_ALL(すべて)
  * Phi::MB_CANCEL(キャンセル)
  * Phi::MR_HELP(ヘルプ)
  * Phi::MB_IGNORE(無視)
  * Phi::MB_NO(いいえ)
  * Phi::MB_NO_TO_ALL(すべていいえ)
  * Phi::MB_OK(OK)
  * Phi::MB_RETRY(再試行)
  * Phi::MB_YES(はい)
  * Phi::MB_YES_TO_ALL(すべてはい)


  13行目では Phi::message_dlg の返り値がresultに代入されていますが、resultの値は押されたボタンによって値が変化します。13行目を例に取ると、「OK」のボタンが押されると Phi::MR_OK が、「はい」のボタンが押されると Phi::MR_YES が、「いいえ」のボタンが押されると Phi::MR_NO が、「キャンセル」のボタンが押されると Phi::MR_CANCEL が result に代入されます。ちなみに Rubyでは result は単なる変数なので、 Delphi と違って特殊な意味はありません。ボタンの定数 と Phi::message_dlg の返り値の関係は下のようになっています。

  * Phi::MB_ABORT -> Phi::MR_ABORT
  * Phi::MB_ALL -> Phi::MR_ALL
  * Phi::MB_CANCEL -> Phi::MR_CANCEL
  * Phi::MB_HELP -> 無し
  * Phi::MB_IGNORE -> Phi::MR_IGNORE
  * Phi::MB_NO -> Phi::MR_NO
  * Phi::MB_NO_TO_ALL -> 無し(整数の9)
  * Phi::MB_OK -> Phi::MR_OK
  * Phi::MB_RETRY -> Phi::MR_RETRY
  * Phi::MB_YES -> Phi::MR_YES
  * Phi::MB_YES_TO_ALL -> 無し(整数の10)

  
  13行目以降のすべての場合について説明するのは無理なので、ここでは「はい」のボタンが押された時の動作について説明します。13行目の Phi::message_dlg で表示されたダイアログの「はい」のボタンを押すと、result には Phi::MR_YES が代入されます。16行目 case result はresultの値とその下に出てくる when 〜 の 〜 の部分を比較して一致した時(正確にはRubyの === や =~ の結果がtrueの時) に when の部分に書かれたことが実行されます。今回の場合は result の値が Phi::MR_YES ですので、二つ目の when Phi::MR_YES の部分(22〜42行)が実行されます。

  22行では再びメッセージダイアログを表示させています。今回は6つのボタンが表示されるダイアログになっていますが、ここでは「すべてはい」のボタンが押されたことにして、説明を続けます。

  「すべてはい」のボタンが押されると、result2には10(Phi::MR_YES_TO_ALLは定義されていません)が代入されます。次に25行目の case result2 の部分が評価されて39〜41行の部分が実行されますが、39と40行はコメントですので、実際に実行されるのは41行だけです。

  41行は4〜6行で定義した show_ok_msg のメソッド呼び出しです。このメソッドを実行すると、メソッドの引数(「'すべてはいのボタンが押されました。'」)が4〜6行のmsgになり、5行目の Phi::message_dlg(msg, Phi::MT_INFORMATION, [Phi::MB_OK], 0) が実行されます。この場合は「'すべてはいのボタンが押されました。'」が表示される「OK」ボタンを一つ持つメッセージダイアログが表示されます。 

  メソッド定義で注意することは Ruby では Delphi の procedure や function が def (メソッド定義) ですべて統一されているということです( Delphi の property 等も def で定義することになります)。 Ruby のメソッドというのはすべて返り値を持ち、デフォルトでは nil が返ります。ですから本質的には Delphi の function にあたるものしか定義できないわけですが、上の show_ok_msg のように一見すると Delphi の procedure ように見えるメソッドを定義することもできます。Ruby のメソッドの返り値を設定したい場合は return を使うことになります(他の方法もあります)。

  上のスクリプトはどのボタンを押すかによって分岐していくので、サンプルスクリプトを実行して色々と試してみてください。

  補足: 残念ながら今のところDelphiのApllication.MessageBox(Phi::APPLICATION.message_box)とShowMessage(Phi::show_message)は実装されていないようです。

1.1.1.1. クラスやメソッド

: Phi#
* Phi::message_dlg

1.2. その2(ファイル選択のダイアログ)

  %href: ./rb/dialog2.rb dialog2.rb%

--ruby
001  require 'phi'
002  require 'dialogs'
003  
004  form = Phi::Form.new(:form1, 'formです')
005  button = Phi::Button.new(form, :button1, 'hoge')
006  button.align = Phi::AL_CLIENT
007  
008  button.on_click = proc do
009    dlg = Phi::OpenDialog.new
010    dlg.filter = 'テキスト(*.txt)|*.txt|すべて(*.*)|*|'
011    if dlg.execute
012      path = File::expand_path(dlg.file_name)
013      if FileTest::readable?(path)
014        File::foreach(path) do |l|
015          print l
016        end
017      else
018        Phi::message_dlg("#{path}: 読みこむことが出来ません。",
019        Phi::MT_ERROR, [Phi::MB_OK], 0)
020      end
021    end
022  end
023  
024  form.show
025  Phi.mainloop
--

  このスクリプトを実行すると、%href: img/dialog2.png このような% ウィンドウがあらわれます。

1.2.1. 解説
  ボタンを押すと、ファイル選択のダイアログが表示されます。

  目新しいのは8〜22行目ですので、今回はこの部分についてのみ説明します。

  ボタンが押されると、9行目が実行されて Phi::OpenDialog のオブジェクトが生成され、それがdlgに代入されます。 Phi::OpenDialog はファイル選択ダイアログのクラスです。

  次に10行目では dlg.filter( Phi::OpenDialog#filter )の属性によってファイル選択ダイアログに表示されるファイルの拡張子が設定されます。上の例では dlg.filter の値は 'テキスト(*.txt)|*.txt|すべて(*.*)|*|' です。 dlg.filter の説明は少々ややこしいですが、順を追って説明しようと思います。

  最初に dlg.filter の文字を「|」で区切ると、

  * テキスト(*.txt)
  * *.txt
  * すべて(*.*)
  * *


  のようになります。上の項目のうち奇数番目の項目がファイル選択ダイアログの「ファイルの種類」の項目に現れ、その次の偶数番目の項目が表示されるファイルの拡張子になります。従って、上の場合はファイル選択ダイアログの「ファイルの種類」には

  * テキスト(*.txt)
  * すべて(*.*)

  
  の二つが表示されることになります。「ファイルの種類」で「テキスト(*.txt)」を選んだ場合、選択できるファイルは「*.txt」のワイルドカード(ファイルマスク?)で指定されるファイルになり、「すべて(*.*)」を選んだ場合は「*」で指定されるファイルを選択することが出来ます。ちなみに「*」ではすべてのファイルを選択することが可能です。

  ファイル選択ダイアログには他にもいくつかのメソッド(プロパティ)があるので、試してみてください。

  11行目のdlg.execute( Phi::OpenDialog#execute )で初めてファイル選択のダイアログが現れます。11行目以降はこのメソッドの返り値によって処理が変わります。 dlg.execute の返り値はファイル名が設定されている状態でダイアログの「開く」ボタンが押された時にtrueになり、「キャンセル」ボタンが押された時にfalseになります。

  dlg.executeの返り値がtrueの時は12行目が実行されて、 path に選択されたファイルのフルパスが代入されます。 dlg.file_name( Phi::OpenDialog#file_name )の属性には選択されたファイルの名前が入っているので、それを Rubyの File::expand_path を使ってフルパスに変換し、path に代入しています。

  13行目は path で表されるファイルが読みこみ可能かどうかを調べています。 FileTest::readable? はRubyのFileTestモジュールに定義されたメソッドで、このメソッドによってファイルが読みこみ可能かどうかを調べることができます。このメソッドの返り値が false の場合は18〜19行が実行されて、「読みこむことが出来ません。」というメッセージが表示されます。逆に FileTest::readable? が true を返した場合は14〜16行が実行されます。
  
  14〜16行はファイルをオープンしてその内容を標準出力(apollo.exeの操作卓等)にプリントします。「File::foreach(path) do |l| 〜 end」ではpathのファイルの内容が1行読みこまれ、それが「l」に代入され、15行目で「l」が標準出力にプリントされます。「l」がプリントされると、pathのファイルの次の行が「l」に代入されて、再び15行目が実行されます。これがファイルの終わり(EOF)まで続きますので、最終的にpathのファイルの内容のすべてが標準出力にプリントされることになります。

  14〜16行はRubyのイテレーターと呼ばれるもので、ループの抽象化等で使われる便利な仕組みです(馴れるまでは難しく感じるでしょうが)。RubyのFileクラスの使い方も含めて、詳しくはRubyのリファレンスマニュアルを参照してください。

1.2.1.1. クラスやメソッド

: Rubyの組み込みモジュール
* FileTest

: Rubyの組み込みクラス
* File

: Phi::OpenDialog
* Phi::OpenDialog.new
* Phi::OpenDialog#filter
* Phi::OpenDialog#execute
* Phi::OpenDialog#file_name

1.3. その他

  上で紹介したPhi::OpenDialogの他にも

  * Phi::ColorDialog#
  * Phi::FontDialog#
  * Phi::SaveDialog#


  のようなダイアログのクラスがあるので、試してみてください。

  今回はダイアログを自分で定義しなかったですが、Rubyなら自分でダイアログを作ることも簡単にできます。後ほど紹介するつもりですので、頑張ってチュートリアルを読んでいってください。  
