レガシー Windows API(概要)について

ここで紹介しているAPIは、Windows95、Windows NT3.5時代のAPI群であり、最新のAPIは含まれていないことに注しして欲しい。なお、当時の解説書は現在よりもより詳細に解説しているため、参考になるはずである。

  • レイアウトを変換する際、崩れているページがあります。
  • 概要およびSampleコードはありますが、APIの解説はありません。

ご要望があれば旧版のWin32 API(HELP形式)をお譲りします。問い合わせフォームより申し込みください。

Windows API コモン ダイアログ ボックス ライブラリの概要

コモン ダイアログ ボックスによって、 Microsoft(R) Win32(R) アプリケーション プログラミング インターフェイス (API) を使ったアプリケーションの開発が容易になります。「コモン ダイアログ ボックス」とは、 ダイアログ ボックス プロシージャとダイアログ ボックス テンプレートを含むリソース ファイルを供給せずに、 関数を1つ呼び出すだけで表示できるダイアログ ボックスです。ダイナミック リンク ライブラリのCOMDLG32.DLLは、 各種のコモン ダイアログ ボックスのデフォルトのプロシージャとテンプレートを提供します。各デフォルトダイアログ ボックス プロシージャは、 コモン ダイアログ ボックスとそのコントロールのメッセージや通知を処理します。デフォルトのダイアログ ボックス テンプレートは、 コモン ダイアログ ボックスとそのコントロールの外観を定義します。

次に示すトピックでは、 Win32のコモン ダイアログ ボックスについて説明しています。

[色の設定]ダイアログ ボックス

[フォントの指定]ダイアログ ボックス

[ファイルを開く]ダイアログ ボックスと[ファイル名を付けて保存]ダイアログ ボックス

[印刷]ダイアログ ボックスと[プリンタの設定]ダイアログ ボックス

[文字列の検索]ダイアログ ボックスと[文字列の置換]ダイアログ ボックス

必要なスタック サイズの設定

[色の設定]ダイアログ ボックスによる基本色の表示

[色の設定]ダイアログ ボックスによるカスタム カラーの表示

[フォントの指定]ダイアログ ボックスの表示

[ファイルを開く]ダイアログ ボックスの表示

[ファイル名を付けて保存]ダイアログ ボックスの表示

[ファイルを開く]ダイアログ ボックスや[ファイル名を付けて保存]ダイアログ ボックスのリスト ボックス コントロールの監視

[ファイルを開く]ダイアログ ボックスや[ファイル名を付けて保存]ダイアログ ボックスのファイル名の監視

デフォルト プリンタの[印刷]ダイアログ ボックスの表示

[文字列の検索]ダイアログ ボックスの表示

[文字列の置換]ダイアログ ボックスの表示

[文字列の検索]ダイアログ ボックスや[文字列の置換]ダイアログ ボックスのダイアログ メッセージの処理

コモン ダイアログ ボックスのカスタマイズ

適切なカスタマイズと不適切なカスタマイズ

フック関数とカスタム ダイアログ ボックス テンプレート

カスタム ダイアログ ボックスの表示

コモン ダイアログ ボックスのヘルプのサポートと処理

エラーの検出

コモン ダイアログ ボックス関数

コモン ダイアログ ボックスによって、 Win32ベースのアプリケーションの開発が容易になるほかに、 特定の作業を行う場合の標準的な操作方法が確立されるため、 ユーザーにも利点があります。Windowsアプリケーションでコモン ダイアログ ボックスを使用することによって、 あるアプリケーションでコモン ダイアログ ボックスの使い方を習得したユーザーが、 ほかのアプリケーションでも同じ作業を簡単に実行できるようになります。

このトピックでは、 さまざまなコモン ダイアログ ボックスについて説明し、 Win32ベースのアプリケーションでコモン ダイアログ ボックスを使用するためのコード例を示します。

各種のコモン ダイアログ ボックスを、 このトピックで説明する順番で次の表に示します。

名前 説明

[色の設定] 利用可能な色と、 ユーザーがカスタム カラーを定義するためのコントロールを表示します。

[フォントの指定] 利用可能なフォントとそのポイント サイズのリストを表示します。ユーザーがフォントを選択すると、 ダイアログ ボックスは、 そのフォントでサンプル テキストを表示します。

[ファイルを開く] 指定された拡張子、 ディレクトリ、 ドライブに一致するファイル名のリストを表示します。ユーザーは、 リストされているファイル名のいずれかを選択して、 アプリケーションがオープンすべきファイルを指定します。

[ファイル名を付けて保存] 指定された拡張子、 ディレクトリ、 ドライブに一致するファイル名のリストを表示します。ユーザーは、 リストされているファイル名のいずれかを選択して、 アプリケーションが保存すべきファイルを指定します。

[印刷] インストールされているプリンタとその設定に関する情報を表示します。ユーザーは、 このダイアログ ボックスのコントロールを変更したり選択することによって、 出力の印刷方法を指定し、 印刷処理を開始できます。

[プリンタの設定] 現在のプリンタ設定を表示し、 用紙の方向、 サイズ、 供給源などを (プリンタ ドライバがサポートしていれば) を設定するためのオプションを提供します。[プリンタの設定]ダイアログ ボックスは、 アプリケーションから直接呼び出されるか、 [印刷]ダイアログ ボックスからオープンされます。

[文字列の検索] アプリケーションが検索すべき文字列をユーザーが入力するためのエディット コントロールを表示します。ユーザーは、 検索方向や、 指定した文字列の大文字と小文字を区別するかどうか、 一致の条件を単語全体だけに限定するかどうかを指定できます。

[文字列の置換] ユーザーが文字列を入力できる2つのエディット コントロールを表示します。1つ目の文字列は置換される単語や値を指定し、 2つ目の文字列は新しい単語や値を指定します。

[色の設定]ダイアログ ボックス

[色の設定]ダイアログ ボックスには、 ユーザーが色を選択したり作成するためのコントロールがあります。

[色の設定]ダイアログ ボックスを次に示します。

[基本色]コントロールには、 最大48色が表示されます。実際に表示される色の個数は、 ディスプレイ ドライバによって異なります。たとえば、 VGAドライバは48色を表示しますが、 モノクロ ディスプレイ ドライバは16色しか表示しません。ユーザーは、 [基本色]コントロールによって、 表示されている色を選択できます。

[作成した色]コントロールを表示するには、 [色の作成]ボタンをクリックします。[作成した色]コントロールは、 カスタム カラーを表示します。このコントロールでは、 16個の長方形の内のいずれかを選択して、 次に示す方法のいずれかを使って新しい色を作成できます。

[赤][緑][青]の各エディット コントロールを使って赤、 緑、 青 (RGB) の値を指定してから、 [追加]ボタンを選択して、 新しい色を選択されている長方形に表示します。

・ (ダイアログ ボックスの右上の) カラー スペクトル コントロールのポインタを移動して、 色合いと鮮やかさの値を選択します。明るさコントロール (スペクトル コントロールの右側の長方形) のポインタを移動して明るさを設定します。それから、 [追加]ボタンを選択して、 新しい色を選択されている長方形に表示します。

[色合い][鮮やかさ][明るさ]の各エディット コントロールを使って色合い、 鮮やかさ、 明るさ (HSL) の値を指定してから、 [追加]ボタンを選択して、 新しい色を選択されている長方形に表示します。

[色|純色]コントロールは、 ユーザーの選択に対応するディザ カラーと純色を表示します (ディザ カラーとは、 1つ以上の純色を組み合わせて作成された色です)。CHOOSECOLOR構造体のFlagsメンバには、 [ヘルプ]ボタンを表示するかどうかを示すフラグ ビットがあります。このビットが設定されているときは、 [ヘルプ]ボタンが表示されます。

[色の設定]ダイアログ ボックスは、 完全オープンと部分オープンの2つの方法で表示できます。[色の設定]ダイアログ ボックスを部分オープン表示しているときは、 ユーザーはカスタム カラーを変更できません。

[色の設定]ダイアログ ボックスで使われるカラー モデル

[色の設定]ダイアログ ボックスでは、 色を指定するのにRGBモデルとHSLモデルを使用します。使用されているモデルにかかわらず、 内部的な記憶はRGBモデルで行われます。

RGBカラー モデル

