Coding4Fun: パネル ゲーム

パネル ゲーム

Michal Altair Valášek
Altair Communications

March 3, 2006
日本語版最終更新日 2006 年 5 月 10 日

最近、私は、あるテレビ番組の影響によりチェコ共和国内で流行しているパネル ゲームで遊ぶためのアプリケーションを短時間で記述するという難題に取り組む機会がありました。幸運にも、私は Visual Basic Express をインストールしたノート パソコンを持っていました。今回は、Visual Basic Express を使用するとソフトウェアを簡単に記述できること、そして、正常に動作する Windows アプリケーションをとても簡単に作成できる方法を紹介します。また、Microsoft .NET Framework 2.0 の Windows フォームで利用できる次の新しい技術を使用して、一貫性がありユーザーにとって使いやすいインターフェイスを作成する方法についても紹介します。サンプル プログラム ファイル内では実際のコメント行は英語で書かれていますが、この記事内では説明目的で日本語で書かれています。

  • Windows フォーム デザイナの GUI デザインの基礎。

  • アプリケーションの構成設定を格納する。

  • 境界線がない全画面表示のウィンドウを作成し、そこでコントロールを動的に生成する。

ゲームのルール

厳密には、パネル ゲームは、コンピュータ ゲームではありません。どちらかというと、パズルに近いゲームです。このゲームで遊ぶ際にはコンピュータが役立ちます。コンピュータを使用すると、ビデオ プロジェクタを使用できるので、紙で作ったカードを使用するよりも、簡単に画像を壁に映し出すことができます。特に、私たちのようなコンピュータのヘビー ユーザーにとってはなおさらのことです。

パネル ゲームで遊ぶには、2 組のチーム (1 チーム 1 人以上) とゲーム マスターが必要です。ゲーム マスターが画像を選択します。画像は番号付きのパネルで覆われた状態で表示されます。各チームのプレーヤーが順にパネルを 1 枚ずつはがして行きます。パネルをはがすと、下に隠れている画像が部分的に表示され、プレーヤーは、その画像が何であるかを当てます。プレーヤーの答えが正しい場合、そのプレーヤーのチームがゲームの勝者となります。プレーヤーの答えが正しくない場合は、相手チームのプレーヤーの順番になります。

このアプリケーションでは、ゲーム マスターが画像を選択して、パネルの番号や色などのパラメータを設定してから、パネルで覆われた状態の画像を表示させるようにしたいと考えていました。また、パネルをクリックすると、パネルが消えて、その下に隠れている画像の一部が表示されるようにし、 Enter キーを押すと画像全体が表示され、Esc キーを押すと設定画面に戻るようにしたいと考えていました。

最適なユーザー エクスペリエンス

見た目に凝ったアプリケーションは、 色使いやフォームの外観がすばらしく、画像が多用されています。このようなアプリケーションは見栄えはよいのですが、 残念ながら多くの場合は役に立ちません。ロール プレーイング ゲームのアプリケーションである場合を除き、画面上に表示されているものがボタンであるのか、またはデザイナが作り上げたものの一部であるのかについてユーザーを悩ませるのは得策ではありません。

Windows オペレーティング システムが普及した主な理由の 1 つとして、すべてのアプリケーションで要素が同じように表示されることが挙げられます。ユーザーは、表示されている要素がメニューやボタンであること、小さな正方形がチェック ボックスであることを瞬時に理解することができます。開発者が独自に開発するアプリケーションでも、わかりきったことをやり直すのではなく、同様に共通のルールに従うことをお勧めします。

また、アプリケーションは、アプリケーションの作成に使用したコンピュータだけでなく、異なるシステム構成のコンピュータでも正常に動作する必要があります。たとえば、私のように、タスク バーを画面下部ではなく画面上部に配置しているユーザーもいます。また、高解像度 (1600 x 1200 など) を好むユーザーもいれば、文字が読みやすい低解像度 (1024 x 768 など) を好むユーザーもいます。そのため、Windows フォームは、ユーザーが快適だと感じる表示環境に合わせてサイズを変更できるようにデザインすることをお勧めします。ユーザーが Windows フォームのサイズを変更したり、移動したりしたときには、アプリケーションは、変更内容を記憶して、次にユーザーがアプリケーションを実行したときにフォームを同じ位置に配置するようにする必要があります。また、コンピュータには、複数のユーザー アカウントが登録されていることがあるため、変更内容と設定はユーザーごとに格納する必要があることも覚えておく必要があります。

これは、最適なユーザー エクスペリエンスを実現する適切なユーザー インターフェイスをデザインするための技法です。不要な混乱を招くことなく、コンピュータを使い慣れていないユーザーも、アプリケーションを使用できるようにする必要があります。

