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

このセクションでは、一般的なダイアログ ボックスを呼び出すタスクについて説明します。

色の選択

このトピックでは、ユーザーが色を選択できるように [ ] ダイアログ ボックスを表示するサンプル コードについて説明します。 サンプル コードでは、まず CHOOSECOLOR 構造体を初期化し、次に ChooseColor 関数を呼び出してダイアログ ボックスを表示します。 関数が TRUE を返し、ユーザーが色を選択したことを示す場合、サンプル コードは選択した色を使用して新しいソリッド ブラシを作成します。

この例では、 CHOOSECOLOR 構造体を使用して、次のようにダイアログ ボックスを初期化します。

  • 値の静的配列へのポインターを使用して lpCustColors メンバーを初期化します。 配列内の色は最初は黒ですが、静的配列では、ユーザーが作成したカスタム色が、以降の ChooseColor 呼び出しで保持されます。
  • CC_RGBINIT フラグを設定し、rgbResult メンバーを初期化して、ダイアログ ボックスが開いたときに最初に選択される色を指定します。 指定しない場合、最初の選択は黒になります。 この例では 、rgbCurrent 静的変数を使用して、 ChooseColor の呼び出しの間に選択した値を保持します。
  • ダイアログ ボックスのユーザー設定の色の拡張機能が常に表示されるように、 CC_FULLOPEN フラグを設定します。
CHOOSECOLOR cc;                 // common dialog box structure 
static COLORREF acrCustClr[16]; // array of custom colors 
HWND hwnd;                      // owner window
HBRUSH hbrush;                  // brush handle
static DWORD rgbCurrent;        // initial color selection

// Initialize CHOOSECOLOR 
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.hwndOwner = hwnd;
cc.lpCustColors = (LPDWORD) acrCustClr;
cc.rgbResult = rgbCurrent;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
 
if (ChooseColor(&cc)==TRUE) 
{
    hbrush = CreateSolidBrush(cc.rgbResult);
    rgbCurrent = cc.rgbResult; 
}

フォントの選択

このトピックでは、ユーザーがフォントの属性を選択できるように 、[ フォント ] ダイアログ ボックスを表示するサンプル コードについて説明します。 サンプル コードでは、まず CHOOSEFONT 構造体を初期化し、次に ChooseFont 関数を呼び出してダイアログ ボックスを表示します。

次の使用例は、 CF_SCREENFONTS フラグを設定して、ダイアログ ボックスに画面フォントのみを表示するように指定します。 CF_EFFECTS フラグを設定して、ユーザーが取り消し線、下線、色のオプションを選択できるようにするコントロールを表示します。

ChooseFont がTRUE を返す場合、ユーザーが [OK] ボタンをクリックしたことを示す CHOOSEFONT 構造体には、lpLogFont メンバーが指す LOGFONT 構造体のメンバーなど、ユーザーが選択したフォントとフォント属性を説明する情報が含まれます。 rgbColors メンバーには、選択したテキストの色が含まれています。 サンプル コードでは、この情報を使用して、所有者ウィンドウに関連付けられているデバイス コンテキストのフォントとテキストの色を設定します。

HWND hwnd;                // owner window
HDC hdc;                  // display device context of owner window

CHOOSEFONT cf;            // common dialog box structure
static LOGFONT lf;        // logical font structure
static DWORD rgbCurrent;  // current text color
HFONT hfont, hfontPrev;
DWORD rgbPrev;

// Initialize CHOOSEFONT
ZeroMemory(&cf, sizeof(cf));
cf.lStructSize = sizeof (cf);
cf.hwndOwner = hwnd;
cf.lpLogFont = &lf;
cf.rgbColors = rgbCurrent;
cf.Flags = CF_SCREENFONTS | CF_EFFECTS;

if (ChooseFont(&cf)==TRUE)
{
    hfont = CreateFontIndirect(cf.lpLogFont);
    hfontPrev = SelectObject(hdc, hfont);
    rgbCurrent= cf.rgbColors;
    rgbPrev = SetTextColor(hdc, rgbCurrent);
 .
 .
 .
}

ファイルを開く

Note

Windows Vista 以降では、ファイルを開くときに共通ファイル ダイアログが共通項目ダイアログに置き換わりました。 共通ファイル ダイアログ API ではなく、共通項目ダイアログ API を使用することをお勧めします。 詳細については、「 共通項目ダイアログ」を参照してください。

このトピックでは、ユーザーが開くファイルのドライブ、ディレクトリ、名前を指定できるように、[ 開く ] ダイアログ ボックスを表示するサンプル コードについて説明します。 サンプル コードでは、最初に OPENFILENAME 構造体を初期化してから、 GetOpenFileName 関数を呼び出してダイアログ ボックスを表示します。

