テクニカル ノート 14: カスタム コントロール
ここでは、カスタムおよび自己描画コントロールに対する MFC のサポートについて説明します。また、動的サブクラス化について説明し、 CWnd のオブジェクトと HWNDの秒間の関係を示します。
MFC の CTRLTEST サンプル アプリケーションは、多くのカスタム コントロールを使用する方法について説明します。MFC の一般的なサンプル CTRLTEST とオンライン ヘルプについては、ソース・コードを参照してください。
オーナー描画コントロールとメニュー
ウィンドウがオーナー描画コントロールとメニューに Windows メッセージの使用によりサポートを提供します。コントロールまたはメニューの親ウィンドウでこれらのメッセージを受信し、応答関数を呼び出しますします。オーナー描画コントロールまたはメニューの外観と動作をカスタマイズするためにこれらの関数をオーバーライドできます。
MFC は直接次の関数のオーナー描画をサポートします:
カスタム描画の動作を実装するに CWnd の派生クラスでこれらの関数をオーバーライドできます。
この方法は、再利用可能なコードの原因はありません。CWnd の 2 種類のクラスに 2 個の同様のコントロールがある場合、 2 か所でカスタム コントロールの動作を実装します。MFC サポートされる自己描画コントロール アーキテクチャでは、この問題を解決します。
自己描画コントロールとメニュー
MFC は、標準のオーナー描画のメッセージに既定の実装 ( CMenu の CWnd およびクラス)を提供します。この既定の実装では、オーナー描画パラメーターを解釈し、コントロールまたはメニューにオーナー描画メッセージに委任します。これは、描画コードがコントロールまたはメニューのクラスにあるため、オーナー ウィンドウの自己描画と、呼び出されます。
自己描画コントロールを使用してコントロールを表示するには、オーナー描画のセマンティクスを使用する再利用可能なコントロールのクラスをビルドできます。コントロールを描画するためのコードは親コントロール クラスではなくありません。これは、カスタム コントロールのプログラミングにオブジェクト指向方法です。自己描画のクラスに関数を次のリストを追加します:
自己描画ボタンの場合:
CButton:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this button
自己描画のメニューの場合:
CMenu:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this menu CMenu:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this menu
自己描画リスト ボックスの場合:
CListBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this list box CListBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this list box CListBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this list box if LBS_SORT CListBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this list box
自己描画コンボ ボックスの場合:
CComboBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this combo box CComboBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this combo box CComboBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this combo box if CBS_SORT CComboBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this combo box
オーナー描画の詳細については、構造体 (DRAWITEMSTRUCT、 MEASUREITEMSTRUCT、 COMPAREITEMSTRUCTと DELETEITEMSTRUCT)は、 CWnd::OnDrawItem、 CWnd::OnMeasureItem、 CWnd::OnCompareItemと CWnd::OnDeleteItem については、 MFC のドキュメントを参照してください。
自己描画コントロールとメニューを使用する
自己描画のメニューについては、 OnMeasureItem と OnDrawItem のメソッドをオーバーライドします。
自己描画リスト ボックス、コンボ ボックスでは、 OnMeasureItem と OnDrawItemをオーバーライドします。リスト ボックスに LBS_OWNERDRAWVARIABLE のフォームまたはコンボ ボックスのダイアログ テンプレートで CBS_OWNERDRAWVARIABLE の形式を指定します。OWNERDRAWFIXED のフォームは自己描画の項目を自己描画コントロールがリスト ボックスに接続される前に固定項目の高さを決定できないため、使用しません。この制限を回避するには、メソッド CListBox::SetItemHeight と CComboBox::SetItemHeight を使用できます)。
OWNERDRAWVARIABLE にフォームを切り替えると、システムにコントロールに NOINTEGRALHEIGHT の形式を適用します。コントロールが可変サイズの項目で必要な高さを計算できないため INTEGRALHEIGHT の既定のスタイルは無視され、コントロールは NOINTEGRALHEIGHT常にです。項目が修正された高さの場合、部分的な項目がコントロールのサイズを指定して、項目のサイズに整数の乗数として描画されないようにできます。
LBS_SORT または CBS_SORT のフォームの自己描画リスト ボックス、コンボ ボックスでは、 OnCompareItem のメソッドをオーバーライドします。
自己描画リスト ボックス、コンボ ボックスでは、 OnDeleteItem は、通常はオーバーライドされません。特別な処理を実行する場合は、 OnDeleteItem をオーバーライドできます。これが適用されるの 1 種類のケースは追加のメモリやそのほかのリソースが各リスト ボックスやコンボ ボックスの項目に格納されている場合です。
自己描画コントロールとメニューの例
MFC の一般的なサンプル CTRLTEST は自己描画のメニューおよび自己描画リスト ボックスのサンプルを紹介します。
自己描画ボタンのほとんどの代表的な例は、ビットマップ ボタンです。ビットマップ ボタンはさまざまな状態の 1 ビット、 2 ビット、または 3 ビットのビットマップ イメージを表示するボタンです。この例は、 MFC クラス CBitmapButtonで説明します。
動的サブクラス化
場合によっては既に存在するオブジェクトの機能を変更する必要があります。前の例で作成される前にコントロールをカスタマイズする必要があります。動的サブクラス化は既に作成されているコントロールをカスタマイズできるようにします。
サブクラス化は、ペインの WndProc をカスタマイズされた WndProc で置き換え、既定の機能の古い WndProc を呼び出すための Windows の用語です。
これは C++ のクラスの派生と混同しないでください。ついては、 C++ の用語 基本クラス と 派生クラスは 、ペイン オブジェクト モデルの スーパークラス 化、および サブクラス に似ています。C++ が動的サブクラス化をサポートしない以外、 MFC C++ のサブクラス化派生、ウィンドウは機能的に同じです。
CWnd のクラスは、. のオブジェクト ( CWndから派生)とウィンドウのオブジェクト間の接続を提供します ( HWNDと呼ばれます)。
これらが参照する 3 種類の一般的な方法があります:
CWnd は HWNDを作成します。CWndから派生したクラスを作成して、派生クラスの動作を変更できます。HWND は、アプリケーションが CWnd::Createをダイヤルするときに作成されます。
アプリケーションは、既存の HWNDに CWnd をアタッチします。既存のペインの動作は変更されません。これは、デリゲートの例では、エイリアスへの CWnd::Attach を CWnd のオブジェクトへの HWND を呼び出すことによって可能になります。
CWnd は、既存の HWND にアタッチされ、派生クラスの動作を変更できます。これは意図した動作を変更すると、実行時のペイン オブジェクトのクラス、呼び出されるため、動的サブクラス化。
メソッド CWnd::SubclassWindow とCWnd::SubclassDlgItemを使用して動的サブクラス化を実行できます。
ルーチンは両方とも、既存の HWNDへの CWnd のオブジェクトを接続します。SubclassWindow は HWND を直接受け取ります。SubclassDlgItem はコントロールの ID と親ウィンドウを取得するヘルパー関数です。SubclassDlgItem はダイアログ テンプレートから作成されたダイアログ コントロールに C++ オブジェクトを接続するように設計されています。
SubclassWindow と SubclassDlgItemの複数の例については CTRLTEST の例を使用するか参照してください。