このようなアプリケーションを実現するのは、難しいと思うかもしれませんが、 それほど難しくありません。Microsoft .NET Framework 2.0 には、このような問題を簡単に解決するための機能が多数用意されています。開発者に必要なのは、これらの機能を理解することだけです。

ユーザー インターフェイスを作成する

Visual Basic Express を起動して、新しい Windows アプリケーション プロジェクトを作成しましょう (または、この記事の先頭にあるリンクからダウンロードできる完成したプロジェクトをダウンロードして開いてください)。プロジェクトを作成すると、空のフォームが表示され、そこにコントロールを配置できます。

完成したアプリケーションの設定フォームは、次のようになります。

フォームにコントロールを配置する

まず、グループ ボックス、ボタン、およびテキスト ボックスを配置します。コントロールを別のコントロールの近く、またはフォームの境界線の近くに配置すると、コントロールの 4 辺から青い線が表示されます。この線は、他のコントロールまたは境界線を基準にして、コントロールを同じ間隔で配置するうえで役立ちます。この Visual Studio 2005 の新機能により、コントロールの配置作業がとても簡単になります。

フォームをデザインするときには、[レイアウト] ツール バーを表示させることができます。任意のツール バーを右クリックし、コンテキスト メニューを表示して [レイアウト] をクリックすると、 新しいツール バーが表示されます。このツール バーには、他のコントロールとの関係に基づいてコントロールを配置したり、類似コントロールを同じサイズに揃えたり、中央揃えにしたりするなどの操作を行うボタンが用意されています。これらのボタンを実際に使用すると、これらのボタンの機能を理解することができます。

この時点では、フォームには、次のような一般的なコントロールが配置されています。

  • 背景画像の設定と、その上を覆うパネル (ラベル) の設定をグループ化するために使用する 2 つのグループボックス コントロール。

  • 画像ファイルのパスを設定するため使用するテキスト ボックス コントロール。

  • ファイルを参照するのに使用するボタン コントロール。

行と列の番号を入力するために、テキスト ボックスを使用することは可能ですが、最適な方法ではありません。入力された値が、2 〜 20 などの特定の範囲内の整数であることを確認する必要があります。そのため、ここでは、テキスト ボックスではなく NumericUpDown コントロールを使用することが適切です。このコントロールのプロパティ ウィンドウでは、最小値と最大値を指定できます。

パネルの背景と前面に表示される番号の色の設定には、上にあるテキスト ボックスと同じ BorderStyle プロパティと Size プロパティの値を指定した標準のラベル コントロールを 2 つ使用することができます。ここで気を付ける必要があるのは、BackColor プロパティです。また、これらのコントロールの近くには、ユーザーが色を選択するためのボタンを配置します。

同様の方法を使用して、パネルに表示される番号に使用するフォントを選択できるようにすることもできます。ただし、フォントの指定は複雑です。たとえば、フォント名、フォント サイズ、およびスタイル (太字や斜体など) に関する情報を格納する必要があります。フォントの指定については後で説明します。ここでは、コントロールを配置して外観に関する値を設定します。

では、アプリケーションを実行してみましょう。アプリケーションを実行すると、ウィンドウが表示されます。ボタンをクリックしたり、テキスト ボックスに文字を入力したりすることはできますが、 何の処理も行われません。とりあえず操作することはできます。

フォームのサイズを変更する

今度は、ウィンドウのサイズを変更してみましょう。ウィンドウのサイズは変更できますが、コントロールのサイズまでは変更されません。フォームのサイズを大きくしても、コントロールはフォームの上部左端に配置されたままです。また、フォームのサイズを小さくすると、コントロールは隠れて見えなくなってしまいます。ここでは、フォームに合わせて、コントロールのサイズも変更されるようにしたいと思います。

アプリケーションを終了し、フォーム上に配置されている任意のコントロールのプロパティを表示します。Anchor プロパティに注目してください。このプロパティでは、Top、Bottom、Left、および Right という 4 つの値を自由に組み合わせて使用することができます。

これらの値は、コンテナ コントロール (この場合はフォーム) のサイズが変更された場合に、コントロールがどのように動作すべきかを指定します。既定では、Anchor プロパティは [Top, Left] に設定されています。つまり、コントロールは、Window フォームの上部左端からの距離を維持します。たとえば、[開始] ボタンや [閉じる] ボタンは、常にフォームの下部左端に配置しておくのが適切でしょう。[Top, Left, Right] など、2 つ以上のアンカーを選択すると、おもしろい動作が見られます。フォームのサイズを変更すると、コントロールは Anchor プロパティで指定された位置に固定され、サイズが変更されます。すべてのコントロールの Anchor プロパティを変更して、フォームのサイズを変更してみてください。ボタンなどのコントロールは、コンテナ コントロールのサイズ変更に比例してサイズが変化しますが、グループ ボックスなどのコントロールは、コントロールのサイズの比率を維持した状態でサイズが変更されます。