RGBモデルは、 ディスプレイなどの発光デバイスの色を指定するために使われます。赤、 緑、 青の値の有効範囲は0から255までで、 0は最小輝度、 255は最大輝度を示します。次の図は、 原色の赤、 緑、 青を組み合わせてほかの4つの色を生成する方法を示しています (ディスプレイ デバイスでは、 赤、 緑、 青の値をすべて0にすると黒になります。ディスプレイの場合、 黒は色がまったくない状態です)。

8つの色と対応するRGB値を次に示します。

 

RGB値

赤 255, 0, 0

緑 0, 255, 0

青 0, 0, 255

シアン 0, 255, 255

マゼンタ 255, 0, 255

黄 255, 255, 0

白 255, 255, 255

黒 0, 0, 0

 

Windowsは、 色を内部的には32ビットのRGB値として格納しています。上位ワードの上位バイトは予約されています。上位ワードの下位バイトは、 青要素の輝度を示します。下位ワードの上位バイトは、 緑要素の輝度を示します。下位ワードの下位バイトは、 赤要素の輝度を示します。

HSLカラー モデル

[色の設定]ダイアログ ボックスには、 HSL値を指定するためのコントロールもあります。次の図は、 カラー スペクトル コントロールと、 縦の明るさコントロールを示しています。これらのコントロールは[色の設定]ダイアログ ボックスに表示され、 ユーザーが指定可能な値の範囲を示しています。

[色の設定]ダイアログ ボックスでは、 鮮やかさと明るさの値は0から240まででなければならず、 色合いの値は0から239まででなければなりません。

HSL値からRGB値への変換

COMDLG32.DLLで提供されている[色の設定]ダイアログ ボックスのダイアログ ボックス プロシージャには、 HSL値を対応するRGB値に変換するコードがあります。いくつかの色のHSL値とRGB値を次に示します。

HSL値 RGB値

赤 (0, 240, 120) (255, 0, 0)

黄 (40, 240, 120) (255, 255, 0)

緑 (80, 240, 120) (0, 255, 0)

シアン (120, 240, 120) (0, 255, 255)

青 (160, 240, 120) (0, 0, 255)

マゼンタ (200, 240, 120) (255, 0, 255)

白 (0, 0, 240) (255, 255, 255)

黒 (0, 0, 0) (0, 0, 0)

 

[フォントの指定]ダイアログ ボックス

[フォントの指定]ダイアログ ボックスには、 フォント、 フォント スタイル (太字、 斜体、 標準など)、 ポイント サイズ、 効果 (下線、 打ち消し線)、 テキストの色などをユーザーが選択できるようにするためのコントロールがあります。

[フォントの指定]ダイアログ ボックスを次に示します。

 

[ファイルを開く]ダイアログ ボックスと[ファイル名を付けて保存]ダイアログ ボックス

[ファイルを開く]ダイアログ ボックスと[ファイル名を付けて保存]ダイアログ ボックスの外観はよく似ています。各ダイアログ ボックスには、 ファイルの位置 (ドライブとディレクトリ) と名前をユーザーが指定できるようにするためのコントロールがあります。[ファイルを開く]ダイアログ ボックスの場合は、 オープンするファイルを選択します。[ファイル名を付けて保存]ダイアログ ボックスの場合は、 保存するファイルを選択します。

[ファイルを開く]ダイアログ ボックスを次に示します。

[印刷]ダイアログ ボックスと[プリンタの設定]ダイアログ ボックス

[印刷]ダイアログ ボックスには、 ユーザーが特定の印刷ジョブ用にプリンタを設定できるようにするためのコントロールがあります。このダイアログ ボックスでは、 印刷の品質、 印刷範囲、 部数 (プリンタが複数の部数をサポートしている場合) などを選択できます。

[印刷]ダイアログ ボックスの[プリンタの設定]ボタンを選択すると、 特定のプリンタに関する[プリンタの設定]ダイアログ ボックスが表示されます。[プリンタの設定]ダイアログ ボックスには、 選択されているプリンタを再設定するためのコントロールがあります。

デバイス ドライバと[印刷]ダイアログ ボックス

[印刷]ダイアログ ボックスは、 ほかのコモン ダイアログ ボックスとは異なり、 ダイアログ ボックス プロシージャがCOMDLG32.DLLとプリンタ ドライバにわかれて存在しています。プリンタ ドライバとは、 プリンタの設定、 グラフィック デバイス インターフェイス (GDI) コマンドから低レベルのプリンタ コマンドへの変換、 特定の印刷ジョブのコマンドのプリンタ キューへの格納などを行うプログラムです。

プリンタ ドライバは、 ダイアログ ボックスとそのコントロールを表示するExtDeviceModeという関数をエクスポートします。以前のバージョンのWindowsでは、 アプリケーションはLoadLibrary関数を呼び出してデバイス ドライバをロードし、 GetProcAddress関数を呼び出してExtDeviceMode関数のアドレスを取得していました。Win32コモン ダイアログ ボックス インターフェイスではこのような処理は不要です。Win32ベースのアプリケーションは、 LoadLibraryGetProcAddressを呼び出さずに、 PrintDlg関数を呼び出すだけで、 [印刷]ダイアログ ボックスを表示して印刷ジョブを開始できます。PrintDlgのコードはCOMDLG32.DLLにあります。アプリケーションがPrintDlgを呼び出したときに表示されるダイアログ ボックスは、 アプリケーションがデバイス ドライバを直接呼び出したときに表示されるダイアログ ボックスとは少し異なります。外観は異なりますが、 機能は非常によく似ています。

[文字列の検索]ダイアログ ボックスと[文字列の置換]ダイアログ ボックス

[文字列の検索]ダイアログ ボックスと[文字列の置換]ダイアログ ボックスの外観はよく似ています。文字列検索機能をアプリケーションに付加するには[文字列の検索]ダイアログ ボックスを、 文字列検索と文字列置換の両方の機能を付加するには、 [文字列の置換]ダイアログ ボックスを使ってください。

[文字列の検索]ダイアログ ボックスと[文字列の置換]ダイアログ ボックスは、 ほかのコモン ダイアログ ボックスとは異なり、 モードレスです。つまり、 ダイアログ ボックスと、 そのダイアログ ボックスを作成したウィンドウとを切り替えることができます。

コモン ダイアログ ボックスの使用

各処理の実行方法を知るには、 次の一覧から必要な処理をクリックしてください。

必要なスタック サイズの設定

[色の設定]ダイアログ ボックスによる基本色の選択

[色の設定]ダイアログ ボックスによるカスタム カラーの選択

[フォントの指定]ダイアログ ボックスによるフォント、 ポイント サイズ、 テキストの色の選択

[ファイルを開く]ダイアログ ボックスによるファイルの選択

[ファイル名を付けて保存]ダイアログ ボックスによるファイル名の選択

[印刷]ダイアログ ボックスの表示による印刷前のプリンタ設定

[文字列の検索]ダイアログ ボックスによる検索文字列の指定

[文字列の置換]ダイアログ ボックスによる検索文字列と置換文字列の指定

コモン ダイアログ ボックスのカスタマイズ

必要なスタック サイズの設定

コモン ダイアログ ボックスを使用するアプリケーションのスタック サイズには、 次の例に示すように、 8Kバイト以上を指定してください。

NAME Generic

DESCRIPTION 'Sample Application for Microsoft Windows'

EXETYPE WINDOWS

STUB 'WINSTUB.EXE'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 8192 ; increased stack size for common dialog boxes

EXPORTS
MainWndProc @1
About @2

[色の設定]ダイアログ ボックスによる基本色の表示

基本画面色のリストから色を1つユーザーに選択させるには、 [色の設定]ダイアログ ボックスを表示します。ここでは、 [色の設定]ダイアログ ボックスを表示するためのコードと構造体をアプリケーションで使う方法について説明します。

CHOOSECOLOR構造体の初期化

[色の設定]ダイアログ ボックスを表示する前に、 CHOOSECOLOR構造体を初期化しなければなりません。この構造体は、 グローバルにするか、 static変数として宣言してください。この構造体のメンバは、 次に示す項目に関する情報を示します。

・ 構造体のサイズ

・ ダイアログ ボックスを所有しているウィンドウ

・ アプリケーションがコモン ダイアログ ボックスをカスタマイズしているかどうか

・ カスタマイズした[色の設定]ダイアログ ボックスで使われるフック関数とカスタム ダイアログ ボックス テンプレート