この例では、 lpstrFilter メンバーは、表示されるファイル名を制限するためにユーザーが選択できる 2 つのファイル名フィルターを指定するバッファーへのポインターです。 バッファーには、文字列の各ペアがフィルターを指定する文字列の double-null で終わる配列が含まれています。 nFilterIndex メンバーは、ダイアログ ボックスの作成時に最初のパターンを使用することを指定します。

次の使用例は、Flags メンバーのOFN_PATHMUSTEXISTフラグとOFN_FILEMUSTEXISTフラグを設定します。 これらのフラグにより、ダイアログ ボックスは、ユーザーによって指定されたパスとファイル名が実際に存在することを返す前に確認します。

ユーザーが [OK] ボタンをクリックし、指定したパスとファイル名が存在する場合、GetOpenFileName 関数は TRUE を返します。 この場合、 lpstrFile メンバーが指すバッファーには、パスとファイル名が含まれます。 サンプル コードでは、関数の呼び出しでこの情報を使用してファイルを開きます。

この例では、OFN_EXPLORER フラグは設定しませんが、既定のエクスプローラー スタイルの [開く] ダイアログ ボックスが表示されます。 ただし、フック プロシージャまたはカスタム テンプレートを指定し、ユーザー インターフェイスをエクスプローラーする場合は、OFN_EXPLORER フラグを設定する必要があります。

注意

C プログラミング言語では、引用符で囲まれた文字列は null で終わります。

 

OPENFILENAME ofn;       // common dialog box structure
char szFile[260];       // buffer for file name
HWND hwnd;              // owner window
HANDLE hf;              // file handle

// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

// Display the Open dialog box. 

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

[印刷] ダイアログ ボックスの表示

このトピックでは、ユーザーがドキュメント を印刷 するためのオプションを選択できるように、[印刷] ダイアログ ボックスを表示するサンプル コードについて説明します。 サンプル コードでは、まず PRINTDLG 構造体を初期化してから、 PrintDlg 関数を呼び出してダイアログ ボックスを表示します。

次の使用例は、PRINTDLG 構造体の Flags メンバーにPD_RETURNDC フラグを設定します。 これにより、 PrintDlghDC メンバー内の選択したプリンターにデバイス コンテキスト ハンドルを返します。 ハンドルを使用して、プリンターに出力をレンダリングできます。

入力時に、サンプル コードは hDevMode メンバーと hDevNames メンバーを NULL に設定します。 関数が TRUE を返す場合、これらのメンバーは、ユーザー入力とプリンターに関する情報を含む DEVNAMES 構造体にハンドルを返します。 この情報を使用して、選択したプリンターに送信する出力を準備できます。

PRINTDLG pd;
HWND hwnd;

// Initialize PRINTDLG
ZeroMemory(&pd, sizeof(pd));
pd.lStructSize = sizeof(pd);
pd.hwndOwner   = hwnd;
pd.hDevMode    = NULL;     // Don't forget to free or store hDevMode.
pd.hDevNames   = NULL;     // Don't forget to free or store hDevNames.
pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; 
pd.nCopies     = 1;
pd.nFromPage   = 0xFFFF; 
pd.nToPage     = 0xFFFF; 
pd.nMinPage    = 1; 
pd.nMaxPage    = 0xFFFF; 

if (PrintDlg(&pd)==TRUE) 
{
    // GDI calls to render output. 

    // Delete DC when done.
    DeleteDC(pd.hDC);
}

Print プロパティ シートの使用

このトピックでは、ユーザーがドキュメントを印刷するためのオプションを選択できるように 、Print プロパティ シートを表示するサンプル コードについて説明します。 サンプル コードでは、まず PRINTDLGEX 構造体を初期化してから、 PrintDlgEx 関数を呼び出してプロパティ シートを表示します。

サンプル コードでは、PRINTDLG 構造体の Flags メンバーにPD_RETURNDC フラグを設定します。 これにより、 PrintDlgEx 関数は 、hDC メンバー内の選択したプリンターにデバイス コンテキスト ハンドルを返します。

入力時に、サンプル コードは hDevMode メンバーと hDevNames メンバーを NULL に設定します。 関数が S_OKを返す場合、これらのメンバーは、ユーザー入力とプリンターに関する情報を含む DEVNAMES 構造体にハンドルを返します。 この情報を使用して、選択したプリンターに送信する出力を準備できます。

