japan.internet.comThe Internet & IT Network
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2009年7月4日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
デベロッパー コラム2008年12月19日 10:00
CodeGuru
CodeGuru japan.internet.com 編集部(japan.internet.com)メールホームrss
米国 WebMediaBrands が運営する、プログラムコードに関する専門サイト。
多数の記事、多数のコードを掲載し、ソースコードをダウンロードすることもできる。

カスタマイズ可能なアラートウィンドウ

海外海外internet.com発の記事

はじめに

 最近あるプロジェクトで、Outlookで新しい電子メールを受信したときに表示されるような通知を、ユーザーに表示する必要が出てきました。ところが、Visual Studio 2003やVisual Studio 2005では、ちょうど良い方法が見つかりませんでした。もちろん、Visual Studio 2008を使用している場合は、(Visual Studio 2008 SP1に統合された)Feature Packリリースで、このための一連のクラスが提供されているので、MFCから無償で入手できます。ただし、Visual Studio 2008を使用しないときは、著者の場合と同じようにつまずく可能性があります。そこで、この問題に関して対応策を練ることにしました。その結果でき上がったのが、さまざまなスタイルの通知ウィンドウを作成できる一連のクラスです。

 今回のミニフレームワークで作成した、カスタマイズ済みアラートウィンドウの例を以下に示します。

シンプルなメール通知
シンプルなメール通知
Office 2003ライクなメール通知
Office 2003ライクなメール通知
Firefox 3のダウンロード完了通知
Firefox 3のダウンロード完了通知
Winampの新規トラック通知
Winampの新規トラック通知

フレームワークの解説

 今回のミニフレームワークを構成するクラスは、次の3つのカテゴリに分類されます。

アラートダイアログ
 表示されるすべてのアラートダイアログの基本クラスです。スタイルを使用して外観をカスタマイズできます。

※注
 上記のクラス図で、CMailAlert、CFirefoxAlertおよびCWinampAlertの各クラスはフレームワークの一部ではなく、本稿で作成するデモアプリケーションに含まれるアラートダイアログの例です。

アラートスタイル
 アラートダイアログの背景と非クライアント領域の描画を処理するクラスの階層です。

アラートコントロール
 アラートダイアログで使用する各種カスタムコントロール(ラベル、ハイパーリンク、画像コントロール、ボタン)です。

CAlertDialog

 CDialogから派生したクラスで、表示されるすべてのアラートウィンドウの基本クラスです。次のような機能があります。

  • 表示するときと閉じるときに、アニメーションしながらタスクバーの上にダイアログを表示します。
  • 設定されたアニメーション時間、表示時間および透過レベルを使用します。
  • マウスが上に重なっているときは、無期限にアクティブを維持します(つまり、マウスがウィンドウ上にあるときは表示経過時間がリセットされます)。
  • 画面の境界内でマウスを使用してウィンドウを移動できます(モニタの数は不問)。
  • 背景と非クライアント領域の描画方法をアラートスタイルでパラメータ化できます。
 このクラスには、以下の3種類のパブリックメソッドがあります。

  • Show()
    アニメーションしながらダイアログを表示します。表示されるまでの時間、表示されている時間、ウィンドウの最大不透明度(255で完全に不透明、0で完全に透過)、およびマウスが上にあるときにウィンドウを表示したまま(完全に不透明のまま)とするかどうかを指定できます。
  • Hide()
    すぐにダイアログを閉じます。アニメーションは中止します(アニメーションしている場合)。
  • SetAlertStyle()
    背景と非クライアント領域の描画処理に使用するスタイルオブジェクトを設定します。
 OnNcPaint()はスタイルオブジェクトのHandleNcPaint()を呼び出し、OnEraseBkgnd()HandleEraseBkgnd()を呼び出します。これらのメソッドのいずれかがFALSEを返すと、イベントの処理は基本クラス(CDialog)に委任されます。

CAlertStyle

 すべてのアラートスタイルの基本クラスで、アラートウィンドウのカスタマイズに使用します。以下の仮想メソッドがあります。

  • HandleNcPaint()
    ウィンドウの非クライアント描画を処理します。
  • HandleEraseBkgnd()
    ウィンドウの背景描画を処理します。
  • OnInitialize()
    ウィンドウの生成時に呼び出され、必要に応じて初期化を実行します。

