プロパティ シートの概要

プロパティ シートは、ユーザーがアイテムのプロパティを表示および編集できるウィンドウです。 たとえば、スプレッドシート アプリケーションでは、プロパティ シートを使用して、ユーザーがセルのフォントと罫線のプロパティを設定したり、ディスク ドライブ、プリンター、マウスなどのデバイスのプロパティを表示および設定したりできます。

このセクションでは、次のトピックについて説明します。

プロパティ シートの基本

アプリケーションにプロパティ シートを実装するには、プロジェクトに Prsht.h ヘッダー ファイルを含めます。 Prsht.h には、プロパティ シートで使用されるすべての識別子が含まれています。

プロパティ シートには、ページと呼ばれる 1 つ以上の重複する子ウィンドウが含まれています。それぞれに、関連するプロパティのグループを設定するためのコントロール ウィンドウが含まれています。 たとえば、ページには、種類のスタイル、ポイント サイズ、色など、アイテムのフォント プロパティを設定するためのコントロールを含めることができます。 各ページにはタブがあり、ユーザーはページをプロパティ シートの前景に移動するために選択できます。 たとえば、日付/時刻コントロール パネル アプリケーションには、次のプロパティ シートが表示されます。

screen shot of a property sheet with two tabs, one of which shows a clock and a monthly calendar control

複数のタブ付きページを含む標準プロパティ シートを使用すると、ユーザーはすべてのプロパティにランダムにアクセスできます。 プロパティを順番に設定する方が適切な場合は、ウィザードを使用できます。

[プロパティ シート] ダイアログ ボックス

プロパティ シートとそのプロパティ シートに含まれるページは、実際にはダイアログ ボックスです。 プロパティ シートは、ページを管理し、それらに共通のコンテナーを提供するシステム定義のダイアログ ボックスです。 プロパティ シート ダイアログ ボックスは、モーダルまたはモードレスにすることができます。 これには、フレーム、タイトル バー、4 つのボタン ([OK][キャンセル][適用]、(必要に応じて) [ヘルプ] が含まれます。 ページのダイアログ ボックス プロシージャは、ユーザーがボタンをクリックすると、WM_NOTIFY メッセージの形式で通知コードを受け取ります。

Note

このセクションのすべての情報が、外観と動作が多少異なるウィザードに適用されるわけではありません。 たとえば、ウィザードには異なるボタン一式はありますが、タブはありません。 詳細については、「ウィザードの作成」を参照してください。

プロパティ シート内の各ページは、アイテムのプロパティの表示と編集に使用されるコントロール ウィンドウを管理する、アプリケーション定義のモードレス ダイアログ ボックスです。 各ページの作成に使用するダイアログ ボックス テンプレートと、コントロールを管理し、対応するアイテムのプロパティを設定するダイアログ ボックス プロシージャを指定します。

プロパティ シートは、ページがアクティブ化を取得または失うとき、およびユーザーが [OK][キャンセル][適用]、または [ヘルプ] ボタンをクリックしたときに、ページのダイアログ ボックス プロシージャに通知コードを送信します。 通知は、WM_NOTIFY メッセージの形式で送信されます。 lParam パラメーターは、[プロパティ シート] ダイアログ ボックスへのウィンドウ ハンドルを含む NMHDR 構造体のアドレスです。

一部の通知コードでは、WM_NOTIFY メッセージに応答して、TRUE または FALSE を返すページが必要です。 これを行うには、ページで SetWindowLong 関数を使用して、ページ ダイアログ ボックスの DWL_MSGRESULT 値を TRUE または FALSE に設定する必要があります。

ページ

プロパティ シートには少なくとも 1 つのページを含める必要がありますが、Windows ヘッダー ファイルで定義されている MAXPROPPAGES 値を超えることはできません。 各ページには、プロパティ シートがプロパティ シートに追加された順序に従って割り当てられる 0 から始まるインデックスがあります。 インデックスは、プロパティ シートに送信するメッセージで使用されます。

プロパティ ページには、ネストされたダイアログ ボックスを含めることができます。 その場合は、最上位のダイアログ ボックスの WS_EX_CONTROLPARENT スタイルを含め、親ダイアログ ボックスへのハンドルを使用して IsDialogMessage 関数を呼び出す必要があります。 これにより、ユーザーはニーモニックとダイアログ ボックスのナビゲーション キーを使用して、ネストされたダイアログ ボックス内のコントロールにフォーカスを移動できます。

各ページには、対応するアイコンとラベルがあります。 プロパティ シートは、各ページのタブを作成し、タブにアイコンとラベルを表示します。すべてのプロパティ シート ページで、太字以外のフォントを使用する必要があります。 フォントが太字でないことを確認するには、ダイアログ ボックス テンプレートで DS_3DLOOK スタイルを指定します。

ページのダイアログ ボックス プロシージャで EndDialog 関数を呼び出してはなりません。 これにより、ページだけでなく、プロパティ シート全体が破棄されます。

プロパティ シート ページの最小サイズは、水平方向に 212 ダイアログ単位と垂直方向に 114 ダイアログ単位です。 ページ ダイアログがこれより小さい場合、ページは最小サイズを満たすまで拡大されます。 Prsht.h ヘッダー ファイルには、次の表に示すように、プロパティ シート ページに推奨されるサイズの 3 つのセットが含まれています。

サイズ 説明
PROP_SM_CXDLG 小さなプロパティ シート ページの幅 (ダイアログ単位)。
PROP_SM_CYDLG 小さなプロパティ シート ページの高さ (ダイアログ単位)。
PROP_MED_CXDLG 中規模のプロパティ シート ページの幅 (ダイアログ単位)。
PROP_MED_CYDLG 中規模のプロパティ シート ページの高さ (ダイアログ単位)。
PROP_LG_CXDLG 大きなプロパティ シート ページの幅 (ダイアログ単位)。
PROP_LG_CYDLG 大きなプロパティ シート ページの高さ (ダイアログ単位)。

これらの推奨サイズを使用すると、アプリケーションと他の Microsoft Windows アプリケーションの間で視覚的な一貫性が確保されます。

Microsoft Visual Studio リソース エディターでは、[リソースの追加] ダイアログ ボックスで適切なサイズのページを作成できます。 ダイアログ ノードを展開し、IDD_PROPPAGE_LARGEIDD_PROPPAGE_MEDIUM または IDD_PROPPAGE_SMALL を選択します。

プロパティ シートは、最大ページに合わせて自動的にサイズ設定されます。

プロパティ シートの作成

プロパティ シートを作成する前に、1 つ以上のページを定義する必要があります。 これには、PROPSHEETPAGE 構造体に、ページに関する情報 (アイコン、ラベル、ダイアログ ボックス テンプレート、ダイアログ ボックス プロシージャなど) を入力し、CreatePropertySheetPage 関数の呼び出しで構造体のアドレスを指定する必要があります。 この関数は、ページを一意に識別する HPROPSHEETPAGE 型へのハンドルを返します。

プロパティ シートを作成するには、PropertySheet 関数の呼び出しで PROPSHEETHEADER 構造体のアドレスを指定します。 この構造体は、プロパティ シートのアイコンとタイトルを定義し、CreatePropertySheetPage を使用して取得する HPROPSHEETPAGE ハンドルの配列のアドレスも含みます。 PropertySheet がプロパティ シートを作成すると、配列で識別されたページが含まれます。 ページは、配列に含まれているのと同じ順序でプロパティ シートに表示されます。

プロパティ シートにページを割り当てるもう 1 つの方法は、HPROPSHEETPAGE ハンドルの配列ではなく、PROPSHEETPAGE 構造体の配列を指定することです。 この場合、PropertySheet はページのハンドルを作成してからプロパティ シートに追加します。

ページが最初に作成されると、そのダイアログ ボックス プロシージャは WM_INITDIALOG メッセージを受け取ります。 メッセージの lParam パラメーターは、ページの作成時に定義される PROPSHEETPAGE 構造体のコピーへのポインターです。 特に、ページが作成されるときに、構造体の lParam メンバーを使用して、アプリケーション定義の情報をダイアログ ボックス プロシージャに渡すことができます。 lParam メンバーを除き、この構造体は読み取り専用として扱う必要があります。 lParam 以外を変更すると、予期しない結果が生じる可能性があります。

その後、システムはページの PROPSHEETPAGE 構造体のコピーをアプリケーションに渡すときに、同じポインターを使用します。 構造体に対する変更はすべて渡されます。 lParam メンバーはシステムによって無視されるため、アプリケーションの他の部分に情報を送信するように変更できます。 たとえば、lParam を使用して、ページの PropSheetPageProc コールバック関数に情報を渡すことができます。

PropertySheet は 、プロパティ シートのサイズと初期位置を自動的に設定します。 位置は所有者ウィンドウの位置に基づいており、サイズはプロパティ シートの作成時にページの配列で指定された最大ページに基づきます。 ページをプロパティ シートの下部にある 4 つのボタンの幅と一致させる場合は、最も幅の広いページの幅を 190 ダイアログ単位に設定します。

プロパティ シートのサイズは、リソース ファイル内のダイアログ テンプレートの widthheight プロパティから計算されます。 詳細については、「DIALOG リソース」または「DIALOGEX リソース」を参照してください。 ただし、互換性の理由から、サイズはページで使用されるフォントではなく、MS Shell Dlg フォントに対して相対的に計算されることに注意してください。 別のフォントを使用するページをデザインする場合は、次のいずれかの候補を使用できます。

  • MS Shell Dlg フォントとページが実際に使用するフォントのサイズの差を補正するために、ダイアログ テンプレートのサイズを調整します。 たとえば、MS Shell Dlg の 2 倍の幅のフォントを選択した場合は、ダイアログ テンプレートの width プロパティを通常の 2 倍に設定します。
  • DIALOGEX テンプレートを使用して、DS_SHELLFONT ダイアログ スタイルを設定します。 その場合、プロパティ シート マネージャーはダイアログ テンプレートの寸法を、ダイアログ テンプレートで使用されるフォントに対して相対的に解釈します。

ページの追加と削除

プロパティ シートを作成した後、アプリケーションは、PSM_ADDPAGE メッセージを送信することで、既存のページ セットの末尾にページを追加できます。 既存のページ間にページを挿入するには、PropSheet_InsertPage メッセージを送信します。 プロパティ シートのサイズは、作成後は変更できませんのでご注意ください。 追加または挿入するページは、プロパティ シート内の現在の最大ページを超えてはなりません。 ページを削除するには、PSM_REMOVEPAGE メッセージを送信します。

ページを定義するときに、プロパティ シートがページの作成時または削除時に呼び出す PropSheetPageProc コールバック関数のアドレスを指定できます。 PropSheetPageProc を使用すると、個々のページに対して初期化操作とクリーンアップ操作を実行できます。

Note

プロパティ シートがページの一覧を操作している間に、多数のメッセージと 1 つの関数呼び出しが発生します。 このアクションが実行されている間、ページの一覧を変更しようとすると、予期しない結果が発生します。 PropSheetPageProc の実装でページを追加、挿入、削除したり、次の通知や Windows メッセージを処理したりしないでください。

これらのメッセージの 1 つを処理している間、または PropSheetPageProc の実行中にプロパティ シート ページを変更する必要が生じた場合は、プライベートの Windows メッセージを投稿します。 プロパティ シート マネージャーがタスクを完了するまで、アプリケーションはそのメッセージを受け取りません。その時点で、ページの一覧を変更しても問題ありません。

プロパティ シートが破棄されると、追加されたすべてのページが自動的に破棄されます。 ページは、ページの作成に使用される配列で指定された順序とは逆の順序で破棄されます。 CreatePropertySheetPage 関数が作成したが、プロパティ シートに追加されなかったページを破棄するには、DestroyPropertySheetPage 関数を使用します。

プロパティ シートのタイトルとページ ラベル

プロパティ シートのタイトルは、プロパティ シートの作成に使用される PROPSHEETHEADER 構造体で指定します。 dwFlags メンバーに PSH_PROPTITLE 値が含まれている場合、プロパティ シートは、バージョンに応じてサフィックス「Properties」またはプレフィックス「Properties for」を追加します。 PSM_SETTITLE メッセージを使用してプロパティ シートが作成され後に、タイトルを変更できます。 Aero ウィザードでは、このメッセージを使用して、内部ページのタイトルを動的に変更できます。

既定では、プロパティ シートは、ダイアログ ボックス テンプレートで指定された名前文字列をページのラベルとして使用します。 ページを定義する PROPSHEETPAGE 構造体の dwFlags メンバーに PSP_USETITLE 値を含めることで、名前文字列をオーバーライドできます。 PSP_USETITLE が指定されている場合、pszTitle メンバーにはページのラベル文字列のアドレスが含まれている必要があります。

ページのアクティブ化

プロパティ シートは、一度にアクティブなページを 1 つだけ持つことができます。 アクティブ化されたページは、ページの重なり合うスタックの前景にあります。 ユーザーは、そのタブを選択してページをアクティブにします。アプリケーションは、PSM_SETCURSEL メッセージを使用してページをアクティブ化します。

プロパティ シートは、アクティブ化を失うページに PSN_KILLACTIVE 通知コードを送信します。 応答として、ページはユーザーがページに加えたすべての変更を検証する必要があります。 アクティブ化を失う前にページに追加のユーザーによる入力が必要な場合は、SetWindowLong 関数を使用して、ページの DWL_MSGRESULT 値を TRUE に設定します。 またページには、問題を説明し、推奨されるアクションを指定するメッセージ ボックスが表示されている必要があります。 アクティブ化を失っても問題ない場合は、DWL_MSGRESULTFALSE に設定します。

アクティブ化を取得するページが表示される前に、プロパティ シートは PSN_SETACTIVE 通知コードをページに送信します。 ページは、コントロール ウィンドウを初期化して応答する必要があります。

[ヘルプ] ボタン

プロパティ シートには、フレームの下部で [OK]/、[キャンセル] /、[適用] ボタンの横に表示されるプロパティ シートの [ヘルプ] ボタンと、状況依存のヘルプを提供する標準的なキャプション バー ボタンの 2 つの [ヘルプ] ボタンを表示できます。

プロパティ シートの [ヘルプ] ボタンはオプションであり、ページごとに有効にすることができます。 1 つ以上のページのプロパティ シートの [ヘルプ] ボタンを表示するには:

  • プロパティ シートの PROPSHEETHEADER 構造体の dwFlags メンバーで PSH_HASHELP フラグを設定します。
  • [ヘルプ] ボタンを表示するページごとに、ページの PROPSHEETPAGE 構造体の dwFlags メンバー でPSP_HASHELP フラグを設定します。

ユーザーが [ヘルプ] ボタンをクリックすると、アクティブなページに PSN_HELP 通知コードが表示されます。 ページは、ヘルプ情報を表示して応答する必要があります。通常は、WinHelp 関数を呼び出します。

キャプション バーの [ヘルプ] ボタンの削除

キャプション バーの [ヘルプ] ボタンは既定で表示されるため、状況依存のヘルプは常に [OK]、[キャンセル]、[適用] ボタンで使用できます。 ただし、必要に応じて、このボタンを削除できます。 プロパティ シートのキャプション バーの [ヘルプ] ボタンを削除するには:

  • バージョン 5.80 以前の共通コントロールのバージョンでは、プロパティ シートコールバック関数を実装する必要があります。
  • バージョン 5.80 以降の共通コントロールでは、プロパティ シートの PROPSHEETHEADER 構造体の dwFlags メンバーで PSH_NOCONTEXTHELP フラグを設定するだけです。 ただし、以前の共通コントロール バージョンとの下位互換性が必要な場合は、コールバック関数を実装する必要があります。

キャプション バーの [ヘルプ] ボタンを削除するプロパティ シートコールバック関数を実装するには:

  • プロパティ シートの PROPSHEETHEADER 構造体の dwFlags メンバーで PSH_USECALLBACK フラグを設定します。
  • コールバック関数を指す PROPSHEETHEADER 構造体の pfnCallBack メンバーを設定します。
  • コールバック関数を実装します。 この関数が PSCB_PRECREATE メッセージを受信すると、プロパティ シートのダイアログ ボックス テンプレートへのポインターも受信します。 このテンプレートから DS_CONTEXTHELP スタイルを削除します。

次の例は、このようなコールバック関数を実装する方法を示しています。

int CALLBACK RemoveContextHelpProc(HWND hwnd, UINT message, LPARAM lParam)
{
    switch (message) 
    {
    case PSCB_PRECREATE:
        // Remove the DS_CONTEXTHELP style from the
        // dialog box template
        if (((LPDLGTEMPLATEEX)lParam)->signature ==    
           0xFFFF)
           {
            ((LPDLGTEMPLATEEX)lParam)->style 
            &= ~DS_CONTEXTHELP;
        }
        else {
            ((LPDLGTEMPLATE)lParam)->style 
            &= ~DS_CONTEXTHELP;
        }
        return TRUE;
    }
    return TRUE;
}

DLGTEMPLATEEX 構造体が定義されていない場合は、次の宣言を含めます。

#include <pshpack1.h>

typedef struct DLGTEMPLATEEX
{
    WORD dlgVer;
    WORD signature;
    DWORD helpID;
    DWORD exStyle;
    DWORD style;
    WORD cDlgItems;
    short x;
    short y;
    short cx;
    short cy;
} DLGTEMPLATEEX, *LPDLGTEMPLATEEX;

#include <poppack.h>

[OK]、[キャンセル]、[適用] ボタン

[OK] ボタンと [適用] ボタンは似ています。どちらも、ユーザーが行ったプロパティの変更を検証して適用するようにプロパティ シートのページに指示します。 唯一の違いは、[OK] ボタンをクリックすると、変更が適用された後にプロパティ シートが破棄されることです。

ユーザーが [OK] または [適用] ボタンをクリックすると、プロパティ シートはアクティブなページに PSN_KILLACTIVE 通知を送信し、ユーザーの変更を検証する機会を与えます。 変更が有効な場合、ページは FALSE に設定された DWL_MSGRESULT 値を使用してSetWindowLong 関数を呼び出す必要があります。 ユーザーの変更が無効な場合、ページは、DWL_MSGRESULTTRUE に設定して、ユーザーに問題を報告するダイアログ ボックスを表示します。 ページは、PSN_KILLACTIVE メッセージで DWL_MSGRESULTFALSE に設定されるまでアクティブのままになります。

DWL_MSGRESULTFALSE に設定することで、PSN_KILLACTIVE 通知にページが応答したら、プロパティ シートは、各ページに PSN_APPLY 通知を送信します。 ページがこの通知を受け取ったら、新しいプロパティを対応するアイテムに適用する必要があります。 ページに対する変更が有効であることをプロパティ シートに示すには、PSNRET_NOERROR に設定された DWL_MSGRESULT を使用して、SetWindowLong を呼び出します。 ページの変更が無効な場合は、エラーを返します。 これにより、プロパティ シートが破棄されず、PSN_APPLY通知を受け取ったページまたは [適用] ボタンが押されたときにフォーカスがあったページにフォーカスが返されます。 エラーを返し、フォーカスを受け取るページを示すには、DWL_MSGRESULT を次のいずれかの値に設定します。

  • PSNRET_INVALID。 プロパティ シートは破棄されず、フォーカスはこのページに返されます。
  • PSNRET_INVALID_NOCHANGEPAGE。 プロパティ シートは破棄されず、ボタンが押されたときにフォーカスがあったページにフォーカスが返されます。

アプリケーションでは、PSM_APPLY メッセージを使用して、[適用] ボタンの選択をシミュレートできます。

[適用] ボタンは、ページがアクティブになったときに最初は無効になります。これは、適用するプロパティの変更がまだないことを示します。 ユーザーがプロパティを編集したことを示すコントロールの 1 つを介してページが入力を受け取ったら、ページは PSM_CHANGED メッセージをプロパティ シートに送信する必要があります。 このメッセージにより、プロパティ シートで [適用] ボタンが有効になります。 ユーザーが後で [適用] または [キャンセル] ボタンをクリックした場合、ページはコントロールを再初期化し、PSM_UNCHANGED メッセージを送信して [適用] ボタンをもう一度無効にする必要があります。

[適用] ボタンをクリックすると、ページがプロパティ シートに変更を加え、変更を元に戻すことができない場合があります。 この場合、ページはプロパティ シートに PSM_CANCELTOCLOSE メッセージを送信する必要があります。 このメッセージにより、プロパティ シートで [OK] ボタンのテキストが [閉じる] に変更され、適用された変更を取り消すことができないことを示します。

場合によっては、変更を有効にする前に、Windows の再起動またはシステムの再起動が必要なシステム構成に変更が行われることがあります。 このような変更を行った後、ページは PSM_RESTARTWINDOWS または PSM_REBOOTSYSTEM メッセージをプロパティ シートに送信する必要があります。 これらのメッセージにより、プロパティ シートが破棄された後、PropertySheet 関数は ID_PSRESTARTWINDOWS または ID_PSREBOOTSYSTEM 値を返します。

ユーザーが [キャンセル] ボタンをクリックすると、プロパティ シートは PSN_RESET 通知コードをすべてのページに送信し、プロパティ シートが破棄されようとしていることを示します。 ページでは、通知を使用してクリーンアップ操作を実行する必要があります。

ウィザード

ウィザードは、プロパティ シートの特殊なタイプです。 ウィザードは、アプリケーションによって制御される順序でページを一度に 1 つずつ表示するように設計されています。 タブをクリックしてページのグループから選択する代わりに、ユーザーはボタンをクリックして順番を 1 ページずつ前後に移動します。 たとえば、次のスクリーン ショットは、[ハードウェアの追加] ウィザードのウェルカム ページを示しています。

screen shot of the welcome page of a wizard

次のスクリーン ショットは、Windows Vista で導入された新しいスタイルである Aero ウィザードの最初のページを示しています。

screen shot of the first page of an aero wizard

ウィザードの詳細については、「ウィザードの作成」を参照してください。