・ 選択されている基本色のRGB値

ダイアログ ボックスをカスタマイズせず、 基本色から色を1つ選択できるようにするときは、 次のようにCHOOSECOLOR構造体を初期化してください。

/* Color variables */

CHOOSECOLOR cc; /* common dialog box structure */
COLORREF acrCustClr[16] = { RGB(255, 255, 255), RGB(239, 239, 239),
RGB(223, 223, 223), RGB(207, 207, 207),
RGB(191, 191, 191), RGB(175, 175, 175),
RGB(159, 159, 159), RGB(143, 143, 143),
RGB(127, 127, 127), RGB(111, 111, 111),
RGB(95, 95, 95), RGB(79, 79, 79),
RGB(63, 63, 63), RGB(47, 47, 47),
RGB(31, 31, 31), RGB(15, 15, 15)
}; /* array of gray colors */

/* Initialize necessary members. */

cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.lpCustColors = (LPDWORD) acrCustClr;
cc.Flags = CC_PREVENTFULLOPEN;

/* Call the ChooseColor function. */

if (ChooseColor(&cc)){
.
. /* Use cc.lpCustColors to select the user's requested color. */
.
}

上記の例では、 lpCustColorsメンバが指す配列は、 灰色を示す16個のダブルワードRGB値を含んでいます。また、 [色の作成]ボタンを使用不能にしてユーザーがカスタム カラーを選択できないようにするため、 FlagsメンバにCC_PREVENTFULLOPENフラグをセットしています。

ChooseColor関数の呼び出し

構造体を初期化したら、 ChooseColor関数を呼び出します。ユーザーが[OK]ボタンを選択してダイアログ ボックスをクローズし、 関数が正常に終了したときは、 ユーザーが選択した基本色のRGB値がCHOOSECOLOR構造体のrgbResultメンバに設定されています。

[色の設定]ダイアログ ボックスによるカスタム カラーの表示

ユーザーがカスタム カラーを作成して選択できるようにするには、 [色の設定]ダイアログ ボックスを表示します。「CHOOSECOLOR構造体の初期化」と「ChooseColor関数の呼び出し」では、 [色の設定]ダイアログ ボックスを表示するためのコードと構造体をアプリケーションで使う方法について説明します。

CHOOSECOLOR構造体の初期化

[色の設定]ダイアログ ボックスを表示する前に、 CHOOSECOLOR構造体を初期化しなければなりません。この構造体は、 グローバルにするか、 static変数として宣言してください。この構造体のメンバは、 次に示す項目に関する情報を示します。

・ 構造体のサイズ

・ ダイアログ ボックスを所有しているウィンドウ

・ アプリケーションがコモン ダイアログ ボックスをカスタマイズしているかどうか

・ カスタマイズした[色の設定]ダイアログ ボックスで使われるフック関数とカスタム ダイアログ ボックス テンプレート

・ カスタム カラー コントロールのRGB値

ダイアログ ボックスをカスタマイズせず、 カスタム カラーを作成して選択できるようにするときは、 次のようにCHOOSECOLOR構造体を初期化してください。

/* Color variables */

CHOOSECOLOR cc; /* common dialog box structure */
COLORREF acrCustClr[16] = { RGB(255, 255, 255), RGB(239, 239, 239),
RGB(223, 223, 223), RGB(207, 207, 207),
RGB(191, 191, 191), RGB(175, 175, 175),
RGB(159, 159, 159), RGB(143, 143, 143),
RGB(127, 127, 127), RGB(111, 111, 111),
RGB(95, 95, 95), RGB(79, 79, 79),
RGB(63, 63, 63), RGB(47, 47, 47),
RGB(31, 31, 31), RGB(15, 15, 15)
}; /* array of gray colors */

/* Initialize the necessary members. */

cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.lpCustColors = (LPDWORD) acrCustClr;
cc.Flags = CC_FULLOPEN;

上記の例では、 lpCustColorsが指す配列は、 16階調の灰色を示す16個の32ビットRGB値を含んでいます。また、 完全な[色の設定]ダイアログ ボックスを表示するため、 FlagsメンバにCC_FULLOPENフラグをセットしています。

ChooseColor関数の呼び出し

構造体を初期化したら、 ChooseColorを呼び出してください。ユーザーが[OK]ボタンを選択してダイアログ ボックスをクローズし、 関数が正常に終了したときは、 lpCustColorsメンバが指す配列に、 ユーザーが要求したカスタム カラーのRGB値が設定されています。

COLOROKSTRING定数で定義されている文字列の新しいメッセージ識別子を作成することによって、 カスタム カラーをより詳細に制御できます。新しいメッセージ識別子を作成するには、 この値をパラメータに指定してRegisterWindowMessage関数を呼び出します。RegisterWindowMessageを呼び出すと、 アプリケーションは、 ダイアログ ボックスがクローズする直前にメッセージを受け取ります。このメッセージのlParamパラメータは、 CHOOSECOLOR構造体を指すポインタです。この構造体のlpCustColorsメンバを使って現在の色をチェックできます。アプリケーションがこのメッセージを処理したときに0以外の値を返すと、 ダイアログ ボックスはクローズしません。

同様に、 SETRGBSTRING値で定義されている文字列の新しいメッセージ識別子を作成できます。アプリケーションのフック関数は、 SETRGBSTRING値を指定して呼び出したRegisterWindowMessage関数が返したメッセージ識別子を使って、 ダイアログ ボックスに色を設定できます。たとえば、 次に示すコードは、 色の選択を青に設定します。

SendMessage(hwndDlg, wSetRGBMsg, 0, (LPARAM) RGB(0, 0, 255));

上記の例では、 wSetRGBMsgはRegisterWindowMessageが返したメッセージ識別子です。SendMessage関数のlParamパラメータには、 設定する色のRGB値を指定します。wParamパラメータは使いません。

上記のようにSendMessageを呼び出すときは、 任意の有効なRGB値を指定できます。RGB値が基本色のいずれかに一致するときは、 オペレーティング システムはその基本色を選択し、 スペクトル コントロールと明るさコントロールを更新しますが、 基本色の選択は変更しません。

[色の設定]ダイアログ ボックスが完全オープンされていないときに、 基本色に一致しないRGB値をアプリケーションが送ると、 オペレーティング システムはダイアログ ボックスを更新しません。ダイアログ ボックスが部分的にオープンされているときは、 スペクトル コントロールや明るさコントロールは表示されていないため、 更新は不要です。

登録ウィンドウ メッセージの処理について詳しくは、 [文字列の検索]ダイアログ ボックスの表示を参照してください。

[フォントの指定]ダイアログ ボックスの表示

[フォントの指定]ダイアログ ボックスは、 CHOOSEFONT構造体のメンバを初期化してChooseFont関数を呼び出すと表示されます。この構造体は、 グローバルにするか、 static変数として宣言してください。CHOOSEFONT構造体のメンバは、 次に示す項目に関する情報を示します。

・ ダイアログ ボックスに最初に表示されるフォントの属性

・ ユーザーが選択したフォントの属性

・ ユーザーが選択したフォントのポイント サイズ

・ フォントのリストがプリンタ、 画面、 またはその両方のどれに対応しているか

・ リストされている利用可能フォントがTrueTypeのみかどうか

・ ダイアログ ボックスに[文字飾り]ボックスを表示するかどうか

・ アプリケーション定義のフック関数でダイアログ ボックス メッセージを処理するかどうか

・ 選択可能なフォントのポイント サイズを指定した範囲に限定するかどうか

・ ダイアログ ボックスにWYSIWYGフォントだけを表示するかどうか (WYSIWYGフォントとは、 画面とプリンタの両方にあるフォントのことです)

・ アプリケーションが最初にダイアログ ボックスを表示するときにChooseFont[サンプル]ボックスにテキストを表示するのに使う色

・ ユーザーが選択した色

[フォントの指定]ダイアログ ボックスを表示するには、 次に示す手順に従ってください。

1. プリンタ フォントが必要ならば、 プリンタのデバイス コンテキスト (DC) を取得して、 そのハンドルをCHOOSEFONT構造体のhDCメンバに設定します。[フォントの指定]ダイアログ ボックスに画面フォントだけを表示するときは、 このメンバにはNULLを設定してください。