CAlertStyleDefault

 基本のスタイル実装です。背景の消去を処理せず、アラートウィンドウの周りにシンプルな境界線を描画します。

CAlertStyleOffice2003

 Office 2003ライクなアラートスタイルです。青いグラデーションのかかった背景と、境界線の黒い四角形のウィンドウを表示します。ウィンドウの最上部に濃い青の小さなバーがあります。

CAlertStyleFirefox

 Firefoxのダウンロード通知ウィンドウに似た外観のウィンドウを生成します。周囲は青い四角形で、背景にはシステムカラーCOLOR_BTNFACEを使用します。

CAlertStyleWinamp

 Winampの新規トラック通知ウィンドウに似た外観のウィンドウを生成します。縁は黒くて丸みがあり、背景にはグレースケールのグラデーションがかかっています。

CAlertLabel

 背景が透明なスタティックコントロールです。テキストにはカスタムカラーを設定できます。デフォルトでは、この色には黒が設定されます。背景の描画にはキャッシュ済みのビットマップを使用します。コントロールの背景を変更した場合は、InvalidateCachedBitmapを呼び出してキャッシュを無効にする必要があります。

CAlertHyperlink

 アラートハイパーリンクはCAlertLabelから派生します。次の追加機能を提供します。

  • マウスがコントロール上にある場合とない場合で、テキストの表示に異なる色を設定できます。
  • テキストに下線を引くことができます。
  • マウスがコントロール上にあるときに、別のカーソルを割り当てることができます。
  • クリックされたときに親クラスに通知します。

CAlertPictureCtrl

 アラート画像コントロール(CAlertLabelから派生)は、透明化できる画像を表示します。以下のような機能があります。

  • アイコンまたはビットマップを表示できます。
  • イメージの描画に透明色を使用できます。

CAlertButton

 アラートボタンは、以下のような機能を持つボタンです。

  • 常にフラットです。
  • ビットマップまたはアイコンを設定できます。これは、必ずクライアント領域の中央に表示されます。
  • イメージ描画用の透明色を指定できます。
  • マウスがコントロール上にあるときの背景描画用のハイライト色を指定できます。
  • クリックされたときに親クラスに通知します。

CAlertButtonClose

 クローズアラートボタンは、ウィンドウを閉じるX印を表示するアラートボタンです(このボタン用のアイコンリソースやビットマップリソースは不要です)。