印刷操作が完了すると、サンプル コードは DEVMODEDEVNAMESおよび PRINTPAGERANGE バッファーを解放し、 DeleteDC 関数を呼び出してデバイス コンテキストを削除します。

// hWnd is the window that owns the property sheet.
HRESULT DisplayPrintPropertySheet(HWND hWnd)
{
    HRESULT hResult;
    PRINTDLGEX pdx = {0};
    LPPRINTPAGERANGE pPageRanges = NULL;

    // Allocate an array of PRINTPAGERANGE structures.
    pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
    if (!pPageRanges)
        return E_OUTOFMEMORY;

    //  Initialize the PRINTDLGEX structure.
    pdx.lStructSize = sizeof(PRINTDLGEX);
    pdx.hwndOwner = hWnd;
    pdx.hDevMode = NULL;
    pdx.hDevNames = NULL;
    pdx.hDC = NULL;
    pdx.Flags = PD_RETURNDC | PD_COLLATE;
    pdx.Flags2 = 0;
    pdx.ExclusionFlags = 0;
    pdx.nPageRanges = 0;
    pdx.nMaxPageRanges = 10;
    pdx.lpPageRanges = pPageRanges;
    pdx.nMinPage = 1;
    pdx.nMaxPage = 1000;
    pdx.nCopies = 1;
    pdx.hInstance = 0;
    pdx.lpPrintTemplateName = NULL;
    pdx.lpCallback = NULL;
    pdx.nPropertyPages = 0;
    pdx.lphPropertyPages = NULL;
    pdx.nStartPage = START_PAGE_GENERAL;
    pdx.dwResultAction = 0;
    
    //  Invoke the Print property sheet.
    
    hResult = PrintDlgEx(&pdx);

    if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT) 
    {
        // User clicked the Print button, so use the DC and other information returned in the 
        // PRINTDLGEX structure to print the document.
    }

    if (pdx.hDevMode != NULL) 
        GlobalFree(pdx.hDevMode); 
    if (pdx.hDevNames != NULL) 
        GlobalFree(pdx.hDevNames); 
    if (pdx.lpPageRanges != NULL)
        GlobalFree(pPageRanges);

    if (pdx.hDC != NULL) 
        DeleteDC(pdx.hDC);

    return hResult;
}

印刷ページの設定

このトピックでは、ユーザーが用紙の種類、用紙ソース、ページの向き、ページの余白などの印刷ページの属性を選択できるように、[ページ 設定] ダイアログ ボックスを表示するサンプル コードについて説明します。 サンプル コードでは、最初に PAGESETUPDLG 構造体を初期化してから、 PageSetupDlg 関数を呼び出してダイアログ ボックスを表示します。

次の使用例は、Flags メンバーにPSD_MARGINS フラグを設定し、rtMargin メンバーを使用して初期余白の値を指定します。 PSD_INTHOUSANDTHSOFINCHES フラグを設定して、ダイアログ ボックスが余白の寸法を 1000 分の 1 インチ単位で表すようにします。

入力時に、サンプル コードは hDevMode メンバーと hDevNames メンバーを NULL に設定します。 関数が TRUE を返す場合、関数はこれらのメンバーを使用して、ユーザー入力とプリンターに関する情報を含む DEVNAMES 構造体にハンドルを返します。 この情報を使用して、選択したプリンターに送信する出力を準備できます。

次の例では、 PagePaintHook フック プロシージャを使用して、サンプル ページの内容の描画をカスタマイズすることもできます。

PAGESETUPDLG psd;    // common dialog box structure
HWND hwnd;           // owner window

// Initialize PAGESETUPDLG
ZeroMemory(&psd, sizeof(psd));
psd.lStructSize = sizeof(psd);
psd.hwndOwner   = hwnd;
psd.hDevMode    = NULL; // Don't forget to free or store hDevMode.
psd.hDevNames   = NULL; // Don't forget to free or store hDevNames.
psd.Flags       = PSD_INTHOUSANDTHSOFINCHES | PSD_MARGINS | 
                  PSD_ENABLEPAGEPAINTHOOK; 
psd.rtMargin.top = 1000;
psd.rtMargin.left = 1250;
psd.rtMargin.right = 1250;
psd.rtMargin.bottom = 1000;
psd.lpfnPagePaintHook = PaintHook;

if (PageSetupDlg(&psd)==TRUE)
{
    // check paper size and margin values here.
}

次の例は、サンプル ページ領域に余白の四角形を描画する サンプル PagePaintHook フック プロシージャを示しています。

BOOL CALLBACK PaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    LPRECT lprc; 
    COLORREF crMargRect; 
    HDC hdc, hdcOld; 
 
    switch (uMsg) 
    { 
        // Draw the margin rectangle. 
        case WM_PSD_MARGINRECT: 
            hdc = (HDC) wParam; 
            lprc = (LPRECT) lParam; 
 
            // Get the system highlight color. 
            crMargRect = GetSysColor(COLOR_HIGHLIGHT); 
 
            // Create a dash-dot pen of the system highlight color and 
            // select it into the DC of the sample page. 
            hdcOld = SelectObject(hdc, CreatePen(PS_DASHDOT, .5, crMargRect)); 
 
            // Draw the margin rectangle. 
            Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); 
 
            // Restore the previous pen to the DC. 
            SelectObject(hdc, hdcOld); 
            return TRUE; 
 
        default: 
            return FALSE; 
    } 
    return TRUE; 
}

テキストの検索

このトピックでは、ユーザーが検索操作のパラメーターを指定できるように、[ 検索 ] ダイアログ ボックスを表示および管理するサンプル コードについて説明します。 ダイアログ ボックスは、検索操作を実行できるように、ウィンドウ プロシージャにメッセージを送信します。

[置換] ダイアログ ボックスを表示および管理するコードは、ReplaceText 関数を使用してダイアログ ボックスを表示する点を除き、似ています。 [ 置換 ] ダイアログ ボックスは、ユーザーが [ すべて置換 ] ボタンと [ すべて置換 ] ボタンをクリックしたときにもメッセージを送信します。

[ 検索 または 置換 ] ダイアログ ボックスを使用するには、次の 3 つの個別のタスクを実行する必要があります。

  1. FINDMSGSTRING 登録済みメッセージのメッセージ識別子を取得します。
  2. ダイアログ ボックスを表示します。
  3. ダイアログ ボックスが開いているときに FINDMSGSTRING メッセージを処理します。

アプリケーションを初期化するときは、 RegisterWindowMessage 関数を呼び出して 、FINDMSGSTRING 登録済みメッセージのメッセージ識別子を取得します。

UINT uFindReplaceMsg;  // message identifier for FINDMSGSTRING 

uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);

[検索] ダイアログ ボックスを表示するには、まず FINDREPLACE 構造体を初期化してから、FindText 関数を呼び出します。 FINDREPLACE 構造体と検索文字列のバッファーは、ダイアログ ボックスが閉じる前にスコープ外に出ないように、グローバル変数または静的変数である必要があることに注意してください。 登録されたメッセージを受信するウィンドウを指定するには、 hwndOwner メンバーを設定する必要があります。 ダイアログ ボックスを作成したら、返されたハンドルを使用してダイアログ ボックスを移動または操作できます。

FINDREPLACE fr;       // common dialog box structure
HWND hwnd;            // owner window
CHAR szFindWhat[80];  // buffer receiving string
HWND hdlg = NULL;     // handle to Find dialog box

// Initialize FINDREPLACE
ZeroMemory(&fr, sizeof(fr));
fr.lStructSize = sizeof(fr);
fr.hwndOwner = hwnd;
fr.lpstrFindWhat = szFindWhat;
fr.wFindWhatLen = 80;
fr.Flags = 0;

hdlg = FindText(&fr);

ダイアログ ボックスが開いているときは、メイン メッセージ ループに IsDialogMessage 関数の呼び出しを含める必要があります。 IsDialogMessage 呼び出しで、ダイアログ ボックスにパラメーターとしてハンドルを渡します。 これにより、ダイアログ ボックスでキーボード メッセージが正しく処理されます。

ダイアログ ボックスから送信されたメッセージを監視するには、ウィンドウ プロシージャで FINDMSGSTRING 登録済みメッセージをチェックし、次の例のように FINDREPLACE 構造体で渡された値を処理する必要があります。

LPFINDREPLACE lpfr;

if (message == uFindReplaceMsg)
{ 
    // Get pointer to FINDREPLACE structure from lParam.
    lpfr = (LPFINDREPLACE)lParam;

    // If the FR_DIALOGTERM flag is set, 
    // invalidate the handle that identifies the dialog box. 
    if (lpfr->Flags & FR_DIALOGTERM)
    { 
        hdlg = NULL; 
        return 0; 
    } 

    // If the FR_FINDNEXT flag is set, 
    // call the application-defined search routine
    // to search for the requested string. 
    if (lpfr->Flags & FR_FINDNEXT) 
    {
        SearchFile(lpfr->lpstrFindWhat,
                   (BOOL) (lpfr->Flags & FR_DOWN), 
                   (BOOL) (lpfr->Flags & FR_MATCHCASE)); 
    }

    return 0; 
}