Windows フォームとコントロールには、このようなサイズ変更の機能が組み込まれていますが、一般に、ユーザーが変更できるフォームのサイズを制限することをお勧めします。たとえば、フォームのサイズが小さくなりすぎると、表示されなくなるコントロールがあります。このような現象を回避するために、Windows フォームには MinimumSize プロパティと MaximumSize プロパティが用意されています。フォーム デザイナ ウィンドウで、フォームにすべてのコントロールが完全に表示され、読んだり、使用したりできるという条件を満たす最小のサイズまで、コントロールのサイズを小さくします。それから、プロパティ ウィンドウで、フォームの Size プロパティの値をコピーして、MinimumSize プロパティのフィールドに貼り付けます。これで、アプリケーションを実行してウィンドウのサイズを変更しても、コントロールは適切なサイズに変更され、ウィンドウが小さくなりすぎることはありません。

コモン ダイアログを使用する

今度は、コードを記述して、アプリケーションで実際に処理を行いましょう。まず、いくつかのボタンが機能するようにしましょう。[参照] ボタンと [変更] ボタンでは、ファイルを参照したり、色やフォントを選択するために Windows のコモン ダイアログ ボックスを使用します。これには 2 つの理由があります。1 つ目の理由は、ユーザーは、コモン ダイアログ ボックスが使用されることを期待しているからです。ほぼすべての Windows プログラムでは、この方法が使用されています。そのため、別のダイアログ ボックスが表示されると、ユーザーは違和感を感じます。2 つ目の理由は、この方法が最も簡単な方法であるからです。これ以外の方法を使用すると、実装が困難になります。これは、怠け者になることが、事態を好転させるという一例です。

では、ファイルの選択処理から始めましょう。[ツール ボックス] ペインの [ダイアログ] セクションにある OpenFileDialog コントロールを、フォーム上に配置します。このコントロールは、フォーム上には表示されず、編集ペインの下部にある灰色の領域に表示されます。この現象は、このダイアログ コントロール自体が、フォーム上での視覚的な実装を持っていないために発生します。このコントロールは、ユーザーに対して直接表示されるボタンやテキスト ボックスとは異なります。

このコントロールのプロパティ ウィンドウには、ダイアログ ボックスのタイトルやファイルが満たす必要のある条件 (例、CheckFileExists) など、さまざまなものの設定が含まれています。ここでは、Filter という名前のプロパティを使用します。このプロパティの値では、[ファイルの種類] ボックスに表示する文字列を指定します。

このパネル ゲーム アプリケーションでは、このプロパティの値は "画像|*.jpg;*.bmp;*.gif;*.png;*.tif;*.tiff|すべてのファイル|*.*" になります。既定では、ユーザーが特定の種類の画像ファイルを選択できるようにします。また、最終的な手段として、ユーザーが、拡張子に関係なく、すべてのファイルを表示できるようにします。ファイルの種類は、縦線で区切っています。

今度は、現在選択されているファイルをポイントした状態の [ファイルを開く] ダイアログ ボックスを表示して、ユーザーが [開く] ボタンをクリックすると、現在選択されているファイルの名前がテキスト ボックスに表示されるようにする数行のコードを記述します。[参照] ボタンをダブルクリックして、コードを編集するペインを表示し、次のコードを Click イベントのハンドラとして記述します。

  
    Private Sub ButtonBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonBrowse.Click
    ' [ファイルを開く] ダイアログ ボックスを表示します。
    Me.OpenFileDialogImage.FileName = Me.Text boxImageFilePath.Text
    If Me.OpenFileDialogImage.ShowDialog(Me) <> Windows.Forms.DialogResult.OK Then Return
    Me.Text boxImageFilePath.Text = Me.OpenFileDialogImage.FileName
End Sub

[色の設定] コモン ダイアログ ボックスと色の選択の方法も、非常によく似ています。[フォント] コモン ダイアログ ボックスのコードは、ファイルや色の選択とは多少異なるので、後で説明します。

オートコンプリートの不思議な力

Windows のすばらしい機能の 1 つに、テキスト ボックス エントリのオートコンプリートがあります。これは、ユーザーが、エントリ (ファイルのパスなど) の入力を開始すると、以前に入力した値に基づいて入力候補を表示する機能です。パネル ゲーム アプリケーションでオートコンプリートを有効にするには、設定フォームの Image file ボックスの AutoCompleteMode プロパティを SuggestAppend に設定し、AutoCompleteSource プロパティを FileSystem に設定する必要があります。

キーボードについてもお忘れなく

ユーザーがマウスではなくキーボードを使用して、アプリケーションを制御できるようにすることも忘れないでください。アプリケーションが適切にデザインされている場合、上級ユーザーは、キーボードを使用した方が迅速かつ簡単にアプリケーションを操作できると感じています。

キーボードによる操作を迅速かつ簡単に行えるようにするには、次の 3 つのことが役立ちます。

  • 既定のボタン。

  • タブ オーダー。

  • キーボード アクセラレータ。

まず、既定のボタンについて見てみましょう。多くのダイアログ ボックスには、Enter キーと Esc キーなどの機能に相当する [OK] ボタンと [キャンセル] ボタンが配置されています。この機能は、フォームの AcceptButton プロパティや CancelButton プロパティを使用して有効にすることができます。このアプリケーションでは、これらのプロパティには [開始] ボタンと [閉じる] ボタンを設定します。Enter キーまたは Esc キーを押すと、アプリケーションは、これらのキーに対応するボタンが押された場合と同様に動作します。Start ボタンの機能は後から追加しますが、フォームを閉じるという [閉じる] ボタンの機能は、次のコードを使用して簡単に追加することができます。

  
    Private Sub ButtonClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonClose.Click
        ' ウィンドウを閉じて、アプリケーションを終了します。
        Me.Close()
End Sub

次は、タブ オーダーについて見てみましょう。標準的なアプリケーションでは、Tab キーを押すと、タブ オーダーが設定されている順でフォーカスが次のコントロールに移動します。コントロールが選択される順序は、各コントロールの TabIndex プロパティで指定されています。最適なユーザー エクスペリエンスを提供するには、タブ オーダーは、ユーザーがデータを入力する順序と同じに設定する必要があります (通常、これは、フォーム上でコントロールが配置されている順と同じになります)。

既定では、タブ オーダーは、フォームにコントロールを配置するときに設定されます。つまり、1 つ目に配置したコントロールのタブ オーダーは 0、2 つ目は 1 のようになります。多くの場合、このタブ オーダーは適切ではありません。もちろん、TabIndex プロパティの値を手動で設定することはできますが、Visual Basic には優れた機能が用意されています。[表示] メニューの [タブ オーダー] をクリックすると、 すべてのコントロールの左端に、番号付きの小さな正方形が表示されます。

ハリッハするよ拡大画像が表示され?す

(画像をクリックすると拡大表示されます。)

この状態で、タブ オーダーを設定する順にコントロールをクリックします。この操作を行ったら、もう一度、[表示] メニューの [タブ オーダー] をクリックして、番号を非表示にします。

TabIndex プロパティの値は、ラベル コントロールなど、直接選択できないコントロールにも割り当てる必要があります。それは、 キーボード アクセラレータを設定する必要があるからです。

実行中のフォームでは、一部の文字に下線が引かれていることがあります (システム構成によっては、Alt キーを押さないと下線が表示されない場合もあります)。Alt キーを押しながら下線が引かれた文字のキーを押すと、適切なコントロールにフォーカスを移動させることができます。また、ラベルなど、コントロール自体を選択できない場合、フォーカスは、タブ オーダーで設定された順序に従って次のコントロールに移動します。つまり、このアプリケーションでは、Alt キーを押しながら I キーを押すと、ファイル名を入力するテキスト ボックスが選択されます。

下線を引く文字は、その文字の前にアンパサンドを入力することによって指定できます。ラベル コントロールに「&Image file」という名前を付けると、文字 I に下線が引かれ、文字 I がキーボード アクセラレータとして使用されるようになります。多くの場合、キーボード アクセラレータは、ラベルの 1 文字目になります。ただし、1 文字目が既に別のラベルでキーボード アクセラレータとして割り当てられている場合は、次の文字をキーボード アクセラレータとして使用します。つまり、F は既に "&Foreground" で使用されているので、"F&ont" のように 2 つ目の文字をキーボード アクセラレータとして設定しています。

アプリケーション設定を管理する

パーソナル コンピュータが誕生したときから、構成設定を格納する必要がありました。構成設定は、 テキスト ファイルとして保存したり、レジストリに保存したりするなど、さまざまな方法で保存することができます。Microsoft .NET では、構成設定を XML ファイルに格納します。xml ファイルに格納すると、値の読み取りや変換は自動的に行われるため、これらの処理について心配する必要がありません。

