UNIX USER 2003/10
この項は、ソフトバンクパブリッシングのUNIX USER誌 2003/10月号に掲載された記事の原稿(校正前)を、2004/06〜7月に改変・公開したものです。
(そのため、古い情報が混じっていたらごめんなさい。)→混じってました。2004/10/28修正
皆さんは、人から「ちょっとしたプログラム」の作成を頼まれたりしないでしょうか。例えば、「毎日、○○なテキストフォーマットでメールが来るんだけど、Excelで楽に吸い込めないかなあ」とか、「どこそこのWebの様子を楽に確認できる方法作れない?」とか、そう言ったような話です。まあ要は楽をしたいという要望がもっぱらなのでしょうが、相手が、上司、客先、友人、彼氏、彼女、配偶者などで、無視するわけにも行かない場合も多く(逆に無視できない相手が頼んで来ますね)、結局何とかしなくてはなりません。そして頼んできた相手が使っているのは、大体Windowsで、ややこしいのをインストールするのは嫌(会社関係の場合、許可されないことも)、と言われてcygwinや他のツールを導入できなかったりします。
Windowsに詳しければいいのですが、もしWindowsへのなじみが薄かったらどうするか。今回はスクリプト言語Rubyを使い、Windows向けアプリケーションを作る方法を書いていくことにします。あらかじめ、言語としてのRubyについては知識があると想定させていただきます。
まず、何はともあれRubyですが、これはもう、紹介するまでも無いでしょう。詳しくは総本山(?)であるホームページ「オブジェクト指向スクリプト言語Ruby」(http://www.ruby-lang.org/ja/)をご覧下さい。簡単にご紹介しますと、Rubyとはまつもとゆきひろ氏によって開発された、手軽に楽しくオブジェクト指向出来る言語です。また、強力なライブラリが標準添付、または公開されており、膨大な処理が簡潔に書けるという特徴もあります。本誌2002年2月号にはRubyの特集がありました。
このRubyで書かれたスクリプトをWindowsの実行形式にするのが、Yuya氏によるExerbです。Exerbは、Rubyのスクリプトを実行形式のEXEファイルに変換します。ツールの基幹部分がrubyスクリプトを使って書かれているため、Windows以外のプラットフォームでも実行可能です。不特定多数への配布はライセンスなどに気を付けなければなりませんが、このExerbを使って、一般Windowsユーザ向けのフリーウエア作成をしている方もいらっしゃいます。
そしてWindowsならやはりGUIを使いたくなるということで、拙作のVisualuRuby計画(仮称)を使ったGUI付きのスクリプトのご紹介もしていきます。また、WindowsのAPIを知らないと書けないけれども、あると便利なライブラリも適宜紹介します。
では実際に、適当な例を取って、スクリプトを作成していきましょう。おっとその前に、自分自身の環境へのRubyその他のインストールが必要です。開発用のWindowsマシンにも入れておきましょう。
本稿は筆者の持つ環境の都合により、Windows98SE上のRuby-1.8.0をベースに書かれています。Windows2000でもスクリプトの動作検証などはしていますが、記述の足らない点があるかもしれません。Windowsのバージョンに関してはかなり古くて申し訳ないのですが、どうかご容赦をお願いします。
ExerbによるWindows用実行形式(EXEファイル)作成はUNIX上でもできますが、本稿ではWindows上の操作を書いていきます。まあ、MS-DOSプロンプトからの操作なので、UNIXでの操作はすぐに想像が付くと思います。
まずはrubyのインストールですが、これは当然お使いのOSによって方法が異なります。わざわざ私がここで書かなくてもRubyのホームページから辿れるところに「インストールガイド」(http://www.ruby-lang.org/ja/install.cgi?cmd=view;name=top)というのがありますので、そちらをご覧頂いた方が良いとは思います。Windows上のRubyには幾つか種類 <コラムへの参照> がありますが、ここでは、インストールの一番簡単なActiveScriptRubyをWindowsマシンにインストールすることにします。
ActiveScriptRubyはarton氏のサイト(http://www.geocities.co.jp/SiliconValley-PaloAlto/9251/ruby/)からダウンロードできます。2004/07/06時点ではバージョンが1.8.1.2です。左から3つの数字はRuby本体のバージョンに相当している(少なくとも今までは)ので、このActiveScriptRubyは、ruby-1.8.1に相当します。ダウンロードページに移って、新しいActiveScriptRubyを入手してください。拡張子がmsiですが、これはWindows Installer用の形式です。Windows98/NT4以前ではコンポーネントのインストールが必要ですが、これはダウンロードページの指示に従ってください。Microsoft Wordなどをインストールした際に一緒に導入済みになっていることも多いです。Windows Installerがインストールされていれば、ダウンロードしたmsiファイルをダブルクリックすることでインストールが始まります。 普通のインストーラですので、画面の指示に従ってください。それでインストールは終わりです。インストールが終われば、スクリプトの開発に移って行きましょう。(ruby.exeのあるディレクトリにパスは通しておいてください)
Windows上でのRubyスクリプト開発のための環境がいくつか開発されています。代表的なものはRDE(http://homepage2.nifty.com/sakazuki/rde.html)やRubyWin(http://homepage1.nifty.com/markey/ruby/rubywin/)、Apollo(http://www.moriq.com/apollo/: Delphiのランタイムが別に必要)などでしょうか。海外ではSciTE(http://www.scintilla.org/SciTE.html)など他のものも出ていますが、Unicode以外の漢字コードを扱えないことが多いです。
ここで例となるスクリプトを作成してみます。お題は、デジカメ写真のサムネイル印刷用HTMLの作成です。実はちょうどこの記事を書いているときに要り用だったもので...
これは、画像ファイル群を与えると、その画像をHTMLのTABLEタグを使って配置し、HTMLを出力します。そのHTMLファイルをInternetExplorerやNetscapeなどの印刷機能を使えば紙に出力されたサムネイルを得ることができるというものです。Windowsだとフリーウエアを探しても似たようなものがたくさん手に入りますが、スクリプト書きに慣れてさえいれば、いちいち探して試しているよりは作っちゃったほうが早いことも多いです。
まずは何を入力にして何を出力にするかを決めねばなりませんが、目的に従い、
そしてこれを実装したのがthumb.rbです。Rubyのパワーのおかげで単純なスクリプトになっていますが、それでもWindowsならではの問題が出てきます。
Windowsではパスの区切り文字として使われるのは"\"ですが、UNIXでは"/"です。パス区切り文字の問題が出る所としては、DirクラスやFileクラスのメソッドがあります。標準添付ライブラリではパス区切り文字を"/"として問題が無いように作られているので、Rubyを使う限りはパス区切り文字を"/"に統一したほうが良さそうに思えます。ただしそれは、Rubyインタプリタの組み込みクラスの世界に留まっていられればの話であって、system()などで外部コマンドを呼び出したり、ruby標準添付のWin32API拡張ライブラリを使ってWindowsのAPIを直接利用したり、その他のライブラリの利用を始めたりすると、このパス区切りの問題には時々悩まされることになるでしょう。InternetExplorerはパス区切り文字として"/"を使えるので今回は"\"が使われてそうなところでは毎回"/"に変換しています。to_slashpath()という関数(メソッド)がその機能を担っています。この変換をさぼると、Dir.glob()がちゃんと動かなくなりました。
Windows9xシリーズのOSでは、いにしえより伝わる8.3形式(ショートファイルネーム)の問題があります。WindowsのExplorerの機能であるショートカット(左下に矢印のマークの付いたアイコンで表示されてるアレです)にファイルをドロップすると、Win98以前ではそのファイル名は8.3形式で渡されてしまいます。そうでなくても手で入力するのが面倒な時などにワザと8.3形式で入力することもあるでしょう。そのため場合によっては、8.3形式のファイル名を通常のロングファイルネームに変換する必要があります。
この変換にはWindowsのAPIを利用する必要がありますが、この機能を実装したものとして、lfn.rbを挙げておきます。この中では関数が2箇所で定義されていますが、これはGetLongPathName()という便利なAPIがWin98以降でしか定義されていないためで、念のためにWin95用の方法も実装しています。
ちなみに、GetLongPathName()はパス区切り文字として"/"を利用可能ですが、変換のついでに"/"を"\"に置換して返してくるようです。まるで2つの世界のせめぎ合いのようですが、時々こういうことがありますので、どうかご注意を。
ファイルシステム周りとしては、Dirクラスで利用するワイルドカードがDOSのものと違っているのでWindowsの知識のある方は逆に引っかかることがあるかもしれません。Dir.glob,Dir[]などで使えるワイルドカードは、WindowsやDOSで使うワイルドカードではありません。Rubyのドキュメントを参照してください。UNIXでシェルを使いこなしてきた方にはなじみのある仕様だと思います。
Rubyのワイルドカードでは大文字と小文字は区別されます。しかしWindowsではファイルシステムが大文字小文字を特に区別しないので、今回のようにパターンでケースを無視するか、Dir.glob()の第2引数に File::FNM_CASEFOLD を指定してケースを無視させる必要があります。そうしないとマッチして欲しいファイルがマッチしない原因になります。なぜかWindows(explorerかも?)が時々ファイル名の大文字小文字を勝手に替えてしまうことがありますので注意が必要です。以下に拡張子が".jpg"であるファイルの一覧を得る記述例を書きます。
Dir.glob()の仕様は時々変化しているようです。
また、行末を示すコードのCRLFとLFの違いも気にしておいてください。これは組み込み変数の$\や$/の設定でうまくごまかせることもありますし、ファイルを開く時に常にバイナリモードで開けばOKという場合もあります。どういう使い方をするかで対処法も変わるので一般論はありません。
他にファイル終端の問題があります。今回のthumb.rbの実装では明示的にバイナリモードでの読み取りを指定しなかった場合、画像ファイル内の0x1A(CTRL-Z,EOF)で読み込みが終了してしまいました。これはMS-DOSのさらに前身のCP/Mあたりからの名残(注1)だと思いますが、こういうこともありますのでご注意を。
今回は利用しませんでしたがファイルシステム以外の有名な問題として、ActiveScriptRubyを含むmswin32版rubyではfork()が動きません。そのため、fork()を必要とするライブラリが動きません。また、getsやgetcを呼んでしまうとインタプリタ自体が止まってしまうため、他のスレッドも一緒に停止してしまいます。
system()回りも挙動の変更が多い部分です。(追記)
このほか、Windowsに限りませんが、漢字などの2バイトコードによる問題が発生することがあります。Windowsでは通常、ShiftJISが利用されていますので、そのような文字を扱うスクリプトを起動するときには、rubyに漢字コード設定の -Ks オプションを付けて起動しましょう。特に日本語版Windowsを常用する日本人にとっては、この漢字コード指定のオプションは常に付けておいてもいいくらいです。漢字コードの設定を忘れて文字列処理でハマったり、スクリプトのロードで失敗している人を良く見かけます。
上のような問題点を解決してスクリプトが出来上がるわけですが、ここでスクリプトを実行してみます。まずMS-DOSプロンプト(もしくはコマンドプロンプト)を起動して、thumb.rbをおいたディレクトリに移動し、下のようにしてスクリプトを実行してください。ただし、picture-dirの部分は、画像ファイル(jpeg)の入ったディレクトリのパスを指定してください。
c:\temp> ruby thumb.rb picture-dir
実行にはthumb.rbの他、「Windows上での問題点」で記述したlfn.rb、後述のimage_size.rbとsfolder.rbが必要です。
picture-dirの部分は、手で打たなくてもMS-DOSプロンプトへのディレクトリのドロップで入力できます。スクリプトを見ればすぐわかると思いますが、picture-dirは複数並べて指定できます。
スクリプトを読まれる方のため、スクリプトのポイントを列挙しておきます。スクリプト中のコメントもご覧下さい。
画像ファイルの縦横サイズの取得には、標準添付でないライブラリの力を借りています。ここでは RAA(Ruby Application Archive)から取得した三並氏によるimage_sizeというライブラリ(http://raa.ruby-lang.org/list.rhtml?name=image_size)を利用しました。Rubyの標準添付でないライブラリを検索する手段として、RAAが便利です。
RAA(Ruby Application Library; http://raa.ruby-lang.org/)は、Ruby上で利用できるアプリケーション、ライブラリを集めたアーカイブです。「アプリケーション」と銘打ってはいますが、アプリケーションに限らずライブラリが多数登録されています。そして検索機能やカテゴリによる階層構造により、探しているライブラリを見つけることができます。登録も自由に行うことができます。
RAAには、純粋にRubyのみで書かれたライブラリやアプリケーションの他、Cコンパイラなどを使ってコンパイルしなければならない拡張ライブラリと呼ばれるライブラリも入っています。これらの作成には相応の開発環境が必要です。Web上でコンパイル済のバイナリを見つけることができる場合がありますが、特にWindows上ではどの種類のruby用か(cygwin版用かmswin32版用か)、そしてrubyのバージョンによって互いに互換性がありません。ご注意ください。もし運良く利用可能なバイナリを発見できた場合はruby.exeからみて ../lib/ruby/site_ruby/$RUBY_VERSION/i386-* (*の部分はいろいろ)に入れておきましょう。$RUBY_VERSIONは1.6や1.8など、お使いのrubyのバージョンです。
参考まで、今回の画像ファイルのサイズ取得のライブラリimage_sizeを検索するときには、RAAトップのページからの検索で、キーワード「jpeg」で引いて見つけました。デジカメ画像の情報のExifを扱うライブラリも幾つか登録されていますので、thumb.rbはそれを使ってさらに拡張できます。
当たり前なのですが、Rubyのスクリプトを起動するためには条件があります。それは、rubyのインタプリタがインストールされていることと、必要なrubyのライブラリが揃っている事です。自分の開発環境で動作させる場合は全部揃っていて当然かもしれませんが、スクリプトを人に渡すときや、自分のマシンでも常用でないマシン上で使う場合にはこれが面倒な問題になることがあります。そこでExerbです。Exerbを使うと、Rubyがインストールされていなくても実行できるexeファイルを作成できます。
Exerbはスクリプト、Rubyインタプリタ、Ruby拡張ライブラリを一つのファイルにまとめて実行形式(EXEファイル)を作成するものです。
まずはExerbを取得し、インストールしましょう。Exerbのホームページ(http://exerb.sourceforge.jp/)から最新バージョンをダウンロードします。2004/07/06にははexerb-3.2.0.tar.gzが最新でした。これを展開し、展開したディレクトリでドキュメント(Readme.ja.rd)に従って
c:\temp>ruby setup.rb config c:\temp>ruby setup.rb setup c:\temp>ruby setup.rb install
原稿執筆時点ではExerbはruby-1.6.8相当がデフォルトになっています。そのため、ruby-1.8用の拡張ライブラリの扱いに問題があります。そこでruby-1.8に対応させるためにExerb Core Collectionをインストールすることにします。これは先ほどのExerbのホームページから取得出来ます。執筆時では exerb-cc-2.6.6.tar.gz が最新で、これも展開してExerb本体と同様にinstall.rbを呼び出して(<手順1>)インストールします。ただし、このバージョンの問題は原稿掲載時点では改善されているかもしれません。Exerb本体がruby-1.8に対応していた場合はExerbCoreCollectionのインストールは不要です。(別にインストールしても困りません)
さて、インストールが終わったら、先ほどのthumb.rbを実行形式に変換してみましょう。実行形式の作成にはレシピファイルが必要となります。このレシピファイルは実行ファイルに格納するスクリプトやライブラリの一覧とその他の情報(漢字コードや内部名など)を記述するファイルです。実行時には、このレシピファイルに記述された一番最初のスクリプトが実行されます。このレシピファイルは手動で作成するよりは、ツールを使って自動生成するのが楽です。自動生成には以下のコマンドを実行します。
c:\temp>ruby -r exerb/mkexr thumb.rb
このようにすると、thumb.rbが利用しているライブラリの一覧を自動的に保存しながらthumb.rbが実行されます。そして実行終了後、次のようなthumb.rbc というレシピファイルが生成されます。
# generated by mkrbc.rb kcode sjis script thumb.rb library Win32API.so D:/ruby/lib/ruby/1.8/i386-mswin32/Win32API.so script image_size.rb D:/ruby/lib/ruby/site_ruby/1.8/image_size.rb script lfn.rb script sfolder.rb
実行時に動的に要求されるライブラリが登録されていないことがあります。その場合は手動で登録するか、そのライブラリが要求されるような状況を作り出して実行してください。
Exerb付属のチュートリアルではexerb.rbを実行形式として直接実行していますが、NT系列でないWindowsでは何か細工をしないと普通はこれは無理でしょう。exerb.rb自身はrubyインタプリタと同じディレクトリに入っていると思いますので、バッチファイルを作っておくなどした方が良いでしょう。
exerb.batとして、
@echo off ruby D:/ruby/bin/exerb.rb %1 %2 %3 %4 %5 %6 %7 %8 %9
そうして、
exerb.bat thumb.exr
このthumb.exeにはスクリプトもライブラリもインタプリタ自身もすべて含まれているため、Windowsマシンであればどこへ持っていっても動くでしょう。ちなみに筆者の環境ではファイルサイズが500kByte弱(exerb-2.6.6時点)になりました。
このthumb.exeは全く普通のWindowsの実行形式として扱えます。ですから、単独でクリックして起動することも出来ますし、thumb.exe本体もしくはthumb.exeのショートカットへのファイルやディレクトリのドロップも出来ます(注2)。今回の用途では意味がありませんが、特定の拡張子を生成されたthumb.exeに関連付けることも出来ます。
さて、今回作ったスクリプトは画像ファイルを縮小して一覧するHTMLの生成を行う物でした。筆者はこれ(thumb.exe)のショートカットをデスクトップに置き、デジカメ画像のフォルダの名前を適切な名前に替えてからこのショートカットにドロップして使っています。画像数が多すぎるとリソース不足で落ちたりするのはご愛敬。
また、Exerb自身はrubyが動けばWindows以外でもインストールして動作させることが出来ます。実際にLinux上のExerbで処理して、それをWindowsで実行しましたが、問題なく動作しました。
今回はMS-DOSプロンプトやcmd.exeから使うCUIの実行形式として作成したため、実行するとそのMS-DOSプロンプトの画面が開いていました。この画面から旧来のCUIの流儀で人間と入出力するのでない限り、これはイマイチです。Windowsのソフトとしてはかっこわるいのです。そこで次章では、GUIを利用したスクリプトを作成し、Exerbを使ってMS-DOSプロンプトの開かない実行形式を作成することにします(注3)。
Windows上でRubyから使えるGUI系のライブラリには以下のような物があります(全部ではありません)。[かっこ内]は依存する外部ライブラリです。
これからご紹介していくのは、この中のVisualuRuby計画(仮称)(http://www.osk.3web.ne.jp/~nyasu/software/vrproject.html)のライブラリです。拙作のこのライブラリは、上の一覧を見て頂いても分かるとおり、他のGUIライブラリと比べると、必要な外部ライブラリが存在しないという点が特徴です。Windows自身が持っている、ボタンやリストボックス、ツリービュー、メディアプレーヤなどのGUI部品を扱うため、外部ライブラリを必要としません。このことがExerbで処理したRubyスクリプトを配布する際には強力な利点となると思います。(Exerbはrubyと関係のない外部ライブラリまでは纏めません)
逆に欠点としては、Windowsにべったりであることから、他のOS上ではまったく動きません。GtkやTk、そしてDelphiまでもがマルチプラットフォームなライブラリとしてOS依存性を減らしています。しかしこのVisualuRuby計画(仮称)では、そういったOSに関するマルチプラットフォームは切り捨てています。敢えて言うならWindowsの世界内部での環境依存性(どんなライブラリがインストールされているかということ)を無くしています(注4)。
まずはインストールしなくてはなりません。ただしActiveScriptRubyをインストールされたのでしたら、元から入っていると思います。他の配布を選択されている場合は、ご自分でインストールする必要があるかもしれません。
VisualuRuby計画(仮称)は2つの部分から成り立っています。Windowsのメッセージ処理やリソース管理などを行うswinと、もう一つはWindowsのGUI部品を扱うvrubyです。swinは単独でも利用可能ですが、煩雑なお約束事が多いのでvrubyも一緒に導入します。
この節は、ActiveScriptRubyを導入された方は飛ばしてください。
まずswinですが、これは拡張ライブラリでありインタプリタの種類に依存します。適切なCコンパイラ(注5)が必要です。まずソースをhttp://www.osk.3web.ne.jp/~nyasu/vruby/core.htmlから取得して展開します。Rubyの拡張ライブラリの作成方法に従い、ソースのあるディレクトリで
c:\temp> ruby extconf.rb c:\temp> make c:\temp> make install
次にvrubyの方ですが、vrubyの一式はlzhまたはzipで固められていますので、それをswinソースと同じところから取得して展開し、
c:\temp> ruby vrinstall.rb
さて、もういい加減「VisualuRuby計画(仮称)」と長々と書くのが面倒くさくなってきましたし、とりあえず利用するのは本計画のvrubyなので、以後はvrubyと書きます。
このvrubyがどのようにGUI部品を配置し、スクリプトがどのようにイベントを受けるかを説明しておきます。vrubyに限らず、GUIのスクリプトが他のスクリプトと違って見えるのは、おそらくこれらのポイントのみでしょう。
vrubyを利用して、GUI、というよりウインドウを表示するためには、まずトップレベルのウインドウが必要です。このようなウインドウは、VRFormというクラスで表現されます。何もないトップレベルウインドウを表示してみましょう。こんなものはファイルを作るまでもなく、コマンドラインから以下のように起動してみます。-eオプションは次の引数をスクリプトとして実行するオプションです。swinとvrubyのインストールが正しく済んでいれば、のっぺらぼうのウインドウが出るはずです。
c:\temp> ruby -r vr/vruby -e 'VRLocalScreen.start(VRForm)'
あとはこののっぺらぼうのウインドウに対してボタンを乗せたりサイズを変えたりウインドウのタイトルを付けたりしていくことになります。ボタンなどのGUI部品を乗せる方法は、VRFormのインスタンスを作成してからそれにどんどん部品を乗せていくことも出来ますが、ここでは継承を使って部品込みのトップレベルウインドウを定義することにします。
vrubyでは、トップレベルウインドウであるVRFormや、ただののっぺらぼうなGUI部品であるVRPanelなど、上にGUI部品を乗せる事が出来るウインドウのクラス(注6)では、インスタンスがウインドウの実体を生成した直後に、construct()というメソッドが呼ばれます。このconstructというメソッドの意義は、適切なタイミングで子となるGUI部品を生成することにあります。ですので、VRFormを継承した子クラス(注7)でconstruct()メソッドを定義して、そこでGUI部品を生成します。ボタンを一つ乗せてみましょう。simple.rbのようにaddControlメソッドを利用します。
addControl()メソッドの引数は数が多いのですが、順番に
c:\temp> ruby simple.rb
ちなみに、constructが実行されている状態では、ウインドウの実体は生成されていますが表示されていません。constructが呼ばれた後、表示されます。スクリプトでrequireしているvr/vrcontrolは、Windowsの標準コントロールと呼ばれる部品を利用するために必要です(コモンコントロールだとvr/vrcomctl)。詳しくはVisualuRuby計画(仮称)のwebを参照してください。
#! ruby -Ks
require 'vr/vruby' # vrubyのコア部分の利用(実はこの行は省略可)
require 'vr/vrcontrol' # Windows標準コントロール(ボタンなど)を利用
class MyForm < VRForm
def construct # このメソッドはウインドウ生成直後に呼ばれる
addControl(VRButton,"btn","ボタン",10,10,100,50) # ボタンを追加
end
end
VRLocalScreen.start(MyForm)
ボタンは表示しているだけでは意味がありません。ボタンが押されたことを検知しなくてはならないのです。次にイベントハンドリングを行ってみます。イベントハンドリングには、先ほどGUI部品のインスタンスに付けた名前と、イベントの名前を使います。 先ほどのsimple.rbのMyFormに、次のようなbtn_clickedというメソッドを追加してみましょう。(simple2.rb)
class MyForm < VRForm
... (略)
def btn_clicked
messageBox "CLICKED!" # CLICKED!と表示したメッセージボックスで知らせる
end
end
このbtn_clickedが「ボタンが押された」というイベントを受けるためのメソッドです。あるGUI部品がイベントを発生すると、GUI部品の「インスタンスに付ける名前」と、イベント名を"_"で連結した名前の親ウインドウのメソッドが呼ばれます。simple2.rbでは、ボタン部品がbtnと名付けられていて、ボタンが押されたときのイベント名がclickedなのでイベントハンドラはbtn_clickedというメソッドになります。 一度スクリプトを走らせてボタンを押してみてください。メッセージボックスが出て"CLICKED!"と表示されると思います。
部品自身でイベントを捕捉せず、親で受けるのが奇異に感じられるかもしれませんが、これは元々のWindowsのモデルがそうなっているためです。イベントハンドラをこのような文字列連結したメソッドで受けることにしたのは、VisualBasicを参考にしたからです。各GUI部品のイベントの一覧は、webのリファレンスなどを参考にしてください。vrubyのスクリプト内部にもRDの形式で埋め込んであります。2004/7月には雪見酒氏によるHTMLヘルプもできました。
このほか、イベントとしてはGUI部品以外が発生するイベントもあります。例えば、「マウスがウインドウの上を通過した」や、「ウインドウにフォーカスが当たった」などです。これらを捉えるためには、適切なモジュールをincludeして、「インスタンスに付ける名前」を"self"にします。例えば、「フォーカスが当たった」のを捉えるイベントハンドラは、vr/vrhandlerをrequireし、VRFocusSensitiveをinclude(またはextend)したオブジェクトで、self_gotfocus()となります。ちょっと古めですが、リファレンスのページに一覧もあります。
スクリプトの実行がイベントドリブンとなるので、少しわかりにくいかもしれませんが、
GUI部品のレイアウトなど、見た目のデザインに関しては、雪見酒氏作成のFormDesignerという便利なrubyスクリプトがあり、筆者も重宝しています。これは原稿執筆時点ではVisualuRuby計画(仮称)のページから入手できます。
ここで一つアプリケーションを作ってみます。元々はこの原稿の依頼を頂いた編集さんの希望を縮小(笑)したものなのです。簡単な仕様ですが、
結構GUIのアプリケーションのエッセンスが入っていると思います。
また、Windows独特の内容として、
dropmemo.rbの前半部分はデータを扱う部分です。実はかなり手抜きです。 URLメモの保持するデータはファイルに格納され、以下の形式のテキストが0つ以上連なったものになっていますので、テキストエディタなどで編集できます。
[
TITLE=メモのテキスト
URL=http://hoge.jp/
DATE=2003:08:06:02:49:01
]
表示に関しては、このファイルをStringクラスのscanメソッドで各メモ毎に分割し、リストビューに表示していきます。処理の流れだけを意識するとGUI生成のメソッドの中でデータファイルの解釈をやってしまいたくなりますが、バックエンドのデータ操作部分と、フロントエンドのGUIの部分はきっちり分けておきましょう。多少煩雑になりますが、デバッグやテストが容易になります。ということで、dropmemo.rbも、前半がデータ操作部分で、後半がGUI部分です。
前半のデータ操作部分は、ファイルの読み込みと、データの追加機能を実装しています。ファイルの読み込みは、ファイル全部を丸ごと読み込んでから正規表現でデータを抽出しています。
GUI部分では2つのクラスが定義されています。一つがダイアログ、もう一つがメモの一覧を表示するウインドウです。ダイアログの方はGUI部品を並べてイベントハンドラを書いているだけなので、特に問題がないかと思います。MyFormの方は、ボタンとは違った複雑な部品が幾つか入っていますので説明します。
このMyFormは3つのモジュールをincludeしています。最初のVROleDropTargetは、OLEドラッグ&ドロップを受けるために必要な機能を実装しています。constructメソッドの中でstart_oledroptarget()というメソッドを呼んでいますが、これがドロップターゲットとしての開始手続きです。ここではCF_URL(URLのドロップ)形式のドロップターゲットとなっています。MyFormクラスの最後の2つのメソッドは、OLEドラッグ&ドロップの状況に応じて呼び出されます。ドロップされたときにはself_oledrop()が呼び出されます。これはGUI部品以外が発生するイベントであるため、GUI部品名になるべき所が"self"になっています。
また、リストビューがダブルクリックされたときのイベントハンドラがlview_dblclickedです。ここでは、リストビューの選択されているメモのURLそれぞれを引数に、exec_urlを呼び出しています。exec_urlでは、まずDDE(DynamicDataExchange)という古い技術を使ってInternetExplorerにurlを開かせようとします。
カラムがクリックされたらイベントハンドラのlview_columnclickedが呼ばれます。ここでは、ファイルを読み直してメモをソートし、リストビューにセットし直しています。
実は、データを消去する部分は作っていません。練習がてら一度作ってみてください。筆者の手抜き?いえいえ、これは課題ということで何とぞ。
dropmemo.rbをExerbで実行形式に変換するため、まずはレシピファイルを作成しましょう。
c:\temp> ruby -r exerb/mkrbc dropmemo.rb
実行するのでウインドウが開いてきますが、いきなり終わって大丈夫です。requireされる物はスクリプトの最初にrequireしてしまってますので。終了すると無事にdropmemo.rbcが出来たと思います。今回は依存するファイルが多いので、先ほどよりは大きなファイルが出来たと思います。
さて、次にExerbで実行形式を作成します。Exerbは「コア」という形で複数のインタプリタを持っています。その中のGUI用のコアを使って実行形式を作成すると、お望みの品のできあがりです。コアの指定には -c オプションを利用します。
c:\temp> exerb.bat -c gui dropmemo.rbc
InternetExplorerからURLをドロップすると、ダイアログが出てきてタイトルの入力を促します。適当に入れてENTERキーを押してください(図2)。これでリストビューに登録されたと思います。InternetExplorerの表示を別のページに変えてから、リストビューの項目をダブルクリックすると、InternetExplorerが登録したサイトにジャンプします。
dropmemo.rbにはExerb特有の挙動に対する処置が入っています。それは、スクリプトの中から自分自身のファイル名を知るための変数、$0や__FILE__が、常にファイル名だけしか返さなくなることです。スクリプトを実行形式に変換してしまったので、これらの変数がおかしくなることはある意味当然ではありますが、Exerb側でファイル名だけはセットしてくれるようです。$0や__FILE__はスクリプトのあるパスを得るために使うことがありますが、Exerbによる変換の後はディレクトリの情報が無いので役に立たなくなります。
そこでdropmemo.rbでは、WindowsのAPIを利用して自分自身の実行形式(EXEファイル)のパスを得るメソッドWin32API.get_exepath()を作成しています。
Windowsでrubyを使う時の雰囲気はつかんで頂けたでしょうか。Exerbを使うと、配布対象マシン(Windows)へのrubyのインストールなどの作業が不要なまま、rubyで書いたスクリプトを走らせることが出来ます。VisualuRuby計画(仮称)を使うと、その特徴を保ったままGUIを利用することが出来ます。
これでもう、めんどくさい「雑用」の数々も、rubyのパワーでさっくり終了、になりそうだと思いませんか? ただしこの記事の前半で書いたようにWindowsならではの落とし穴がありますので、うまく避けて行きましょう。