2. CHOOSEFONT構造体のFlagsメンバに適切なフラグを設定します。CF_SCREENFONTSCF_PRINTERFONTSCF_BOTHのいずれかは必ず指定してください。

3. デフォルトの色 (黒) を使わないときは、 CHOOSEFONT構造体のrgbColorsメンバに適切な色を設定してください。

4. CHOOSEFONT構造体のnFontTypeメンバに適切な定数を設定します。

5. FlagsメンバにCF_LIMITSIZEを指定したときは、 CHOOSEFONT構造体のnSizeMinメンバとnSizeMaxメンバを設定します。

6. ChooseFont関数を呼び出します。

次に示す例は、 CHOOSEFONT構造体を初期化してChooseFontを呼び出し、 指定されたフォントを使ってディスプレイにテキストを描画します。

/* Font variables */

CHOOSEFONT cf; /* common dialog box structure */
LOGFONT lf; /* logical-font structure */
HDC hdc; /* display DC handle */
HFONT hfont; /* new logical-font handle */
HFONT hfontOld; /* original logical-font handle */
COLORREF crOld; /* original text color */

/* Initialize the necessary members. */

cf.lStructSize = sizeof (CHOOSEFONT);
cf.hwndOwner = hwnd;
cf.lpLogFont = &lf;
cf.Flags = CF_SCREENFONTS | CF_EFFECTS;
cf.rgbColors = RGB(0, 255, 255);
cf.nFontType = SCREEN_FONTTYPE;

/*
* Display the dialog box, allow the user to
* choose a font, and render the text in the
* window with that selection.
*/

if (ChooseFont(&cf)){
hdc = GetDC(hwnd);
hfont = CreateFontIndirect(cf.lpLogFont);
hfontOld = SelectObject(hdc, hfont);
crOld = SetTextColor(hdc, cf.rgbColors);
TextOut(hdc, 50, 150,
"AaBbCcDdEeFfGgHh", 16);
SetTextColor(hdc, crOld);
SelectObject(hdc, hfontOld);
DeleteObject(hfont);
ReleaseDC(hwnd, hdc);
}

また、 ユーザーが[フォントの指定]ダイアログ ボックスをクローズする前にダイアログ ボックスの現在のLOGFONT構造体を取得するには、 WM_CHOOSEFONT_GETLOGFONTメッセージを使ってください。

[ファイルを開く]ダイアログ ボックスの表示

[ファイルを開く]ダイアログ ボックスは、 OPENFILENAME構造体のメンバを初期化してGetOpenFileName関数を呼び出すと表示されます。

GetOpenFileNameを呼び出す前に、 ダイアログ ボックスに表示されるディレクトリ名やフィルタを構造体のメンバに設定してください (フィルタとは、 ファイル名拡張子のことです。コモン ダイアログ ボックスのコードは、 拡張子を使って、 ディレクトリから適切なファイル名を抜き出します)。GetOpenFileNameは、 選択されたファイルの名前やそのファイル名などのデータを構造体のメンバに返します。

[ファイルを開く]ダイアログ ボックスを表示するには、 次に示す手順に従ってください。

1. 有効なフィルタを文字配列に格納します。

2. その配列を指すポインタをlpstrFilterメンバに設定します。

3. デフォルト フィルタを識別するインデックスの値をnFilterIndexメンバに設定します。

4. 初期ファイル名が設定されている配列を指すポインタをlpstrFileメンバに設定します。この配列には、 選択されたファイル名が返されます。

5. ファイル名配列の長さを示す値をnMaxFileメンバに設定します。

6. 選択されたファイルのタイトルが返されるバッファを指すポインタをlpstrFileTitleメンバに設定します。

7. タイトル バッファの長さを示す値をnMaxFileTitleメンバに設定します。

8. 初期ディレクトリを示す文字列を指すポインタをlpstrInitialDirメンバに設定します (有効な文字列を指すポインタをこのメンバに指定しないときは、 このメンバには0またはNULL文字列を指すポインタを指定しなければなりません)。

9. ダイアログ ボックスのタイトル バーに表示される名前を示す文字列を指すポインタをlpstrTitleメンバに設定します (このポインタにNULLを指定すると、 デフォルトのタイトルは[ファイルを開く]になります)。

10. デフォルトの拡張子を指すポインタをlpstrDefExtメンバに設定します (この拡張子の長さは、 0から3文字です)。

11. GetOpenFileName関数を呼び出します。

次に示す例は、 OPENFILENAME構造体を初期化してGetOpenFileNameを呼び出し、 構造体のlpstrFileメンバを使ってファイルをオープンします。OPENFILENAME構造体は、 グローバルにするか、 static変数として宣言してください。

OPENFILENAME ofn; /* common dialog box structure */
char szDirName[256]; /* directory string */
char szFile[256]; /* filename string */
char szFileTitle[256]; /* file-title string */
char szFilter[256]; /* filter string */
char chReplace; /* string separator for szFilter */
int i, cbString; /* integer count variables */
HANDLE hf; /* file handle */
.
.
/*
* Retrieve the system directory name and
* store it in szDirName.
*/

GetSystemDirectory(szDirName, sizeof(szDirName));

/* Place the terminating null character in the szFile. */

szFile[0] = '\0';

/* Load the filter string from the .RC file. */

cbString = LoadString(hinst, IDS_FILTERSTRING,
szFilter, sizeof(szFilter));

/*
* Add a terminating null character to the filter string.
*/

chReplace = szFilter[cbString - 1];

for (i = 0; szFilter[i] != '\0'; i++){
if (szFilter[i] == chReplace)
szFilter[i] = '\0';
}

/* Set the members of the OPENFILENAMEstructure. */

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = szDirName;
ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST |
OFN_FILEMUSTEXIST;

/* Display the Open dialog box. */

if (GetOpenFileName(&ofn)) {

/* Open the file. */

hf = CreateFile(ofn.lpstrFile, GENERIC_READ,
0, (LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);

.. /* Perform the necessary file operations. */
.

/* Close the file. */

CloseHandle(hf);

} /* end if */

上記の例でIDS_FILTERSTRING値で参照される文字列は、 リソース定義ファイルで次のように定義されています。

STRINGTABLE

BEGIN
IDS_FILTERSTRING "Bitmap File(*.BMP)|*.bmp|"
END
この文字列の縦棒は、 区切り文字として使われています。LoadString関数を使って文字列を取得すると、 区切り文字はNULLで置き換えられます。区切り文字には任意の文字を使うことができますが、 文字列の最後の文字としても指定しなければなりません。このように文字列を設定することによって、 文字列の各部分がメモリ内で連続して配置され、 文字列の最後は2つのNULL文字で終わるようになります。

ネットワーク上のファイルをオープンするアプリケーションは、 SHAREVISTRING値で定義されている文字列の新しいメッセージ識別子を作成してください。新しいメッセージ識別子を作成するには、 この値をパラメータに指定してRegisterWindowMessage関数を呼び出してください。RegisterWindowMessageを呼び出すと、 OpenFile関数の呼び出し中に共有違反が発生するたびにアプリケーションに通知が送られます。登録ウィンドウ メッセージの処理について詳しくは、 [文字列の検索]ダイアログ ボックスの表示を参照してください。

[ファイル名を付けて保存]ダイアログ ボックスの表示

[ファイル名を付けて保存]ダイアログ ボックスは、 OPENFILENAME構造体を初期化してGetSaveFileName関数を呼び出すと表示されます。

GetSaveFileNameを呼び出す前に、 初期ディレクトリの名前やフィルタ文字列などのデータを構造体のメンバに設定してください。この関数は、 保存するファイルの名前やそのファイル名の文字数などのデータを構造体のメンバに返します。

次に示す例は、 OPENFILENAME構造体を初期化してGetSaveFileNameを呼び出し、 ファイルを保存します。OPENFILENAME構造体はグローバルにするか、 static変数として宣言してください。

OPENFILENAME ofn; /* common dialog box structure */
char szDirName[256]; /* directory string */
char szFile[256]; /* filename string */
char szFileTitle[256]; /* file-title string */
char szFilter[256]; /* filter string */
char chReplace; /* string separator for szFilter */
int i, cbString; /* integer count variables */
HANDLE hf; /* file handle */

/*
* Retrieve the system directory name and
* store it in szDirName.
*/

GetSystemDirectory(szDirName, sizeof(szDirName));

/* Place the terminating null character in szFile. */

szFile[0] = '\0';

/* Load the filter string from the .RC file. */

cbString = LoadString(hinst, IDS_FILTERSTRING,
szFilter, sizeof(szFilter));

/*
* Add a terminating null character to the filter string.
*/

chReplace = szFilter[cbString - 1];

for (i = 0; szFilter[i] != '\0'; i++){
if (szFilter[i] == chReplace)
szFilter[i] = '\0';
}

/* Set the members of the OPENFILENAMEstructure. */

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = szDirName;
ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;

/* Display the Save As dialog box. */

if (GetSaveFileName(&ofn)) {

.
. /* Perform the necessary file operations. */
.

/* Close the file. */

CloseHandle(hf);

} /* end if */

上記の例でIDS_FILTERSTRING値で参照される文字列は、 リソース定義ファイルで定義されています。この値は、 [ファイルを開く]ダイアログ ボックスの表示のIDS_FILTERSTRING値とまったく同様に使われています。

[ファイルを開く]ダイアログ ボックスや[ファイル名を付けて保存]ダイアログ ボックスのリスト ボックス コントロールの監視

アプリケーションは、 リスト ボックスの選択を監視して、 カスタム コントロールにデータを処理および表示することができます。たとえば、 [ファイル名]ボックスで選択されているファイルの総バイト数をカスタム コントロールに表示することができます。この値は、 ユーザーがファイルを選択したり選択を取り消したりするたびに総バイト数を計算することによって取得できます。しかし、 LBSELCHSTRINGメッセージを使って、 新しい選択を識別し、 対応するファイルの長さをカスタム コントロールの値に加算した方が高速です (この例では、 カスタム コントロールはコモン ダイアログ ボックスのリソース ファイル テンプレートで識別する標準Windowsコントロールです)。

選択変更メッセージは、 RegisterWindowMessage関数で登録します。メッセージを登録したら、 この関数の戻り値を使ってダイアログ ボックスからのメッセージを識別します。メッセージは、 コモン ダイアログ ボックスのアプリケーション定義のフック関数で処理します。各メッセージのwParamパラメータは、 選択が発生したリスト ボックスを識別します。lParamパラメータの下位ワードは、 リスト ボックスの項目を識別します。lParamパラメータの上位ワードは、 次に示す値のいずれかになります。

意味

CD_LBSELCHANGE lParamの下位ワードが識別する項目は、 単一選択リスト ボックスの項目です。

CD_LBSELSUB lParamの下位ワードが識別する項目が、 複数選択リスト ボックスで選択解除されました。

CD_LBSELADD lParamの下位ワードが識別する項目が、 複数選択リスト ボックスで選択されました。

CD_LBSELNOITEMS 複数選択リスト ボックスで何も選択されていません。

コモン ダイアログ ボックス メッセージの登録の例については、 [文字列の検索]ダイアログ ボックスの表示を参照してください。

[ファイルを開く]ダイアログ ボックスや[ファイル名を付けて保存]ダイアログ ボックスのファイル名の監視

[ファイルを開く]ダイアログ ボックスや[ファイル名を付けて保存]ダイアログ ボックスの処理は、 ユーザーが入力するファイル名を監視して別の処理を行うことによって変更できます。たとえば、 選択されているファイル名が使用不能のときはダイアログ ボックスをクローズできないようにすることができます。また、 複数のファイル名を選択できるようにすることもできます。

ファイル名を監視するには、 FILEOKSTRINGメッセージを登録します。メッセージを登録するには、 メッセージ名をパラメータに指定してRegisterWindowMessage関数を呼び出します。メッセージを登録すると、 COMDLG32.DLLのダイアログ ボックス プロシージャは、 そのメッセージを使って、 ユーザーがファイル名を選択して[OK]ボタンを選択し、 ダイアログ ボックスがファイル名をチェックして戻る準備ができたことを通知します。ダイアログ ボックス プロシージャは、 メッセージをアプリケーションのフック関数に送ってこのような動作を通知します。フック関数は、 メッセージを受け取ったら、 呼び出し側のダイアログ ボックスに値を返してください。メッセージを処理しなかったときは、 フック関数は0を返してください。フック関数でメッセージを処理し、 ダイアログ ボックスをクローズするときは、 0を返してください。フック関数でメッセージを処理せず、 ダイアログ ボックスをクローズするときは、 1を返してください。これ以外の戻り値は予約されています。

デフォルト プリンタの[印刷]ダイアログ ボックスの表示

デフォルト プリンタの[印刷]ダイアログ ボックスを表示するには、 PRINTDLG構造体を初期化して、 PrintDlg関数を呼び出してください。

PRINTDLG構造体のメンバには、 次に示すような情報を設定してください。

・ プリンタのデバイス コンテキスト

・ ダイアログ ボックスのコントロールに表示される値

・ カスタマイズした[印刷]ダイアログ ボックスや[プリンタの設定]ダイアログ ボックスに使われるフック関数とカスタム ダイアログ ボックス テンプレート

現在インストールされているプリンタの[印刷]ダイアログ ボックスを表示するには、 次に示す手順に従ってください。

1. PRINTDLG構造体のFlagsメンバにPD_RETURNDCフラグをセットします (このフラグは、 デバイス コンテキストが必要なときだけセットしてください)。

2. lStructSizeメンバ、 hDevModeメンバ、 hDevNamesメンバを初期化します。

3. 初期化したPRINTDLG構造体を指すポインタを指定してPrintDlg関数を呼び出します。

 

PD_RETURNDCフラグをセットすると、 PrintDlgは、 [印刷]ダイアログ ボックスを表示して、 プリンタ デバイス コンテキストを識別するハンドルをPRINTDLG構造体のhDCメンバに返します (このデバイス コンテキスト ハンドルは、 プリンタに出力するときに、 グラフィック デバイス インターフェイス (GDI) 関数の第1パラメータとして渡します)。

[文字列の検索]ダイアログ ボックスの表示

[文字列の検索]ダイアログ ボックスには、 次に示す情報をユーザーが指定するためのコントロールがあります。

・ 検索する文字列

・ 文字列を単語全体と比較するか、 単語の一部とも比較するか

・ 指定した文字列の大文字と小文字を区別するかどうか

・ 検索方向 (現在のカーソル位置から上に検索するか下に検索するか)

・ 検索を続行して一致する次の文字列を検索するかどうか

[文字列の検索]ダイアログ ボックスを表示するには、 FINDREPLACE構造体を初期化してFindText関数を呼び出します。FINDREPLACE構造体のメンバには、 次に示す項目に関する情報を設定します。

・ ダイアログ ボックスを所有するウィンドウ

・ 検索の実行方法

・ 文字列を受け取る文字バッファ

FINDREPLACE構造体を初期化するときは、 次に示す作業を行ってください。

1. sizeof演算子を使ってlStructSizeメンバを設定します。

2. ダイアログ ボックスのオーナー ウィンドウを識別するハンドルをhwndOwnerメンバに設定します。

3. [文字列の検索]ダイアログ ボックスをカスタマイズするときは、 カスタム ダイアログ ボックスのテンプレートを含むモジュールのインスタンス ハンドルをhInstanceメンバに設定します。

4. ダイアログ ボックスのオプションの選択状態を示す値をFlagsメンバに設定します (たとえば、 FR_NOUPDOWNフラグをセットすると[上に向かって]ボタンと[下に向かって]ボタンが使用不能になり、 FR_NOWHOLEWORDフラグをセットすると[単語単位で検索]チェック ボックスが使用不能になります。また、 FR_NOMATCHCASEフラグをセットすると[大文字と小文字を区別する]チェック ボックスが使用不能になります)。

5. カスタム ダイアログ ボックス テンプレートやフック関数を供給するときは、 適切なフラグをFlagsメンバにさらに設定します。

6. 検索する文字列が返されるバッファを指すポインタをlpstrFindWhatメンバに設定します。

7. lpstrFindWhatが指すバッファのバイト単位のサイズをwFindWhatLenメンバに設定します。

8. アプリケーションからアクセスしなければならないカスタム データをlCustDataメンバに設定します。

9. [文字列の検索]ダイアログ ボックスをカスタマイズするときは、 フック関数を指すポインタをlpfnHookメンバに設定します。

10. カスタム ダイアログ ボックス テンプレートを使うときは、 そのテンプレートを識別する文字列を指すポインタをlpTemplateNameメンバに設定します。

 

次の例は、 FINDREPLACE構造体を初期化してFindTextを呼び出します。この構造体は、 グローバルにするか、 static変数として宣言してください。

 

/* Find/Replace variables */

FINDREPLACE fr; /* common dialog box structure */
FINDREPLACE FAR* lpfr; /* pointer to common dialog box structure */
CHAR szFindWhat[80]; /* buffer receiving string to be found */
HWND hdlg; /* handle identifying dialog window */
UINT uFindReplaceMsg; /* value returned by RegisterMessage() */


/* Initialize the necessary members. */

fr.lStructSize = sizeof(FINDREPLACE);
fr.hwndOwner = hwnd;
fr.lpstrFindWhat = szFindWhat;
fr.wFindWhatLen = sizeof(szFindWhat);

/* Display the modeless Find dialog box. */

hdlg = FindText(&fr);

[文字列の置換]ダイアログ ボックスの表示

[文字列の置換]ダイアログ ボックスは[文字列の検索]ダイアログ ボックスに似ています。しかし、 [文字列の置換]ダイアログ ボックスには[検索する方向]チェック ボックスはなく、 次に示すオプションを指定するための3つのコントロールがあります。

・ 置換文字列

・ 現在選択されている文字列を置き換えるかどうか

・ 一致する文字列をすべて置き換えるかどうか

 

[文字列の置換]ダイアログ ボックスを表示するには、 FINDREPLACE構造体を初期化してReplaceText関数を呼び出します。

[文字列の検索]ダイアログ ボックスや[文字列の置換]ダイアログ ボックスのダイアログ メッセージの処理

[文字列の検索]ダイアログ ボックスと[文字列の置換]ダイアログ ボックスは、 2つの点でほかのコモン ダイアログ ボックスとは異なります。これらのダイアログ ボックスはモードレスであり、 ダイアログ ボックス プロシージャは、 FindText関数やReplaceText関数を呼び出したアプリケーションにメッセージを送ります。これらのメッセージは、 文字列の検索方法や、 大文字と小文字を区別するかどうか、 単語全体と比較するかどうかなどの、 ダイアログ ボックスのコントロールでユーザーが指定したデータを含みます。

 

[文字列の検索]ダイアログ ボックスや[文字列の置換]ダイアログ ボックスからのメッセージを処理するには、 ダイアログ ボックス固有のFINDMSGSTRINGメッセージを登録してください。

このメッセージは、 RegisterWindowMessage関数で登録します。メッセージを登録したら、 関数の戻り値を使って、 [文字列の検索]ダイアログ ボックスや[文字列の置換]ダイアログ ボックスからのメッセージを識別します。次に示す例は、 RegisterWindowMessageを使ってメッセージを登録します。

/* Register the FindReplace message. */

uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);

このメッセージを登録したら、 RegisterWindowMessageの戻り値を使って、 [文字列の検索]ダイアログ ボックスや[文字列の置換]ダイアログ ボックスからのメッセージを処理してください。次に示す例は、 [文字列の検索]ダイアログ ボックスからのメッセージを処理して、 テキストから文字列を見つけ出すために自分自身のSearchFile関数を呼び出します。ユーザーがダイアログ ボックスをクローズしようとすると (つまり、 FINDREPLACE構造体のFlagsメンバがFR_DIALOGTERMのとき)、 ハンドルは無効になり、 プロシージャは0を返します。

 

if (message == uFindReplaceMsg){

/*
* Extract a pointer to the FINDREPLACE
* structure from lParam.
*/

lpfr = (FINDREPLACE FAR*) lParam;

/*
* If the system has set the FR_DIALOGTERM
* flag, invalidate the handle identifying
* the dialog box.
*/

if (lpfr->Flags & FR_DIALOGTERM){
hdlg = NULL;
return 0;
}

/*
* If the dialog box is still valid, call the
* application-defined search routine (SearchFile) to
* search for the requested string.
*/

SearchFile((BOOL) (lpfr->Flags & FR_DOWN),
(BOOL) (lpfr->Flags & FR_MATCHCASE));
return 0;
}

コモン ダイアログ ボックスのカスタマイズ

カスタム コモン ダイアログ ボックスとは、 特定のWindowsアプリケーションに適合するように変更されたコモン ダイアログ ボックスです。複雑なカスタマイズとしては、 元のコントロールを非表示にして新しいコントロールを追加することや、 元のダイアログ ボックスのサイズを変更することなどがあります。簡単なカスタマイズとしては、 既存のコントロールを1つだけ変更することなどがあります。

コモン ダイアログ ボックスをカスタマイズするには、 特別なフック関数を提供しなければなりません。また、 ほとんどの場合、 カスタム ダイアログ ボックス テンプレートも提供しなければなりません。このようなカスタマイズには、 かなりの量のコードの追加が必要です。カスタマイズしたコモン ダイアログ ボックスを表示することは、 構造体のメンバを初期化して関数を1つだけ呼び出すことほど簡単ではありません。

コモン ダイアログ ボックスのコントロールをサブクラス化するには、 フック関数でWM_INITDIALOGメッセージを処理するときにサブクラス化を行ってください。これによって、 ダイアログ ボックスが自分自身のサブクラス プロシージャをインストールしてからアプリケーションがコントロールをサブクラス化することになるため、 コントロール固有のメッセージをアプリケーションが先に受け取れるようになります (サブクラス化を行う場合の基準どおり、 アプリケーションのサブクラス関数で処理しなかったメッセージはすべて前のフック関数に渡してください)。

特定のコントロールの種類を変更するローカル クラスを定義してコントロールをサブクラス化することはできません。これは、 クラスが呼び出されたときにデータ セグメントが正しく初期化されていないためです。データ セグメントは、 アプリケーションのデータ セグメントではなくコモン ダイアログ ボックスのデータ セグメントになっています。

適切なカスタマイズと不適切なカスタマイズ

ユーザーの立場では、 コモン ダイアログ ボックスの主な利点は、 アプリケーション間で変わらない外観と操作です。このため、 コモン ダイアログ ボックスのカスタマイズは、 特に必要なときだけ行ってください。安易なカスタマイズを行うと、 アプリケーション間で一貫した外観と簡単なインターフェイスが失われます。適切なカスタマイズを行うには、 元のコントロールをできるだけそのまま残してください。ダイアログ ボックスのサイズを大きくしたり、 ダイアログ ボックスの余白に新しいコントロールを追加するのは、 適切なカスタマイズといえます。元のコントロールを非表示にしたり、 元のコントロールの機能を変更するのは、 あまり適切なカスタマイズとはいえません。

フック関数とカスタム ダイアログ ボックス テンプレート

各コモン ダイアログ ボックスは、 COMDLG32.DLLで定義されているダイアログ ボックス プロシージャとダイアログ ボックス テンプレートを使用します。ダイアログ ボックス プロシージャは、 コモン ダイアログ ボックスとそのコントロールのメッセージや通知を処理します。ダイアログ ボックス テンプレートは、 ダイアログ ボックスの外観 (寸法、 位置、 ダイアログ ボックス内のコントロールの寸法と位置) を定義します。

カスタム ダイアログ ボックスでは、 用意されているダイアログ ボックス プロシージャとテンプレートのほかに、 アプリケーションが提供するフック関数が必要です。また、 通常、 カスタムのダイアログ ボックス テンプレートも必要です。

フック関数

コモン ダイアログ ボックスの構造体に適切なフラグとポインタを設定しておくと、 COMDLG32.DLLで提供されているダイアログ ボックス プロシージャは、 アプリケーションのフック関数を呼び出します。各コモン ダイアログ ボックスの構造体には、 アプリケーションがフック関数を定義しているかどうかを示すFlagsメンバと、 フック関数を指すlpfnHookメンバがあります。フック関数が存在することを示すフラグをFlagsメンバにセットするときは、 lpfnHookメンバにも適切なポインタを設定してください。次に示す例は、 アプリケーションのフック関数をサポートするために、 OPENFILENAME構造体のFlagsメンバとlpfnHookメンバを設定します。

#include <windows.h> /* required for all Windows applications */
#include <commdlg.h> /* required for all common dialog box functions*/
#include <dlgs.h>
#include "generic.h" /* specific to this application */

