解説

実例で学ぶWindowsプログラミング

第4回 操作性を向上させるファンクション・キーへの対応

― ユーザビリティを高めるファンクション・バーの実装(後編) ―

デジタルアドバンテージ 一色 政彦
2005/03/30
Page1 Page2 Page3 Page4

3.ファンクション・バーとファンクション・メニューのフォームへの追加

 それではフォームに対して、ここまでに作成したファンクション・バーとファンクション・メニューを追加して使ってみよう。

■ファンクション・バーとファンクション・メニューの追加方法

 フォームへファンクション・バーとファンクション・メニューを追加する方法はいつもと同じである。フォーム・デザイナ上にドラッグ&ドロップするだけだ。注意点は、ファンクション・メニューのメニュー項目がフォーム内には生成されないことだ。そのため、フォーム・デザイナ上には何も表示されない(もちろん、実行すれば正しく表示される)。

 フォーム上に追加したそれぞれのコントロールをダブルクリックしてみよう。これにより、標準のイベント・ハンドラがフォームのコード内に追加される。具体的には、ファンクション・バーは「Clickイベント・ハンドラ」(本稿の例では「functionBar1_ButtonClickメソッド」)が、ファンクション・メニューは「FunctionKeyPressイベント・ハンドラ」(本稿の例では「functionMenu1_FunctionKeyPressメソッド」)が追加されるはずだ。先ほどFunctionKeyPressイベントに対してDefaultEvent属性を指定したが、このおかげでFunctionKeyPressイベントがファンクション・メニューの標準イベントとなり、ダブルクリックした際にはそのイベント・ハンドラが追加されることになっているのだ。

 なおここでも1つ問題が発生している。本稿では、ファンクション・バーは大きさが自動的に変更される設定になっている(=AutoSizeプロパティがTrueになっている)ので、場合によってはファンクション・バーの近くに配置したコントロールが、ファンクション・バーと重なって隠れてしまう可能性がある。これを避けるために、ファンクション・バーの下に標準のPanelコントロールを配置し、そのDockプロパティを「Fill」(=コントロールを全域に広げる)に設定する。つまり、フォームの上部がファンクション・バー、下部がPanelコントロールという状態にする。

 これらの手順を実行しているのが次の画面だ。

ファンクション・バーとファンクション・メニューのフォームへの配置と設定
この画面のような手順により、すべてのフォームに対してファンクション・バーとファンクション・メニューの追加と設定を行う。
  [FunctionBar]コントロールをフォーム・デザイナ上にドラッグ&ドロップする。これにより、ファンクション・バーがフォームに追加される。
  [FunctionMenu]コントロールをドラッグ&ドロップすると、ファンクション・メニューがフォームに追加される。なお、この画面を見れば分かるが、コントロールに追加済みのファンクションのメニュー項目は、フォーム・デザイナ上では見えないので注意してほしい。実際にプログラムを実行すると正しくメニューが表示される。
  標準のPanelコントロールを配置し、そのDockプロパティを「Fill」に設定する。なお、すでにコントロールをフォーム上に配置済みの場合には、それらのコントロールをPanelコントロール上に再配置する必要がある(すべてのコントロールを選択したうえで、カット&ペーストすればよい。ただしClickイベント・ハンドラの設定が失われるのでイベント・ハンドラの再設定が必要)。
  ファンクション・バーをダブルクリックすると、ファクション・ボタンのClickイベント・ハンドラが追加される。
  (フォーム・デザイナ下部のコンポーネント領域にある)ファンクション・メニューをダブルクリックすると、ファンクション・メニューのFunctionKeyPressイベント・ハンドラが追加される。

■ファンクション・バーとファンクション・メニューのイベント・ハンドラ

 上記の作業により、ファンクション・バーのClickイベント・ハンドラ(本稿の例では「functionBar1_ButtonClickメソッド」)と、ファンクション・メニューのFunctionKeyPressイベント・ハンドラ(本稿の例では「functionMenu1_FunctionKeyPressメソッド」)が追加されたら、それらのメソッド内に次のようなコードを記述しよう。

private void functionBar1_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e)
{
  // ファンクション・メニューでのクリックにすり替え
  this.functionMenu1.PerformClick(e.Button.Tag.ToString());
}

private void functionMenu1_FunctionKeyPress(object sender, Insiders.Windows.Forms.FunctionKeyPressEventArgs e)
{
  // ファンクション・キーごとの処理を実行
  switch (e.FunctionKey)
  {
    case FunctionKey.F1: MessageBox.Show("F1"); break;
    case FunctionKey.F2: MessageBox.Show("F2"); break;
    ……中略……
    case FunctionKey.Escape: this.Close(); break;
  }
}
ファンクション・バーとファンクション・メニューのイベント・ハンドラの実装

 ファンクション・バーのfunctionBar1_ButtonClickイベント・ハンドラでは、クリックされたファンクション・バーのボタンのタグ文字列をパラメータに指定して(先ほど実装した)ファンクション・メニューのPerformClickメソッドを呼び出している。これにより、ファンクション・バーでのクリックが、ファンクション・メニューでのクリックにすり替わる。要するに、ファンクション・バーの処理も実際にはファンクション・メニュー側で行われることになる。

 ファンクション・メニューのfunctionMenu1_FunctionKeyPressイベント・ハンドラでは、メソッド・パラメータとして渡されたFunctionKeyPressEventArgsオブジェクトから、ファンクション・キーの値を取得し、そのキーごとに個別の処理を行っている。

 つまりこの2つのメソッド内容により、前述したように、ファンクション・バーとファンクション・メニューの処理を(ファンクション・メニューの)FunctionKeyPressイベント・ハンドラで一元管理しているわけである。

