トレーニング
モジュール
Windows 開発プロジェクトに最適なアプリケーション フレームワークを選ぶ - Training
Windows 開発者には、Windows で実行されるアプリケーションを作成するためのさまざまなオプションがあります。 このモジュールでは、Windows 開発に使用できる Windows UI フレームワークを紹介します。 また、アプリケーションに最適なフレームワークを選ぶ方法に関するガイダンスも提供します。
このブラウザーはサポートされなくなりました。
Microsoft Edge にアップグレードすると、最新の機能、セキュリティ更新プログラム、およびテクニカル サポートを利用できます。
このノートでは、カスタム コントロールと自己描画コントロールの MFC サポートについて説明します。 また、動的サブクラス化について説明し、CWnd オブジェクトと HWND
の関係について説明します。
MFC サンプル アプリケーション CTRLTEST は、多くのカスタム コントロールを使用する方法を示しています。 MFC の一般的なサンプル CTRLTEST とオンライン ヘルプのソース コードを参照してください。
Windows メッセージを使用して、所有者描画コントロールとメニューをサポートします。 コントロールまたはメニューの親ウィンドウは、これらのメッセージを受信し、応答で関数を呼び出します。 これらの関数をオーバーライドして、所有者描画コントロールまたはメニューの外観と動作をカスタマイズできます。
MFC では、次の関数を使用した所有者描画が直接サポートされます:
CWnd
派生クラスでこれらの関数をオーバーライドして、カスタム描画動作を実装できます。
この方法では、再利用可能なコードは得られません。 2 つの異なる CWnd
クラスに 2 つの類似したコントロールがある場合は、2 つの場所にカスタム コントロールの動作を実装する必要があります。 MFC でサポートされている自己描画コントロール アーキテクチャによって、この問題が解決されます。
MFC は、標準の所有者描画メッセージの既定の実装 ( CWnd
と CMenu クラス) を提供します。 この既定の実装では、所有者描画パラメーターがデコードされ、所有者描画メッセージがコントロールまたはメニューに委任されます。 描画コードはコントロールまたはメニューの クラスに含まれ、所有者ウィンドウには含めないため、これは自己描画と呼ばれます。
自己描画コントロールを使用すると、所有者描画セマンティクスを使用してコントロールを表示する再利用可能なコントロール クラスを構築できます。 コントロールを描画するコードは、その親ではなく、コントロール クラス内に配置されます。 これは、カスタム コントロール プログラミングに対するオブジェクト指向のアプローチです。 次の関数の一覧を自己描画クラスに追加します:
自己描画ボタンの場合:
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 or CBS_SORT スタイルを持つ自己描画リスト ボックスおよびコンボ ボックスの場合、OnCompareItem
メソッドをオーバーライドする必要があります。
自己描画リスト ボックスとコンボ ボックスの場合、 OnDeleteItem
は通常オーバーライドされません。 特別な処理を実行する場合は、 OnDeleteItem
をオーバーライドできます。 これが該当するケースの 1 つは、追加のメモリまたは他のリソースが各リスト ボックスまたはコンボ ボックス項目と一緒に格納されている場合です。
MFC の一般的なサンプル CTRLTEST には、自己描画メニューと自己描画リスト ボックスのサンプルが含まれています。
自己描画ボタンの最も一般的な例は、ビットマップ ボタンです。 ビットマップ ボタンは、異なる状態のビットマップ イメージを 1 つ、2 つ、または 3 つ表示するボタンです。 この例は、MFC クラス CBitmapButton で提供されています。
場合によっては、既に存在するオブジェクトの機能を変更する必要があります。 前の例では、コントロールを作成する前にカスタマイズする必要があります。 動的サブクラス化を使用すると、既に作成されているコントロールをカスタマイズできます。
サブクラス化は、ウィンドウの WndProc をカスタマイズした WndProc
に置き換え、既定の機能のために古い WndProc
を呼び出す場合の用語です。
これを、C++ クラスの派生と混同しないでください。 明確にするために、C++ 用語の基本クラスと派生クラスは、Windows オブジェクト モデルのスーパークラスとサブクラスに類似しています。 MFC を使用した C++ 派生とWindowsサブクラス化は機能的に似ていますが、C++ では動的サブクラス化がサポートされていません。
CWnd
クラスは、C++ オブジェクト (CWnd
から派生) と Windows ウィンドウ オブジェクト (HWND
と呼ばれる) 間の接続を提供します。
これらが関連する一般的な方法は 3 種類あります:
CWnd
HWND
を作成します。 CWnd
から派生したクラスを作成することで、派生クラスの動作を変更できます。 HWND
は 、アプリケーションにより CWnd::Create が呼び出された場合に作成されます。
アプリケーションは、CWnd
を既存のHWND
にアタッチします。 既存のウィンドウの動作は変更されません。 これは委任のケースであり、CWnd::Attach を呼び出して、既存の HWND
を CWnd
オブジェクトにエイリアスとして指定することで可能になります。
CWnd
は既存の HWND
にアタッチされ 、派生クラスの動作を変更できます。 これが動的サブクラス化と呼ばれるのは、実行時に Windows オブジェクトの動作 (したがって、クラス) 変更するためです。
動的サブクラス化は、CWnd::SubclassWindow とCWnd::SubclassDlgItem のメソッド使用して実現できます。
どちらのルーチンでも、CWnd
オブジェクトを 既存の HWND
にアタッチします。 SubclassWindow
は HWND
を直接受け取ります。 SubclassDlgItem
は、コントロール ID と親ウィンドウを受け取るヘルパー関数です。 SubclassDlgItem
は、ダイアログ テンプレートから作成されたダイアログ コントロールに C++ オブジェクトをアタッチするように設計されています。
SubclassWindow
と SubclassDlgItem
を使用する場合のいくつかの例については、CTRLTEST の例を参照してください。
トレーニング
モジュール
Windows 開発プロジェクトに最適なアプリケーション フレームワークを選ぶ - Training
Windows 開発者には、Windows で実行されるアプリケーションを作成するためのさまざまなオプションがあります。 このモジュールでは、Windows 開発に使用できる Windows UI フレームワークを紹介します。 また、アプリケーションに最適なフレームワークを選ぶ方法に関するガイダンスも提供します。