OPENFILENAME ofn; /* common dialog box structure */
char szDirName[256]; /* directory string */
char szFile[256]; /* filename string */
char szFileTitle[256]; /* file-title string */
char szFilter[256]; /* filter string */
char chReplace; /* string separator for szFilter */
int i, cbString; /* integer count variables */
DWORD cBufLen; /* dword count */
DWORD cTmp; /* dword count */
HANDLE hf; /* original file handle */
HANDLE hfBackup; /* backup file handle */
char szBuffer[256]; /* character buffer */
char szChar[256]; /* character buffer */
char* pszBackupFile; /* pointer to backup filename */
BOOL fBackup; /* TRUE if user checked "backup" box */

/* Retrieve the system directory name. */

GetSystemDirectory((LPSTR)szDirName, sizeof(szDirName));

/* Place the terminating null character in the szFile. */

szFile[0] = '\0';

/* Load the filter string from the .RC file. */

cbString = LoadString(hinst, IDS_FILTERSTRING,
szFilter, sizeof(szFilter));

/* Add a terminating null character to the string. */

chReplace = szFilter[cbString - 1];

for (i = 0; szFilter[i] != '\0'; i++) {
if (szFilter[i] == chReplace)
szFilter[i] = '\0';
}
/* Initialize the required OPENFILENAME members. */

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = hinst;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = szDirName;
ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST |
OFN_FILEMUSTEXIST | OFN_ENABLEHOOK |
OFN_ENABLETEMPLATE;
ofn.lpfnHook = FileOpenHookProc;
ofn.lpTemplateName = "FILEOPEN";

上記の例では、 アプリケーション定義のフック関数のアドレスをOPENFILENAME構造体のlpfnHookメンバに設定しています。フック関数は、 カスタム ダイアログ ボックスが必要とするメッセージや通知を処理します。WM_INITDIALOGメッセージを除いて、 フック関数は、 COMDLG32.DLLのダイアログ ボックス プロシージャよりも前にメッセージや通知を受け取ります。WM_INITDIALOGの場合は、 ダイアログ ボックス プロシージャよりも後にフック関数がメッセージを受け取ります。フック関数は、 メッセージの処理を終了したら、 COMDLG32.DLLのダイアログ ボックス プロシージャもそのメッセージを処理すべきかどうかを示す値を返してください。ダイアログ ボックス プロシージャにメッセージを処理させるときは、 FALSEを返してください。ダイアログ ボックス プロシージャにメッセージを無視させるときは、 TRUEを返してください。

[OK]ボタンからのメッセージをダイアログ ボックス プロシージャが処理した後で処理するには、 [OK]ボタンからのメッセージを受け取ったときに、 自分自身に対してメッセージをポストしてください。共通ダイアログ ボックス プロシージャがダイアロゴ ボックスのメッセージを処理し終わると、 アプリケーションはポストしたメッセージを受け取ります。[文字列の検索]ダイアログ ボックスと[文字列の置換]ダイアログ ボックスでは、 COMDLG32.DLLがメッセージを処理するまでFINDREPLACE構造体のFlagsメンバに変更は反映されないため、 この方法は[文字列の検索]ダイアログ ボックスや[文字列の置換]ダイアログ ボックスで特に役立ちます。

次に示す例は、 カスタムの[ファイルを開く]ダイアログ ボックスのフック関数を示しています。

UINT FAR PASCAL FileOpenHookProc(HWND hdlg, UINT msg, WPARAM wParam,
LPARAM lParam)
{
switch (msg) {
case WM_INITDIALOG: /* Received <after> commdlg is processed. */

return TRUE;

case WM_COMMAND:

/* Use IsDlgButtonChecked to set lCustData. */

if (wParam == IDOK)

/* Set the "backup file" flag. */

fBackup = (DWORD) IsDlgButtonChecked(hdlg, ID_CUSTCHX);

return FALSE; /* Allow standard processing. */
break;

default:
return FALSE;

} /* end switch */

return FALSE;
}

このフック関数は、 ユーザーが[OK]ボタンを選択すると、 カスタムのチェック ボックスをテストします。チェック ボックスが選択されていれば、 フック関数は、 0以外の値をグローバル変数に設定します。そうでないときは、 0を設定します。

フック関数からはEndDialog関数を呼び出さないでください。フック関数からコモン ダイアログ ボックスを異常終了させるには、 次に示す例のように、 PostMessage関数を使って、 ダイアログ ボックス プロシージャにIDABORT値を渡してください。

PostMessage(hDlg, WM_COMMAND, IDABORT, (LONG) FALSE);

フック関数がIDABORT値をポストすると、 コモン ダイアログ ボックスは、 lParamパラメータの下位ワードの値を返します。たとえば、 GetOpenFileNameのフック関数が (LONG) 100を最後のパラメータに指定してPostMessage関数を呼び出すと、 GetOpenFileNameは100を返します。

フック関数は、 次の例に示すように、 アプリケーションのモジュール定義 (.DEF) ファイルでエクスポートしてください。

NAME Generic ; application's module name

DESCRIPTION 'Sample Win32-based Application'

EXETYPE WINDOWS ; required for all Windows applications

STUB 'WINSTUB.EXE' ; Generates error message if the
; application is run without Windows

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024
STACKSIZE 8192

EXPORTS
MainWndProc @1 ; name of window processing function
About @2 ; name of "About" processing function
FileOpenHookProc @3; name of common dialog box callback 

ダイアログ ボックス テンプレートのカスタマイズ

COMDLG32.DLLで提供されている各コモン ダイアログ ボックスのテンプレートは、 そのコモン ダイアログ ボックスを表示するために使われます。通常、 コモン ダイアログ ボックスをカスタマイズ場合は、 COMDLG32.DLLのダイアログ ボックス テンプレートを使わずに、 カスタムのダイアログ ボックス テンプレートを作成する必要があります (カスタムのダイアログ ボックス テンプレートは必ずしも必要なわけではありません。ダイアログ ボックスを少しだけ変更するときは、 カスタム テンプレートは不要です)。

カスタム ダイアログ ボックス テンプレートはCOMDLG32.DLLのダイアログ ボックス テンプレートを修正して作成してください。各コモン ダイアログ ボックスのテンプレートのファイル名とダイアログ ボックスの名前を次に示します。

テンプレート名 対応するダイアログ ボックス

COLOR.DLG [色の設定]

FILEOPEN.DLG [ファイルを開く](単一選択)

FILEOPEN.DLG [ファイルを開く](複数選択)

FINDTEXT.DLG [文字列の検索]

FINDTEXT.DLG [文字列の置換]

FONT.DLG [フォントの指定]

PRNSETUP.DLG [印刷]

PRNSETUP.DLG [プリンタの設定]

[ファイルを開く]ダイアログ ボックス用のカスタム ダイアログ ボックス テンプレートからの抜粋を次に示します。

FILEOPEN DIALOG LOADONCALL MOVEABLE DISCARDABLE
36, 24, 264, 134
CAPTION "ファイルを開く"
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME
FONT 8, "Helv"
BEGIN
LTEXT "ファイル名:(\030N\031フ)", stc3, 6, 6, 76, 10
CONTROL "", edt1, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_BORDER |
WS_TABSTOP | WS_CHILD | ES_OEMCONVERT | ES_LOWERCASE,
6, 16, 90, 12
CONTROL "", lst1, "listbox", LBS_SORT | LBS_NOTIFY | LBS_DISABLENOSCROLL |
WS_VSCROLL | WS_BORDER | WS_TABSTOP | LBS_EXTENDEDSEL
| LBS_HASSTRINGS | LBS_OWNERDRAWFIXED,
6, 32, 90, 68

LTEXT "ディレクトリ:(\030D\031テ)", -1, 110, 6, 92, 9
LTEXT "", stc1, 110, 16, 92, 9, SS_NOPREFIX
CONTROL "", lst2, "listbox",
LBS_SORT | LBS_HASSTRINGS | LBS_NOTIFY | LBS_DISABLENOSCROLL
| WS_VSCROLL | WS_CHILD | WS_BORDER | WS_TABSTOP
| LBS_OWNERDRAWFIXED,
110, 32, 92, 68

LTEXT "ファイルの種類:(\030T\031シ)", stc2, 6, 102, 90, 9
CONTROL "", cmb1, "combobox", CBS_DROPDOWNLIST | CBS_AUTOHSCROLL |
WS_BORDER | WS_VSCROLL | WS_TABSTOP | WS_CHILD,
6, 112, 90, 36

LTEXT "ドライブ:(\030V\031ト)", stc4, 110, 102, 92, 9
CONTROL "", cmb2, "combobox",
CBS_SORT | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED | CBS_DROPDOWNLIST
| WS_CHILD | CBS_AUTOHSCROLL | WS_BORDER | WS_VSCROLL
| WS_TABSTOP,
110, 112, 92, 68
DEFPUSHBUTTON "OK", IDOK, 208, 6, 50, 14, WS_GROUP
PUSHBUTTON "キャンセル", IDCANCEL, 208, 24, 50, 14, WS_GROUP

PUSHBUTTON "ヘルプ(\030H\031ヘ)", pshHelp, 208, 46, 50, 14, WS_GROUP
PUSHBUTTON "ネットワーク(\030W\031ネ)...", psh14, 208, 114, 50, 14, WS_GROUP
AUTOCHECKBOX "書き込み禁止(\030R\031カ)", chx1, 208, 68, 50, 12,
WS_TABSTOP | WS_GROUP

AUTOCHECKBOX "ファイル バックアップ(\030B\031ハ)", ID_CUSTCHX, 208, 86, 50, 12,
BS_AUTOCHECKBOX | WS_CHILD | WS_TABSTOP | WS_GROUP

END

最後のエントリによって、 既存の[書き込み禁止]チェック ボックスの下に、 新しい[ファイル バックアップ]チェック ボックスが追加されます。

カスタム テンプレートは、 アプリケーションのリソース ファイルに追加してください。ダイアログ ボックスで使用しないコントロールがあるときでも、 一意なコントロール識別子 (-1以外の識別子) はすべて使ってください。表示しないコントロールがあるときは、 そのコントロールの座標をダイアログ ボックスの外側に設定してください。また、 不要なボタンは使用不能にして、 不要なタブ ストップは削除してください。

カスタム ダイアログ ボックスの表示

フック関数とダイアログ ボックス テンプレートを用意したら、 コモン ダイアログ ボックスの構造体のメンバにカスタマイズ用の値を設定し、 適切な関数を呼び出してカスタム ダイアログ ボックスを表示します。

次に示す例は、 GetOpenFileName関数を呼び出して、 カスタムの[ファイルを開く]ダイアログ ボックスの[ファイル バックアップ]チェック ボックスが選択されていれば、 バックアップ ファイルを作成します。

/* Process the requested file. */

if (GetOpenFileName(&ofn)) {

/*
* If the user checked the Backup File Check box,
* create a backup file.
*/

if (fBackup) {

/* Open the requested file. */

hf = CreateFile(ofn.lpstrFile, GENERIC_READ,
0, (LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);

/* Process the extension (if it exists). */

if (ofn.nFileExtension) {
for(i = 0; i < (int)ofn.nFileExtension;
i++)
szChar[i] = *ofn.lpstrFile++;
} /* end if */

else {
i = 0;
while (*ofn.lpstrFile != '\0')
szChar[i++] = *ofn.lpstrFile++;
szChar[i] = '.';
} /* end else */

/* Create the backup filename string. */

pszBackupFile = lstrcat(szChar, "BAK");

/* Create the backup file. */

hfBackup = CreateFile(pszBackupFile, GENERIC_WRITE,
0, (LPSECURITY_ATTRIBUTES) NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);

/*
* Copy the contents of the original file
* to the new file.
*/

ReadFile(hf, szBuffer, 256, &cBufLen,
NULL);

while (cBufLen == 256) {
WriteFile(hfBackup, szBuffer, 256, &cBufLen,
NULL);
ReadFile(hf, szBuffer, 256, &cBufLen,
NULL);
}

WriteFile(hfBackup, szBuffer, cBufLen, &cTmp,
NULL);


/* Close the files. */

CloseHandle(hfBackup);
CloseHandle(hf);

} /* end if */
} /* end if */

コモン ダイアログ ボックスのヘルプのサポートと処理

コモン ダイアログ ボックスに[ヘルプ]ボタンを表示するには、 そのダイアログ ボックスの構造体のFlagsメンバに適切なフラグを設定してください。コモン ダイアログ ボックスの構造体と、 その構造体に対応するヘルプ表示フラグを次に示します。

構造体 フラグの値

  • OPENFILENAME OFN_SHOWHELP
  • CHOOSECOLOR CC_SHOWHELP
  • FINDREPLACE FR_SHOWHELP
  • CHOOSEFONT CF_SHOWHELP
  • PRINTDLG PD_SHOWHELP

 

[ヘルプ]ボタンを表示するときは、 ユーザーのヘルプ要求を処理しなければなりません。ヘルプの処理は、 アプリケーションのウィンドウ プロシージャまたはフック関数で行います。

アプリケーションのウィンドウ プロシージャでヘルプ要求を処理するときは、 HELPMSGSTRING値で定義されている文字列の新しいメッセージ識別子を作成しておかなければなりません。新しいメッセージ識別子を作成するには、 この値をパラメータに指定してRegisterWindowMessage関数を呼び出します (登録ウィンドウ メッセージの処理について詳しくは、 [文字列の検索]ダイアログ ボックスの表示を参照してください)。また、 新しいメッセージ識別子を作成するほかに、 ダイアログ ボックスのオーナー ウィンドウのハンドルを、 構造体のhwndOwnerメンバに設定してください。メッセージ識別子を作成してhwndOwnerメンバを設定すると、 ダイアログ ボックス プロシージャは、 ユーザーが[ヘルプ]ボタンを選択するたびにオーナー ウィンドウのウィンドウ プロシージャに通知します。

次に示す例は、 オーナー ウィンドウのウィンドウ プロシージャでヘルプ要求を処理します。if文は、 メッセージを処理するswitch文のdefault:節に置いてください。

MyHelpMsg = RegisterWindowMessage(HELPMSGSTRING);.
.
if (message == MyHelpMsg)
WinHelp(hWnd, "appfile.hlp", HELP_CONTEXT, ID_MY_CONTEXT);

フック関数でヘルプ要求処理するときは、 WM_COMMANDメッセージで次に示す条件をテストしてください。

wParam == pshHelp

この条件が真ならば、 フック関数は、 上記の例のようにWinHelp関数を呼び出してください (フック関数でヘルプを処理するときは、 フック関数のコードを含むソースファイルでヘッダー ファイルDLGS.Hをインクルードしてください)。

エラーの検出

コモン ダイアログ ボックス関数が正常に終了しなかったときは、 CommDlgExtendedError関数を呼び出して、 エラーの原因を調べてください。CommDlgExtendedErrorは、 最近のエラーの原因を示すエラー値を返します。

CDERR.Hヘッダー ファイルには、 CommDlgExtendedErrorが返すエラー値の範囲を種類ごとに識別する6つの値が定義されています。その定数を値の範囲の順に示します。

定数 説明

CDERR_GENERALCODES コモン ダイアログ ボックスの一般的なエラー コードです。このエラーは0x0000から0x0FFFまでです。

PDERR_PRINTERCODES [印刷]コモン ダイアログ ボックスのエラー コードです。このエラーは0x1000から0x1FFFまでです。

CFERR_CHOOSEFONTCODES [フォントの指定]コモン ダイアログ ボックスのエラー コードです。このエラーは0x2000から0x2FFFまでです。

FNERR_FILENAMECODES [ファイルを開く]コモン ダイアログ ボックスと[ファイル名を付けて保存]コモン ダイアログ ボックスのエラー コードです。このエラーは0x3000から0x3FFFまでです。

FRERR_FINDREPLACECODES [文字列の検索]コモン ダイアログ ボックスと[文字列の置換]コモン ダイアログ ボックスのエラー コードです。このエラーは0x4000から0x4FFFまでです。

CCERR_CHOOSECOLORCODES [色の設定]コモン ダイアログ ボックスのエラー コードです。このエラーは0x5000から0x5FFFまでです。

コモン ダイアログ ボックス関数

コモン ダイアログ ボックスに関する関数を次に示します。

  • ChooseColor
  • ChooseFont
  • FindText
  • GetFileTitle
  • GetOpenFileName
  • GetSaveFileName
  • PrintDlg
  • ReplaceText

 

 

▲ページトップに戻る

【本を読んでもよくらからない】 … 個別指導でわかりやすくお教えします
inserted by FC2 system