■ファンクションの設定

 最後に、ファンクション・バーやファンクション・メニューの項目のテキスト設定と、その有効化/無効化の設定を行う。これはそれぞれのフォームごとで行う必要がある。本稿では、これらの設定処理は各フォームのコンストラクタで行うことにしよう。

 そのサンプル・コードは次のとおりだ。

public StartMenuWindow ()
{
  InitializeComponent();
  SetFunction();
}

private void SetFunction()
{
  // (1)FunctionManagerオブジェクトの生成
  FunctionManager man = new FunctionManager(functionMenu1, functionBar1);
  // (2)FunctionManagerオブジェクトのSetFunctionメソッドの呼び出し
  man.SetFunction(
    FunctionKey.F1, "ヘルプ", "ヘルプを表示します。");
  // (3)FunctionManagerオブジェクトのDisableFunctionメソッドの呼び出し
  man.DisableFunction(
    FunctionKey.F2,  FunctionKey.F3,  FunctionKey.F4);
}
ファンクション設定のサンプル・コード
コードの実装内容については下の本文に記述した。

 本稿では、ファンクション・バーやファンクション・メニューを一括して設定するためのクラスとして、FunctionManagerクラスを実装している。上記のコードではこのクラスを利用している。具体的には、SetFunctionメソッドにおいて次の流れで設定を行っている。

(1)FunctionManagerオブジェクトの生成
→そのコンストラクタにより、ファンクション・バーやファンクション・メニューのオブジェクトを設定している。

(2)FunctionManagerオブジェクトのSetFunctionメソッドの呼び出し
→この例では[F1]キーのテキストを「ヘルプ」とし、ツールチップのテキストとして「ヘルプを表示します。」を設定している。

(3)FunctionManagerオブジェクトのDisableFunctionメソッドの呼び出し
→この例では[F2][F3][F4]キーを無効化している。

■ファンクション・バーとファンクション・メニューの実行

 以上でファンクション・キーへの対応が終わった。ほかのフォームに対しても、この「ファンクション・バーとファンクション・メニューの追加」「イベント・ハンドラの実装」「ファンクションの設定」という手順を実行しておこう。

 次の画面は、上記のプログラムを実際に動かした結果だ。

ファンクション・バーとファンクション・メニューを追加したフォームの実行結果
[F1]キーは、SetFunctionメソッドにより設定した「ヘルプ」というテキストが両方のコントロールとも正しく反映されている(この画面では確認できないが、ファンクション・バーの[F1]ボタンにマウス・カーソルを合わせると、「ヘルプを表示します。」というツールチップが現れる)。また[F2]〜[F4]キーは、DisableFunctionメソッドの指定どおりに無効化されている。
  正しく追加および設定されたファンクション・バー。
  正しく追加および設定されたファンクション・メニュー。

■[Escape]キーの有効化

 実は1点だけ、まだ実装が不足している個所がある。前述したように、メニュー項目のShortcutプロパティは[Escape]キーに対応していないため、このままでは[Escape]キーが効かない。

 これに対応するには、フォームで[Escape]キーを取得して、それをメニュー・バーに通知する必要がある。この処理は、もちろんMDI子ウィンドウのフォームで行ってもよいが、すべてのMDI子ウィンドウに実装が必要となることを考えれば、それよりもMDI親ウィンドウで行った方が効率的だ。

 具体的には、MDI親ウィンドウ(本稿では「MainWindow」クラス)のProcessDialogKeyメソッドをオーバーライドして、その中に次のコードを記述すればよい。

// [Escape]キーが押されたら子MDIウィンドウを閉じる
protected override bool ProcessDialogKey(Keys keyData)
{
  // 基底クラスのProcessDialogKeyを事前に呼び出す
  if (base.ProcessDialogKey (keyData) == true)
  {
    // 基底クラスで処理された場合には
    // 処理済み(true)の戻り値を返す
    return true;
  }
  // MDI親ウィンドウで[Escape]キーを取得
  if (keyData == Keys.Escape)
  {
    // それをメニュー・バーに通知
    return FunctionMenu.ProcessEscapeKey(ActiveMdiChild);
  }
  return false;
}
MDI親ウィンドウに実装した[Escape]キーへの対応
MDI親ウィンドウで[Escape]キーを取得して、それをメニュー・バーに通知している。

 上記のコードでは、[Escape]キーが入力された際に、ファンクション・メニューの静的メソッド「ProcessEscapeKey」(前述)を呼び出すことで、ファンクション・メニューへの[Escape]キーの通知を実現している。

 ちなみにVisual C# .NETでは、エディタ上で「override」と記述すると、IntelliSenseが働いて、オーバーライド可能なメソッドのリストが表示される便利な機能があるので、ぜひ活用するとよい。

 前回と今回は業務系アプリケーションのユーザビリティを高めるファンクション・バーおよびファンクション・メニューの実装方法を紹介した。その作成を通して、コンポーネントの終了処理や、メニューのマージについて説明した。

 さて次回は、フォーカスのあるコントロールをハイライト表示して目立たせたり、その入力項目の説明をツールチップで表示したり、入力内容に問題がある場合に.NETの機能によるエラー通知を行ったりするといった機能を実装する予定だ。これらの機能も、アプリケーションの使い勝手を高めるためには必須の項目だ。次回もご期待いただきたい。End of Article

 

 INDEX
  解説:実例で学ぶWindowsプログラミング
  第4回 操作性を向上させるファンクション・キーへの対応(後編)
    1.ファンクション・メニューの実装
    2.FunctionMenuコントロールの作成
    3.独自イベントの実装方法
  4.ファンクション・バーとファンクション・メニューのフォームへの追加
 
インデックス・ページヘ  「解説:実例で学ぶWindowsプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH