プロパティシート


アプリケーションの設定

ゲームのような特殊なソフトウェアを除いて、多くの Windows アプリケーションは
ソフトウェアの様々な設定を行うためのプロパティシートを使っています

プロパティシート

プロパティシートは、タブコントロールを応用した代表的な良い見本でしょう
タブを選択することによって、ダイアログのコントロールがダイナミックに変化します
これによって、少ないウィンドウ領域で複雑な設定用のコントロールを表示させられます

プロパティシートの実体は、複数の異なるダイアログコントロールから成り立っています
プロパティシートは、タブが選択されると適切なダイアログコントロールを表示するのです
ダイアログをウィンドウの内部に、どのように配置するかという問題は
全てプロパティシートが計算し、適切に表示してくれるため、非常に簡単に実装でき
私たちは、タブごとのダイアログのリソースと、プロシージャを作るだけなのです

プロパティシートを作成するためには、最初に個々のタブに相当するアイテムを作ります
プロパティシートにおけるタブに関連したダイアログをページと表現します
ページを作成するには CreatePropertySheetPage() 関数を使います

HPROPSHEETPAGE CreatePropertySheetPage(LPCPROPSHEETPAGE lppsp);

lppsp には、PROPSHEETPAGE 構造体へのポインタを指定します
この構造体には、作成するプロパティシートのページの情報を格納します
関数が成功すれば、新しいページのハンドルが、失敗すれば NULL が返ります

PROPSHEETPAGE 構造体は次のように定義されています
typedef struct _PROPSHEETPAGE {
    DWORD dwSize;
    DWORD dwFlags;
    HINSTANCE hInstance;
    union {
        LPCSTR pszTemplate;
        LPCDLGTEMPLATE pResource;
        };
    union {
        HICON hIcon;
        LPCSTR pszIcon;
        };
    LPCSTR pszTitle;
    DLGPROC pfnDlgProc;
    LPARAM lParam;
    LPFNPSPCALLBACK pfnCallback;
    UINT FAR * pcRefParent;

#if (_WIN32_IE >= 0x0400)
    LPCTSTR pszHeaderTitle;
    LPCTSTR pszHeaderSubTitle;
#endif
} PROPSHEETPAGE, FAR *LPPROPSHEETPAGE;
dwSize には、この構造体のサイズを指定します
dwFlags は、構造体のどのメンバを使用するかをフラグで指定します
このメンバには、以下の定数を組み合わせて指定することができます

定数解説
PSP_DEFAULT 構造体の全てのメンバに対し、デフォルト値を使用する
PSP_DLGINDIRECT プロパティシートの点プレーどがすでにメモリ内にあり
pResource メンバはそのメモリ位置を指している
この場合 pszTemplate メンバは無視される
PSP_HASHELP このページがアクティブになったら、「ヘルプ」ボタンを使用可能にする
PSP_RTLREADING テキストを右から左に向かって描画する
ヘブライ語、またはアラビア語で有効
PSP_USECALLBACK この構造体によって定義されたプロパティシートページが
作成、または削除される時 pfnCallback で指定された関数を呼び出す
PSP_USEHICON ページタブの小さなアイコンとして hIcon (ハンドル)を使用する
PSP_USEICONID ページタブの小さなアイコンとして pszIcon (リソース)を使用する
PSP_USEREFPARENT この構造体によって作成されるプロパティシートページのライフタイムの間
pcRefParent によって指定された参照カウントを管理する
PSP_USETITLE ダイアログのタイトルに pszTitle を使用する
デフォルトでは、ダイアログボックステンプレートのタイトルが使用される

hInstance には、ダイアログボックステンプレートなどのリソースが格納されている
モジュールのインスタンスハンドルを指定します

pszTemplate は、ページに使用するダイアログボックステンプレートの識別子を指定します
PSP_DLGINDIRECT フラグが設定されている場合は無視されます
pResource は、ロード済みのダイアログボックステンプレートへのポインタを指定します
< PSP_DLGINDIRECT フラグが設定されていなければ、このメンバは無視されます

hIcon はページのタブの小さなアイコンとして用いるアイコンのハンドルを指定します
PSP_USEICON フラグが設定されていなければ、このメンバは無視されます
pszIcon は、タブのアイコンをリソースから取得する場合に、識別子を指定します
PSP_USEICONID フラグが設定されていなければ、このメンバは無視されます

pszTitle は、ページのタイトルとなる文字列、またはリソース識別子を指定します
PSP_USETITLE フラグが設定されていなければ、このメンバは無視されます

pfnDlgProc は、ページダイアログのダイアログプロシージャへのポインタを指定します
これは、これまでのダイアログのプロシージャと同じように作って
ページに対するイベントを処理できますが
ページのダイアログプロシージャは、EndDialog() を呼び出してはなりません
lParam には、アプリケーション定義の追加情報を指定できます

pfnCallback には LPFNPSPCALLBACK 型の関数ポインタを指定します
このコールバック関数は、ページが作成されたり、破棄される時に呼び出されます
pcRefParent は参照カウントの値へのポインタを指定します
PSP_USERREFPARENT フラグが設定されていない場合、このメンバは無視されます

pfnCallback メンバに指定するコールバック関数は
一般的に PropSheetPageProc() と呼ばれる次のように定義された関数です
UINT CALLBACK PropSheetPageProc(
    HWND hwnd , UINT uMsg ,
    LPPROPSHEETPAGE ppsp
);
hwnd は予約されている引数です
uMsg には、関数が呼ばれた理由を示すアクションフラグを指定します
ここには、次のいずれかの定数が格納されています

定数解説
PSPCB_CREATE ページが作成されようとしている
ページを作成する場合は 0 以外、作成を拒否する場合は 0 を返す
PSPCB_RELEASE ページが破棄されようとしている
戻り値は無視される

ppsp は、ページの情報を格納した PROPSHEETPAGE 構造体へのポインタを指定します
関数の戻り値は、アクションによって異なります

CreatePropertySheetPage() 関数でページを作成するときは
同一のプロパティシートのページのハンドルは配列に保存しておきます
これは、プロパティシートにページを渡すとき、配列で一度に渡すためです

プロパティシートの作成には PropertySheet() 関数を用います
この関数は、プロパティシートを情報をもとに作成して表示します

int PropertySheet(LPCPROPSHEETHEADER lppsph);

lppsph には、PROPSHEETHEADER 構造体へのポインタを指定します
関数が成功すれば正数が、失敗した場合は -1 が返ります

プロパティシートはモーダルダイアログ、またはモードレスダイアログにもなるため
モードレスダイアログボックスの場合はウィンドウのハンドルが
モーダルダイアログボックスの場合は、以下のいずれかの値が返ります

定数解説
ID_PSREBOOTSYSTEM ページが PSM_REBOOTSYSTEM メッセージをプロパティシートに送信した
ユーザーが行った変更を有効にするには
コンピュータを再起動しなければならない
ID_PSRESTARTWINDOWS ページが PSM_RESTARTWINDOWS メッセージをプロパティシートに送信した
ユーザーが行った変更を有効にするには
コンピュータを再起動しなければならない

PROPSHEETHEADER 構造体は次のように定義されています
typedef struct _PROPSHEETHEADER {
    DWORD dwSize;
    DWORD dwFlags;
    HWND  hwndParent;
    HINSTANCE hInstance;
    union {
        HICON hIcon;
        LPCTSTR pszIcon;
        };
    LPCSTR pszCaption;
    UINT nPages;
    union {
        UINT nStartPage;
        LPCTSTR pStartPage;
        };
    union {
        LPCPROPSHEETPAGE ppsp;
        HPROPSHEETPAGE FAR *phpage;
        };
    PFNPROPSHEETCALLBACK pfnCallback;
} PROPSHEETHEADER, FAR *LPPROPSHEETHEADER;
dwSize は、この構造体のサイズを指定します
dwFlags には、この構造体の使用するメンバを表すフラグを指定します
このメンバには、以下の定数を組み合わせて指定することができます

定数解説
PSH_DEFAULT 全てのメンバに対してデフォルトの意味を使用する
PSH_HASHHELP プロパティシートの「ヘルプ」ボタンを表示する
PSH_MODELESS モードレスダイアログボックスのプロパティシートを作成する
PSH_MULTILINETABS 複数行表示のタブを使用する
PSH_MOAPPLYNOW 「更新」ボタンを削除する
PSH_PROPSHEETPAGE ページを作成する時 ppsp を使用する
このとき phppageは無視される
PSH_PROPTITLE pszCaption で指定された文字列を
プロパティシートのタイトルとして使用する
PSH_RTLREADING テキストを右から左方向に描画する
ヘブライ語、またはアラビア語に有効
PSH_USECALLBACK プロパティシートを初期化する時 pfnCallback で指定した関数を呼び出す
PSH_USEHICON プロパティシートダイアログボックスのアイコンとして hIcon (ハンドル)を用いる
PSH_USEICONID プロパティシートダイアログボックスのアイコンとして pszIcon (リソース)を用いる
PSH_USEPSTARTPAGE プロパティシートの初期ページに pStartPage を用いる
このとき nStartPage は無視される
PSH_WIZARD ウィザードプロパティシートを作成する

hwndParent には親ウィンドウのハンドルを指定します
hInstance は、リソースを含むモジュールのインスタンスハンドルを指定します
このメンバはリソースからアイコンなどを読み込む場合に指定しなければなりません

hIcon には、プロパティシートのタイトルバーに表示するアイコンのハンドルを指定します
PSH_USEHICON フラグが設定されていなければ、このメンバは無視されます
pszIcon は、タイトルバーに表示するアイコンのリソース識別子を指定します
PSH_USEICONID フラグが設定されていなければ、このメンバは無視されます

nPages には、phpage メンバが指す配列内にある要素の数を指定します
nStartPage は、プロパティシートを作成した時、初期時に表示するページ番号を指定します
PSH_USEPSTARTPAGE フラグが設定されている場合、このメンバは無視され
代わりに pStartPage メンバに初期時に表示するページの名前を指定します

ppsp には、プロパティシートの各ページを定義した
PROPSHEETPAGE 構造体の配列へのポインタを指定します
このメンバは、構造体から直接ページを作成するアプローチの時に使用します
PSH_PROPSHEETPAGE フラグが設定されていなければ、このメンバは無視されます

phpage には、各ページのハンドルの配列へのポインタを指定します
ppsp メンバを使用しない場合、こちらの方法でページを作成することになります
今回は、この phpage メンバを用いて作成する方法を採用します

pfnCallback は PFNPROPSHEETCALLBACK 型の関数ポインタを指定します
このコールバック関数は、プロパティシート初期化時に呼び出されます
これは、一般的に PropSheetProc() という名前で次のような型の関数です
int CALLBACK PropSheetProc(
    HWND hwndDlg , UINT uMsg ,
    LPARAM lParam
);
hwndDlg には、プロパティシートダイアログボックスのハンドルが
uMsg は、この関数が呼び出されたアクションを表すフラグが格納されています
通常、プロパティシートが作成されたことを表す PSCB_INITIALIZED フラグがセットされます
lParam は uMsg の追加情報を、戻り値は常に 0 を指定します
/*リソーススクリプト*/
PAGEICON ICON "test.ico"

KITTY DIALOG 0 , 0 , 150 , 70
FONT 16 , "MS Sans Serif"
CAPTION "Kitty's Page" {
	LTEXT "Kitty on your lap" , -1 , 2 , 0 , 70 , 10
}

TARUTO DIALOG 0 , 0 , 150 , 70
FONT 16 , "MS Sans Serif"
CAPTION "TARUTO's Page" {
	LTEXT "Magical nyan nyan TARUTO" , -1 , 2 , 0 , 100 , 10
}
#include <windows.h>
#include <commctrl.h>
#define TITLE TEXT("Kitty on your lap")

BOOL CALLBACK PageProc1(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	return FALSE;
}

BOOL CALLBACK PageProc2(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	return FALSE;
}

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	PROPSHEETPAGE psp;
	PROPSHEETHEADER psh;
	HPROPSHEETPAGE hPsp[2];

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		InitCommonControls();		
		return 0;
	case WM_RBUTTONUP:
		psp.dwSize = sizeof (PROPSHEETPAGE);
		psp.dwFlags = PSP_DEFAULT | PSP_USEICONID;
		psp.pszIcon = TEXT("PAGEICON");
		psp.hInstance = (HINSTANCE)GetWindowLong(hWnd , GWL_HINSTANCE);

		psp.pszTemplate = TEXT("KITTY");
		psp.pfnDlgProc = (DLGPROC)PageProc1;
		hPsp[0] = CreatePropertySheetPage(&psp);

		psp.pszTemplate = TEXT("TARUTO");
		psp.pfnDlgProc = (DLGPROC)PageProc2;
		hPsp[1] = CreatePropertySheetPage(&psp);

		psh.dwSize = sizeof (PROPSHEETHEADER);
		psh.dwFlags = PSH_DEFAULT | PSH_USEHICON;
		psh.hwndParent = hWnd;
		psh.hIcon = LoadIcon(NULL , IDI_ASTERISK);
		psh.pszCaption = TITLE;
		psh.nPages = 2;
		psh.phpage = hPsp;
		PropertySheet(&psh);
		return 0;
	}
	return DefWindowProc(hWnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hWnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hWnd = CreateWindow(
			TEXT("KITTY") , TITLE ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);
	if (hWnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


このプログラムは、ウィンドウのクライアント領域を右クリックすると
上の図のプロパティシートを作成し、表示します

タブをクリックして表示されるページは、実際は独立したダイアログです
プロパティシートのサイズなどは、すべて API が計算してくれるため
開発者は、目的のダイアログテンプレートとプロシージャを書くだけで良いのです

プロパティシートのページのハンドルは、削除する必要があります
実は、プロパティシートのダイアログが閉じられれば PropertySheet() 関数が
自動的にページのハンドルを削除してくれるため、上のプログラムは問題がありません

しかし、ページのハンドルを PropertySheet() 関数で使わなかった場合は
明示的に DestroyPropertySheetPage() で破棄しなければなりません

BOOL DestroyPropertySheetPage(HPROPSHEETPAGE hPSPage);

hPSPage には、プロパティシートページのハンドルを指定します
成功した場合は 0 以外、失敗した場合は 0 が返ります


設定の確定

ユーザーがプロパティシート内のコントロールに値を入力したとしても
その時点でデータが更新されるべきではありません

プロパティシートコントロールは、ユーザーが「OK」ボタン、または「更新」ボタンを押したときに
変更した内容を確定するべきであり、「キャンセル」ボタンが押されることも考慮して
それまでは、例えラジオボタン等が変更されても、即座に適応してはいけません

「OK」ボタンと「更新」ボタンの違いは、「更新」ボタンは押してもダイアログが閉じないことと
プロパティシートに変更が加えられない限り、「更新」ボタンは有効にならないという点です
では、どうやってプロパティシートに変更が加えられたことを通知すればよいのでしょうか

プロパティシートに変更が加えられた場合 PropSheet_Changed() マクロを使い
プロパティシートに変更が加えられたことを通知します
こうすれば、「更新」ボタンが有効になります

BOOL PropSheet_Changed(HWND hPropSheetDlg , HWND hwndPage);

hPropSheetDlg には、プロパティシートのハンドルを
hwndPage には、変更されたページのハンドルを指定します
戻り値は定義されていないため、無視します

ページのハンドルとは、すなわちページに用いられているダイアログのハンドルであり
プロパティシートのハンドルは、ページの親ウィンドウのハンドルと考えられるため
プロシージャから GetParent() 関数を用いて取得することができます

ユーザーが「OK」ボタン、または「更新」ボタンを押すと
ダイアログプロシージャに WM_NOTIFY メッセージが送信されます
この通知コードが PSN_APPLY であれば、ボタンが押されたことを意味します
通常、プロパティシートの設定情報が適応されるのはこの瞬間です

ただし、プロパティシートでアクティブなページは常に一つであり
アクティブでなくなってしまう時に設定しなければならないような情報だった場合
上記した条件に加え、他のページのタブがクリックされた時にも通知される必要があります
この場合は PSN_KILLACTIVE 通知コードを処理します
/*リソーススクリプト*/
PAGEICON ICON "test.ico"

KITTY DIALOG 0 , 0 , 150 , 70
FONT 12 , "MS Sans Serif"
CAPTION "Kitty's Page" {
	RADIOBUTTON "RENA" , 1 , 10 , 0 , 100 , 10
	RADIOBUTTON "YUKI" , 2 , 10 , 10 , 100 , 10
	RADIOBUTTON "MIMI" , 3 , 10 , 20 , 100 , 10
}
#include <windows.h>
#include <commctrl.h>
#define TITLE TEXT("Kitty on your lap")

BOOL CALLBACK PageProc1(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	switch (msg) {
	case WM_COMMAND:
		CheckRadioButton(hWnd , 1 , 3 , LOWORD(wp));
		PropSheet_Changed(GetParent(hWnd) , hWnd);
		return TRUE;
	case WM_NOTIFY:
		if (((NMHDR *)lp)->code == PSN_APPLY)
			MessageBox(hWnd , 
				TEXT("OK または更新ボタンを押しました") , TEXT("設定") , 0);
		return TRUE;
	}
	return FALSE;
}

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	PROPSHEETPAGE psp;
	PROPSHEETHEADER psh;

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		InitCommonControls();		
		return 0;
	case WM_RBUTTONUP:
		psp.dwSize = sizeof (PROPSHEETPAGE);
		psp.dwFlags = PSP_DEFAULT | PSP_USEICONID;
		psp.pszIcon = TEXT("PAGEICON");
		psp.hInstance = (HINSTANCE)GetWindowLong(hWnd , GWL_HINSTANCE);

		psp.pszTemplate = TEXT("KITTY");
		psp.pfnDlgProc = (DLGPROC)PageProc1;

		psh.dwSize = sizeof (PROPSHEETHEADER);
		psh.dwFlags = PSH_DEFAULT | PSH_USEHICON | PSH_PROPSHEETPAGE;
		psh.hwndParent = hWnd;
		psh.hIcon = LoadIcon(NULL , IDI_ASTERISK);
		psh.pszCaption = TITLE;
		psh.nPages = 1;
		psh.ppsp = &psp;
		PropertySheet(&psh);
		return 0;
	}
	return DefWindowProc(hWnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hWnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hWnd = CreateWindow(
			TEXT("KITTY") , TITLE ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);
	if (hWnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


このプログラムは、ウィンドウのクライアント領域を右クリックすると
上の図のようなプロパティシートが表示されます
因みに、プロパティシートページを CreatePropertySheetPage() 関数を使わずに
直接 PROPSHEETPAGE 構造体から作成している点にも注目してください

ラジオボタンを選択すると、プロシージャはそのボタンを有効にし
さらに PropSheet_Changed() マクロを使って更新ボタンを有効にしています
OK ボタンや更新ボタンが押されると、それを WM_NOTIFY で受けとって処理します


CreatePropertySheetPage()

HPROPSHEETPAGE CreatePropertySheetPage(LPCPROPSHEETPAGE lppsp);

プロパティシートページのハンドルを生成します

lppsp - PROPSHEETPAGE 構造体へのポインタを指定します

戻り値 - 新しいページのハンドル、失敗すれば NULL

PropSheetPageProc()

UINT CALLBACK PropSheetPageProc(
    HWND hwnd , UINT uMsg ,
    LPPROPSHEETPAGE ppsp
);
ページが作成、または破棄される時に呼び出される
アプリケーション定義のコールバック関数です

hwnd - 予約されている引数です
uMsg - 関数が呼ばれた理由を示すアクションフラグを指定します
ppsp - ページの情報を格納した PROPSHEETPAGE 構造体へのポインタを指定します

戻り値 - アクションによって異なる

uMsg には以下の定数を指定することができます

定数解説
PSPCB_CREATE ページが作成されようとしている
ページを作成する場合は 0 以外、作成を拒否する場合は 0 を返す
PSPCB_RELEASE ページが破棄されようとしている
戻り値は無視される

PropertySheet()

int PropertySheet(LPCPROPSHEETHEADER lppsph);

プロパティシートを作成して表示します

lppsph - PROPSHEETHEADER 構造体へのポインタを指定します

戻り値 - 成功すれば正数、失敗した場合は -1

成功時の戻り値は、モードレスダイアログボックスの場合はウィンドウのハンドル
モーダルダイアログボックスの場合は、以下のいずれかの値が返ります

定数解説
ID_PSREBOOTSYSTEM ページが PSM_REBOOTSYSTEM メッセージをプロパティシートに送信した
ユーザーが行った変更を有効にするには
コンピュータを再起動しなければならない
ID_PSRESTARTWINDOWS ページが PSM_RESTARTWINDOWS メッセージをプロパティシートに送信した
ユーザーが行った変更を有効にするには
コンピュータを再起動しなければならない

PropSheetProc()

int CALLBACK PropSheetProc(
    HWND hwndDlg , UINT uMsg ,
    LPARAM lParam
);
プロパティシートの初期化時に呼び出される
アプリケーション定義のコールバック関数です

hwndDlg - プロパティシートダイアログボックスのハンドルを指定します
uMsg - この関数が呼び出されたアクションを表すフラグを指定します
lParam - uMsg の追加情報を指定します

戻り値 - 常に 0

DestroyPropertySheetPage()

BOOL DestroyPropertySheetPage(HPROPSHEETPAGE hPSPage);

指定したページのハンドルを破棄します

hPSPage - プロパティシートページのハンドルを指定します

戻り値 - 成功した場合は 0 以外、失敗した場合は 0

PropSheet_Changed()

BOOL PropSheet_Changed(HWND hPropSheetDlg , HWND hwndPage);

プロパティシートに、変更が加えられたことを通知します

hPropSheetDlg - プロパティシートのハンドルを指定します
hwndPage - 変更されたページのハンドルを指定します

戻り値 - 定義されていない



前のページへ戻る次のページへ