すべてのユーザーについて格納する必要があるアプリケーションの設定を、 "アプリケーション スコープの設定" と呼びます。通常、この設定は、インストール時または初期設定時に管理者によって構成され、一般ユーザーが変更してはなりません。この設定は、アプリケーションの EXE ファイルと同じディレクトリにあり、EXE ファイルと同じファイル名で拡張子が .config のファイルに格納されます。ただし、パネル ゲーム アプリケーションには、このような構成設定はありません。

このアプリケーションの構成設定は、すべて "ユーザーごとの設定" になります。つまり、アプリケーションの設定はユーザーが読み取りおよび書き込みを行える場所に格納する必要があります。また、ユーザーが必ずしも管理者特権を持っているとは限らないことについても考慮する必要があります。ユーザーごとのアプリケーションの設定を格納するのに最適な場所はユーザー プロファイルです。通常、アプリケーションの設定は、C:\Documents and Settings\<ユーザー名>\Local Settings\Application Data\<ベンダ名>\<製品名> に格納するのが最適です。実際、.NET では、アプリケーションの設定ファイルの作成と管理が十分に考慮されているので、 アプリケーションの作成者が行う必要があるのは、アプリケーションに関する情報を提供することだけです。

ソリューション エクスプローラ ウィンドウに移動し、[My Project] をダブルクリックします。新しいウィンドウが表示されたら、 [アプリケーション] タブで [アセンブリ情報] ボタンをクリックし、作成者とアプリケーションに関する情報を入力します。

ここに入力した値は、構成ファイルや他のものの場所を指定する際に使用されます。

[My Project] フォルダを選択した状態で、[設定] タブをクリックします。ここでは、アプリケーションの構成プロパティを定義できます。設定の名前、型、スコープ、および既定値を指定します。たとえば、それぞれのボックスに、ImageFilePath、String、User、および C:\WINDOWS\Web\Wallpaper\Bliss.bmp という値を指定します。アプリケーション設定では、比較的複雑な型を指定することができます。たとえば、色 (System.Drawing.Color) やフォント (System.Drawing.Font) を指定することができます。

ハリッハするよ拡大画像が表示され?す

(画像をクリックすると拡大表示されます。)

Visual Basic では、これらの値の読み込みおよび書き込みの処理に対応するプロキシ クラスが自動的に作成されるため、アプリケーションの作成者は、適切な型を指定して、これらの値を直接使用することができます。たとえば、My.Settings.OverlayFont のように値を使用することができます。

ご覧のとおり、これも怠け者になることが、事態を好転させる一例です。プログラマとはすばらしい職業です。構成ファイルについて悩むことなくアプリケーションの設定を読み取ったり書き込んだりできるだけでなく、ファイルも適切に配置されます。ユーザーは、構成ファイルを自分のプロファイルに格納することができるので、構成ファイルに対して書き込みの特権を持たなくても、アプリケーションがクラッシュすることはありません。Windows XP には、ファイルと設定の転送ウィザードというおまけの機能が用意されています。

アプリケーションの設定を使用する

今度は、アプリケーションの設定を使用して (つまり、読み取りおよび書き込みを行って) みましょう。基本的に、アプリケーションの設定の使用には 2 とおりの方法があります。1 つ目の方法としては、自動生成された My.Settings クラスを使用して、プログラムからアプリケーションの設定を使用することができます (My.Settings クラスについては、既に説明しました)。その後、ボタンでフォント名やフォント サイズなどを選択して、それを反映するコードを記述します。

上の例と同様に、フォームに FontDialog コントロールを配置し、フォントを設定するボタンの Click イベント ハンドラに次のコードを記述します。

  
    Private Sub ButtonFont_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonFont.Click
    ' [フォント] ダイアログ ボックスを表示します。
    Me.FontDialogChange.Font = My.Settings.OverlayFont
    If Me.FontDialogChange.ShowDialog(Me) <> Windows.Forms.DialogResult.OK Then Return
    My.Settings.OverlayFont = Me.FontDialogChange.Font
    Me.LabelFont.Text = String.Format("{0}, {1} pt", My.Settings.OverlayFont.Name, My.Settings.OverlayFont.SizeInPoints)
End Sub

2 つ目の方法としては、プロパティ バインドを使用して、アプリケーションの設定を宣言して使用することができます。Image file テキスト ボックスを使用して、この例について説明しましょう。テキスト ボックスをクリックして、プロパティを表示します。プロパティ ウィンドウで (ApplicationSettings) という項目を探して、その隣にある + をクリックします。次に、(PropertyBinding) 行にある [・・・] ボタンをクリックします。このボタンをクリックすると、次のダイアログ ボックスが表示されます。