フレームワークの使い方

 下図に、電子メールのアラートウィンドウ作成に使用したコントロールを示します。

 次の作業を実行してください。

  • ダイアログテンプレート(境界なし)を作成し、必要に応じてラベルまたはハイパーリンクを表示するためのスタティックコントロールや、ボタン、画像コントロールを追加します。
  • ダイアログテンプレートからクラス(CDialogから派生したもの)を追加します。
  • クラスヘッダーに「AlertDialog.h」をインクルードし、基本クラスをCDialogからCAlertDialogに変更します。
  • アラートダイアログに使用するカスタマイズ済みの各コントロール(アラートコントロール)に対して、DDX機能を使用して変数を追加します。例えば、タイトルを表示するラベルに対して、以下を実行します。
    • ダイアログクラスのヘッダーに「AlertLabel.h」をインクルードします。
    • CAlertLabel型の変数をクラスに追加します。
    • CAlertLabel m_ctrlTitle;
      
    • 次のように、DoDataExchangeで変数をコントロールに関連付けます。
    • void CDemoAlert::DoDataExchange(CDataExchange* pDX)
      {
         CAlertDialog::DoDataExchange(pDX);
      
         DDX_Control(pDX, IDC_STATIC_TITLE, m_ctrlTitle);
      }
      
  • アラートウィンドウの背景を変更する場合は、OnInvalidateをオーバーライドして、すべてのラベル、ハイパーリンク、画像コントロールおよびボタンについてInvalidateCachedBitmap()を呼び出す必要があります。
  • void CDemoAlert::OnInvalidate()
    {
       m_ctrlTitle.InvalidateCachedBitmap();
    }
    
  • ハイパーリンクまたはボタンがクリックされたときに通知が必要な場合は、「AlertMessages.h」内に定義されている適切なメッセージを処理します。
    • クラスにメッセージハンドラを追加します。
    •    afx_msg LRESULT OnHyperlinkedClicked(WPARAM wParam,
                                              LPARAM lParam);
         afx_msg LRESULT OnButtonClicked(WPARAM wParam,
                                         LPARAM lParam);
      
    • 適切なハンドラをメッセージマップに追加します。
    • BEGIN_MESSAGE_MAP(CDemoAlert, CAlertDialog)
         ON_MESSAGE(WMA_HYPERLINKCLICKED,
                    &CDemoAlert::OnHyperlinkedClicked)
         ON_MESSAGE(WMA_BUTTONCLICKED,
                    &CDemoAlert::OnButtonClicked)
      END_MESSAGE_MAP()
      
    • ハンドラを実装します。通常は、親ウィンドウにメッセージを送信して、特定のボタンまたはコントロールがクリックされたことを通知します。以下のコードでは、アラートウィンドウのみを非表示にします。
    • LRESULT CDemoAlert::OnHyperlinkedClicked(WPARAM wParam,
                                               LPARAM lParam)
      {
         Hide();
      
         return 0;
      }
      
      LRESULT CDemoAlert::OnButtonClicked(WPARAM wParam,
                                          LPARAM lParam)
      {
         Hide();
      
         return 0;
      }
      
  • デフォルトでは、CAlertDialogWM_LBUTTONDOWNWM_LBUTTONUPを処理すると、マウスを使ってウィンドウを移動できます。この動作が不要な場合(例えばユーザーがウィンドウをクリックしたら、ウィンドウを閉じるような場合)は、派生したダイアログクラスでこれらのメッセージを処理し、適切なアクションを実行してください。例については、デモアプリケーションのCWinampAlertをご覧ください。
 これらのクラスの使用例については、デモアプリケーションを参照ください。

デモアプリケーション

 本稿では、3種類のアラートウィンドウを生成するデモアプリケーションを作成します。それぞれ、電子メール通知、FirefoxライクなアラートおよびWinampライクなアラートです(スクリーンショットは、本稿の最初にあります)。

 このデモアプリケーションでは、以下の設定をカスタマイズできます。

  • アニメーション時間(表示するときと通常閉じるとき)。ミリ秒単位で指定します。
  • 表示時間(表示アニメーションが終了してから閉じるアニメーションが始まるまでの間隔)。ミリ秒単位で指定します。
  • 表示アニメーションが終了した後の最大不透明度。0?100のパーセント単位で指定します。100を指定すると、ウィンドウが完全に不透明になります。
  • マウスがウィンドウ上にあるときに(不透明でなければ)ウィンドウを完全に不透明にして、マウスがウィンドウから離れるまで表示し続けるかどうか。この場合、マウスがウィンドウから離れると、表示タイマが再開されます。

注意事項

 本稿で紹介したコードは、著作権表示を明記する場合に限り、(営利、非営利に関わらず)どのような種類のアプリケーションでも利用、改変または拡張することができます。新たにコントロールや機能を作成して第三者に公開する場合は、既存のコードと統合するときにお気軽にご連絡ください。

謝辞

 一部のコードについては、以下の記事と投稿より、コードを引用または参考とさせていただきました。

著者紹介

Marius Bancila(Marius Bancila)
VC++の分野でMicrosoft MVPを受賞。ノルウェー企業でソフトウェア開発者として勤務。主にMFCとVC#を使ったデスクトップアプリケーションの構築に従事。ブログ(www.mariusbancila.ro/blog)の内容はWindowsプログラミングが中心。2007年7月に、ルーマニア人のMVP受賞者2人と一緒に、ルーマニアのC++/VC++プログラマのコミュニティであるodexpert.roを設立した。
Copyright 2009 Japan Internet.com K.K. All Rights Reserved.http://www.internet.com/