Share via


일반 대화 상자 사용

이 섹션에서는 일반적인 대화 상자를 호출하는 작업에 대해 설명합니다.

색 선택

이 항목에서는 사용자가 색을 선택할 수 있도록 대화 상자를 표시하는 샘플 코드에 대해 설명합니다. 샘플 코드는 먼저 CHOOSECOLOR 구조를 초기화한 다음 ChooseColor 함수를 호출하여 대화 상자를 표시합니다. 함수가 사용자가 색을 선택했음을 나타내는 TRUE를 반환하는 경우 샘플 코드는 선택한 색을 사용하여 새 단색 브러시를 만듭니다.

이 예제에서는 CHOOSECOLOR 구조를 사용하여 다음과 같이 대화 상자를 초기화합니다.

  • 값의 정적 배열에 대한 포인터를 사용하여 lpCustColors 멤버를 초기화합니다. 배열의 색은 처음에는 검은색이지만 정적 배열은 후속 ChooseColor 호출을 위해 사용자가 만든 사용자 지정 색을 유지합니다.
  • CC_RGBINIT 플래그를 설정하고 rgbResult 멤버를 초기화하여 대화 상자가 열릴 때 처음에 선택된 색을 지정합니다. 지정하지 않으면 초기 선택 영역이 검은색으로 표시됩니다. 이 예제에서는 rgbCurrent 정적 변수를 사용하여 SelectColor 호출 간에 선택한 값을 유지합니다.
  • 대화 상자의 사용자 지정 색 확장이 항상 표시되도록 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 플래그를 설정합니다.

SelectFontTRUE를 반환하여 사용자가 확인 단추를 클릭했음을 나타내는 경우 SELECTFONT 구조에는 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);
 .
 .
 .
}

파일 열기

참고

Windows Vista부터 일반 파일 대화 상자는 파일을 여는 데 사용할 때 공통 항목 대화 상자로 대체되었습니다. 공통 파일 대화 상자 API 대신 공통 항목 대화 상자 API를 사용하는 것이 좋습니다. 자세한 내용은 일반 항목 대화 상자를 참조하세요.

이 항목에서는 사용자가 열 파일의 드라이브, 디렉터리 및 이름을 지정할 수 있도록 열기 대화 상자를 표시하는 샘플 코드에 대해 설명합니다. 샘플 코드는 먼저 OPENFILENAME 구조를 초기화한 다음 GetOpenFileName 함수를 호출하여 대화 상자를 표시합니다.

이 예제에서 lpstrFilter 멤버는 사용자가 표시되는 파일 이름을 제한하기 위해 선택할 수 있는 두 개의 파일 이름 필터를 지정하는 버퍼에 대한 포인터입니다. 버퍼에는 각 문자열 쌍이 필터를 지정하는 문자열의 이중 null 종료 배열이 포함되어 있습니다. nFilterIndex 멤버는 대화 상자를 만들 때 첫 번째 패턴이 사용되도록 지정합니다.

다음은 Flags 멤버에서 OFN_PATHMUSTEXISTOFN_FILEMUSTEXIST 플래그를 설정하는 예제입니다. 이러한 플래그로 인해 대화 상자에서 반환하기 전에 사용자가 지정한 경로와 파일 이름이 실제로 존재하는지 확인합니다.

GetOpenFileName 함수는 사용자가 확인 단추를 클릭하고 지정된 경로와 파일 이름이 있는 경우 TRUE를 반환합니다. 이 경우 lpstrFile 멤버가 가리키는 버퍼에는 경로와 파일 이름이 포함됩니다. 샘플 코드는 함수 호출에서 이 정보를 사용하여 파일을 엽니다.

이 예제에서는 OFN_EXPLORER 플래그를 설정하지 않지만 여전히 기본 Explorer 스타일 열기 대화 상자를 표시합니다. 그러나 후크 프로시저 또는 사용자 지정 템플릿을 제공하고 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 멤버에서 선택한 프린터에 디바이스 컨텍스트 핸들을 반환합니다. 핸들을 사용하여 프린터에서 출력을 렌더링할 수 있습니다.

입력 시 샘플 코드는 hDevModehDevNames 멤버를 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);
}

인쇄 속성 시트 사용

이 항목에서는 사용자가 문서 인쇄 옵션을 선택할 수 있도록 인쇄 속성 시트를 표시하는 샘플 코드에 대해 설명합니다. 샘플 코드는 먼저 PRINTDLGEX 구조를 초기화한 다음 PrintDlgEx 함수를 호출하여 속성 시트를 표시합니다.

샘플 코드는 PRINTDLG 구조체의 Flags 멤버에 PD_RETURNDC 플래그를 설정합니다. 그러면 PrintDlgEx 함수가 hDC 멤버에서 선택한 프린터에 디바이스 컨텍스트 핸들을 반환합니다.

입력 시 샘플 코드는 hDevModehDevNames 멤버를 NULL로 설정합니다. 함수가 S_OK 반환하는 경우 이러한 멤버는 프린터에 대한 사용자 입력 및 정보를 포함하는 DEVNAMES 구조체에 대한 핸들을 반환합니다. 이 정보를 사용하여 선택한 프린터로 보낼 출력을 준비할 수 있습니다.

인쇄 작업이 완료되면 샘플 코드는 DEVMODE, DEVNAMESPRINTPAGERANGE 버퍼를 해제하고 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 플래그를 설정하여 대화 상자가 여백 크기를 10000인치 단위로 표현하도록 합니다.

입력 시 샘플 코드는 hDevModehDevNames 멤버를 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 함수를 사용하여 대화 상자를 표시한다는 점을 제외하고 비슷합니다. 바꾸기 대화 상자는 모두 바꾸기 및바꾸기 단추의 사용자 클릭에 대한 응답으로 메시지를 보냅니다.

찾기 또는 바꾸기 대화 상자를 사용하려면 다음 세 가지 작업을 수행해야 합니다.

  1. FINDMSGSTRING 등록된 메시지에 대한 메시지 식별자를 가져옵니다.
  2. 대화 상자를 표시합니다.
  3. 대화 상자가 열릴 때 FINDMSGSTRING 메시지를 처리합니다.

애플리케이션을 초기화할 때 RegisterWindowMessage 함수를 호출하여 FINDMSGSTRING 등록된 메시지에 대한 메시지 식별자를 가져옵니다.

UINT uFindReplaceMsg;  // message identifier for FINDMSGSTRING 

uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);

찾기 대화 상자를 표시하려면 먼저 FINDREPLACE 구조를 초기화한 다음 FindText 함수를 호출합니다. FINDREPLACE 구조체와 검색 문자열의 버퍼는 대화 상자가 닫히기 전에 scope 나가지 않도록 전역 또는 정적 변수여야 합니다. 등록된 메시지를 받는 창을 지정하려면 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; 
}