ご覧のとおり、このダイアログ ボックスでは、いくつかのプロパティをアプリケーション設定にバインドできます。実際、このダイアログ ボックスを使用すると、[(新規)] リンクをクリックして、適切なデータ型を指定して新しいアプリケーションの設定を簡単に作成することができます。

Text プロパティを ImageFilePath アプリケーション設定にバインドします。同様に、行や列の数など、他のすべてのコントロールをアプリケーション設定にバインドします。色を指定するラベルについては、BackColor プロパティをアプリケーション設定にバインドします。

ただし、すべてのコントロールを、このようにバインドできるわけではありません。たとえば、ラベルのテキストを表示するために選択したフォントを使用するわけではないので、Font ボックス コントロールではバインドは使用しません。

フォームのサイズと位置を記憶する

既に説明したように、正常に動作するアプリケーションは、ウィンドウのサイズと配置を覚えておく必要があります。ここでも、アプリケーションの設定を使用できます。

まず、FormOptionsSize 構成値 (型 System.Drawing.Size) と FormOptionsLocation (型 System.Drawing.Point) を定義します。

次に示すフォームの FormClosed イベント ハンドラのコードでは、ウィンドウを閉じたときのウィンドウの位置とサイズを保存します。

  
    Private Sub FormOptions_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
    ' フォームが最小化または最大化されていない場合は、フォームのサイズと位置を保存します。
    If Not Me.WindowState = FormWindowState.Normal Then Return
    My.Settings.FormOptionsLocation = Me.Location
    My.Settings.FormOptionsSize = Me.Size
End Sub

ウィンドウが最小化または最大化された状態のときには、何も保存されないようにするための条件を追加しました。これは、ウィンドウが最小化または最大化されている場合、Location プロパティと Size プロパティには処理しづらい値が設定されているからです。このコードでは、WindowState プロパティの値を保存することもできますが、一般的に、アプリケーションを最小化した状態で起動するのは望ましいことではありません (アプリケーションが起動されていないとユーザーが勘違いする可能性があります)。

フォームが開かれるときには保存した値が使用されるようにする必要があります。これは、Load イベント ハンドラで行うことができます。ラベルにも指定のフォントが表示されます。選択したファイルの値は、データ バインドにより自動的に読み込まれるため、コードで読み込む必要はありません。

  
    Private Sub FormOptions_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ' フォームのサイズと位置を設定します。
    Me.Location = My.Settings.FormOptionsLocation
    Me.ClientSize = My.Settings.FormOptionsSize
    ' テキスト ボックスにフォント名とフォント サイズを表示します。
    Me.LabelFont.Text = String.Format("{0}, {1} pt", My.Settings.OverlayFont.Name, My.Settings.OverlayFont.SizeInPoints)
End Sub

ゲームで遊ぶ

これまでの手順により、サイズが適切に変更され、構成が維持されるアプリケーションが作成できました。これは優れたアプリケーションですが、まだ十分ではありません。アプリケーションは、その目的を果たす必要があります。つまり、ここでは、ゲームで遊べるようにする必要があります。では、「FormGame」という名前の新しいフォームを追加してみましょう。この時点では、このフォームには何も追加する必要はありません。

メイン ウィンドウの [スタート] ボタンをダブルクリックし、新しく作成した FormGame を表示するために次の数行のコードを記述します。

  
    Private Sub ButtonStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonStart.Click
    ' GameForm を表示します。
    Dim GameForm As New FormGame
    GameForm.ShowDialog(Me)
End Sub

画像を表示する

実際のゲームは、この新しいフォームで作成します。フォームは全画面表示で、境界線なしで表示させる必要があるため、画面全体には画像のみを表示します。この状態を実現するには、FormGame フォームで次のプロパティを設定します。

  • FormBorderStyle = None

  • ShowInTaskbar = False

  • WindowState = Maximized

選択した画像を表示するには、フォームに PictureBox コントロールを配置し、プロパティ ウィンドウで Dock プロパティの値を Fill に設定します。このプロパティは、Anchor プロパティと同様の効果があります。このプロパティを設定すると、コントロールがフォームの 1 辺に固定されます。また、このプロパティに Fill を設定すると、フォーム全体に画像が表示されます。このアプリケーションでは、フォーム全体に画像を表示する必要があるため Fill を設定します。また、PictureBox コントロールをフォームと同じサイズにして、Anchor プロパティに 4 辺を設定する方法があります。ただし、Dock プロパティを使用した方が操作は簡単です。

画像を全画面表示で表示する必要があるため、SizeMode プロパティを Zoom に設定します。この設定により、画像は比率を維持したまま全画面表示で表示されるようになります。

フォームの Load イベント ハンドラに次のコードを配置します。

  
    Private Sub FormGame_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ' 画像を読み込みます。
    Try
        Me.PictureBoxImage.Image = Image.FromFile(My.Settings.ImageFilePath)
    Catch ex As Exception
        MsgBox("画像の読み込み中にエラーが発生しました: " & ex.Message, MsgBoxStyle.Exclamation)
        Me.Close()
    End Try
End Sub

ご覧のとおり、My.Settings.ImageFilePath には事前に作成したバインドを使用してユーザーが選択したファイル名が自動的に設定されるので、この値を直接使用することができます。

ユーザーが入力したデータを操作する際は、予想される最悪なエラーを考慮する必要があります。たとえば、指定されたファイルが破損していたり、画像ではなかったり、存在しないことがあります。上のコードでは、ファイルを画像として読み取れない場合にスローされる可能性がある例外をキャッチします。

この状態でアプリケーションを実行すると、選択した画像が全画面表示で表示されます。メッセージ ボックスのウィンドウは、Alt キーを押しながら F4 キーを押して閉じることができます。

コントロールを動的に生成する

ラベル コントロールを使用して、画像を隠します。デザインの段階では、必要なラベル コントロールの数がわからないため、ラベル コントロールは実行時にプログラムで生成する必要があります。

コードの観点から見ると、コントロールは他のクラスと何ら変わりありません。コントロールについても、インスタンスを作成したり、プロパティを設定したりすることができます。次のコードを使用して Load イベント ハンドラを拡張することができます。

  
    Private Sub FormGame_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ' パネルとして使用する基本的なラベルの幅と高さを生成します。
    Dim H As Int32 = Me.PictureBoxImage.Height \ CInt(My.Settings.Rows)
    Dim W As Int32 = Me.PictureBoxImage.Width \ CInt(My.Settings.Columns)
    ' パネルとして使用するラベルを作成します。
    For Y As Int32 = 1 To CInt(My.Settings.Rows)
        For X As Int32 = 1 To CInt(My.Settings.Columns)
            ' パネルとして使用するラベルを作成して配置します。
            Dim L As New System.Windows.Forms.Label
            Me.PictureBoxImage.Controls.Add(L)
            L.Left = (X - 1) * W
            L.Top = (Y - 1) * H
            L.Width = CInt(IIf(X = My.Settings.Columns, Me.PictureBoxImage.Width - L.Left, W))
            L.Height = CInt(IIf(Y = My.Settings.Rows, Me.PictureBoxImage.Height - L.Top, H))
            ' パネルとして使用するラベルの表示を設定します。
            L.Text = CStr((Y - 1) * My.Settings.Columns + X)
            L.BackColor = My.Settings.OverlayBackgroundColor
            L.ForeColor = My.Settings.OverlayForegroundColor
            L.Font = My.Settings.OverlayFont
            L.TextAlign = ContentAlignment.MiddleCenter
            L.BorderStyle = BorderStyle.FixedSingle
        Next
    Next
    ' 画像を読み込みます。
    Try
        Me.PictureBoxImage.Image = Image.FromFile(My.Settings.ImageFilePath)
    Catch ex As Exception
        MsgBox("画像の読み込み中にエラーが発生しました: " & ex.Message, MsgBoxStyle.Exclamation)
        Me.Close()
    End Try
End Sub

その他、対応する必要があるのは、画面下部と画面右側のラベルの幅と高さのみです。コントロールの Size プロパティは整数値で指定する必要がありますが、画面の解像度はパネルの数では割り切れない可能性があります。画面下部にあるパネルと画面右側にあるパネルのサイズは、他の領域を隠しているパネルのサイズと異なります。すべてのパネルのサイズを均一にすると、画面下部と画面右側の端から、画像が数ピクセル分見えてしまいます。

アプリケーションを実行すると、画像は表示されず番号付きのパネルが表示されます。

パネルに機能を持たせる

クリックされたパネルは、非表示にする必要があります。この動作を実現するには、Click イベント ハンドラで次のコードを使用します。

  
    Private Sub ClickHandler(ByVal sender As Object, ByVal e As EventArgs)
    ' ラベルを透明にします (境界線のみを残します)。
    Dim L As System.Windows.Forms.Label = DirectCast(sender, System.Windows.Forms.Label)
    L.BackColor = Color.Transparent
    L.Text = ""
End Sub

また、マウス ポインタでポイントされたときにも、パネルはポイントされていることを視覚的に示す必要があります。視覚的な変化として適切なのは、パネルの前面と背面の色を切り替える方法です。これには、次の 2 つのメソッドを使用します。

  
    Private Sub MouseEnterHandler(ByVal sender As Object, ByVal e As EventArgs)
    ' ラベルが透明になっていない場合は、ポイントされたときに色を反転させます。
    Dim L As System.Windows.Forms.Label = DirectCast(sender, System.Windows.Forms.Label)
        If L.BackColor = Color.Transparent Then Return
    L.BackColor = My.Settings.OverlayForegroundColor
    L.ForeColor = My.Settings.OverlayBackgroundColor
End Sub
Private Sub MouseLeaveHandler(ByVal sender As Object, ByVal e As EventArgs)
    ' ラベルが透明になっていない場合、マウス ポインタが離れたときに色を元に戻します。
    Dim L As System.Windows.Forms.Label = DirectCast(sender, System.Windows.Forms.Label)
    If L.BackColor = Color.Transparent Then Return
    L.BackColor = My.Settings.OverlayBackgroundColor
    L.ForeColor = My.Settings.OverlayForegroundColor
End Sub

今度は、上のコードにあるメソッドが適切なタイミングで実行されるように、これらのメソッドを関連付けます。コントロールの生成時に、AddHandler コマンドを使用することによって、この目的を達成することができます。内部ループ (コード行 L.BorderStyle = BorderStyle.FixedSingle の直後) に次のコードを記述して、FormGame_Load メソッドを変更します。

  
    ' イベント ハンドラをアタッチします。
AddHandler L.Click, AddressOf ClickHandler
AddHandler L.MouseEnter, AddressOf MouseEnterHandler
AddHandler L.MouseLeave, AddressOf MouseLeaveHandler

これらのメソッドにより、すべてのラベル コントロールのイベントが処理されます。ソース パラメータは、どのコントロールによってイベントが発生したかを示すものです。

アプリケーションの完成まで、あと少しです。この状態でアプリケーションを実行すると、パネルをクリックしたときにパネルが非表示になります。これは、このアプリケーションで必要な動作です。

キー操作をキャッチする

既に説明したように、Enter キーを押すと画像が全画面表示され、Esc キーを押したらゲームが終了するようにしたいと考えています。この動作は、どのように実現できるのでしょうか。この動作を実現するには、フォームの KeyDown イベントを使用します。このイベントのメソッドに、次のコードを記述します。

  
    Private Sub FormGame_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
    Select Case e.KeyData
        Case Keys.Escape
            ' ウィンドウを閉じます。
            Me.Close()
        Case Keys.Enter
            ' 画像全体を表示させます。
            For Each C As Control In Me.PictureBoxImage.Controls
                C.Hide()
            Next
        End Select
End Sub

各パネルを非表示にするコードでは、ラベル コントロールは完全には非表示にせず、コントロールのコンテンツを透明にし、境界線を残すようにしました。上の画像全体を表示するコードでは、ラベル コントロールを非表示にして、黒いグリッド線も表示せずに、きれいな状態で画像を表示します。

まとめ

この記事に沿ってアプリケーションを作成することによって、複雑なアプリケーションを開発する際に役立つ手法についてご理解いただけたら幸いです。

この記事では、まず最初に、適切なユーザー インターフェイスを提供することの重要性について説明しました。Microsoft .NET Framework 2.0 を使用すると、このことは簡単に実現できます。次に、アプリケーション設定のフレームワークがどのように機能するかを確認し、構成設定を簡単に管理する方法についても説明しました。また、アプリケーション設定をコントロール プロパティにバインドして、コードから使用できることについても説明しました。最後に、実行時にコントロールを動的に生成し、コントロールのプロパティを設定し、コントロールのイベントを処理する方法について説明しました。そして、友達と楽しめるゲームが完成しました。ぜひ、楽しいひとときをお過ごしください。

Michal Altair Valášek は、マイクロソフトが認定する ASP.NET の Most Valuable Professional ですが、何でも屋でもあります。本業は、Web 開発者ですが、興味深いテクノロジを試したり、フリーの映画プロデューサーとしても活動しています。また、ASP.NET テクノロジに特化したチェコ語サイトを運営しながら、Altair Communications 社を経営しています。彼は、チェコ共和国のプラハで同棲中で、チェコスロバキアン ウルフ ドックを 1 匹を飼っています。電子メールは、michal.valasek@altairis.cz まで (英語で) お送りください。

top of page Top of Page