Win32 - API - Dialog

[TOC]

다이얼로그

모달(Modal)과 모델리스(Modeless) 다이얼로그

모달 다이얼로그

모델리스(Modeless) 다이얼로그

다이얼로그 생성/종료

// 다이얼로그 생성
/*
HINSTANCE hInstance : 응용프로그램의 인스턴스 핸들러
LPCSTR lpTemplateName : 리소스 아이디 문자열
HWND hWndParent : 다이얼로그의 부모 윈도우 핸들러
DLGPROC lpDialogFunc : 다이얼로그 프로시저
LPARAM dwInitParam : 다이얼로그 초기화 인자값
*/
INT_PTR DialogBox(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);

// 예 - 다이얼로그 생성
DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);

// 다이얼로그 종료
/*
HWND hDlg : 다이얼로그 윈도우 핸들러
INT_PTR nResult : DialogBox() 함수의 리턴값
*/
BOOL EndDialog(HWND hDlg, INT_PTR nResult);

// 예 - 다이얼로그 종료
EndDialog(hWnd, 0);

다이얼로그 프로시저

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		return true;

	case WM_COMMAND:
		switch (wParam)
		{
		case IDOK:
		case IDCANCEL:
			EndDialog(hWnd, 0);
			return TRUE;
		default:
			break;
		}
	default:
		return FALSE;
		break;
	}
	return FALSE;
}

다이얼로그와 부모 윈도우의 데이터 전달

모달 다이얼로그로 데이터 변경하기

// 다이얼로그 박스 생성
// DialogBox의 반환값을 보고 성공/취소를 판단하여 처리한다.
// 반환값을 EndDialog의 두번째 파라미터로 넘기는 값이 반환된다.
if (DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc) != 0) {
	InvalidateRect(hWnd, NULL, TRUE);
};

// 다이얼로그 프로시저
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		// 다이얼로그 초기화 시 각 컨트롤러에 초기값을 넣어준다.
         // IDC_X, IDC_Y, IDC_STR는 Edit 컨트롤
		SetDlgItemInt(hWnd, IDC_X, g_nDialogX, FALSE);
		SetDlgItemInt(hWnd, IDC_Y, g_nDialogY, FALSE);
		SetDlgItemText(hWnd, IDC_STR, g_szDialogStr);
		return true;

	case WM_COMMAND:
		switch (wParam)
		{
		case IDOK:
			// 작업이 끝나고 다이얼로그창을 성공적으로 닫을 때 컨트롤러에 있는 값을 넣어준다.
			g_nDialogX = GetDlgItemInt(hWnd, IDC_X, NULL, FALSE);
			g_nDialogY = GetDlgItemInt(hWnd, IDC_Y, NULL, FALSE);
			GetDlgItemText(hWnd, IDC_STR, g_szDialogStr, 100);
			EndDialog(hWnd, 1); // DialogBox()의 리턴값이 1이 된다.
			break;
		case IDCANCEL:
			// 다이얼로그 작업을 취소할 경우 그대로 나간다.
			EndDialog(hWnd, FALSE); // DialogBox()의 리턴값이 0이 된다.
			return TRUE;
		default:
			break;
		}
	default:
		return FALSE;
		break;
	}
	return FALSE;
}

모델리스 다이얼로그로 데이터 변경하기

// 모델리스 다이얼로그 생성
// IsWindow() 함수로 현재 유효한 윈도우 핸들인지 확인한다.
if (IsWindow(g_hModelessDialog) == FALSE) {
	// CreateDialog()는 생성한 다이얼로그의 핸들을 바로 반환한다.
	g_hModelessDialog = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG2), hWnd, DialogProc_Modeless);

	// 다이얼로그를 생성했지만 아직 보이지 않기 때문에 화면에 보이도록 한다.
	// 디이얼로그 폼 속성에서 Visible 속성에 true(WS_VISIBLE 스타일)를 주었다면 
	// ShowWindow() 함수를 호출하지 않아도 되지만
	// 디폴트가 WS_VISIBLE 스타일이 아니므로 호출한다.
	ShowWindow(g_hModelessDialog, SW_SHOW);
}

// 모델리스 다이얼로그 프로시저
INT_PTR CALLBACK DialogProc_Modeless(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		SetDlgItemInt(hWnd, IDC_X, g_nDialogX, FALSE);
		SetDlgItemInt(hWnd, IDC_Y, g_nDialogY, FALSE);
		SetDlgItemText(hWnd, IDC_STR, g_szDialogStr);
		return true;

	case WM_COMMAND:
		switch (wParam)
		{
		case ID_CHANGE:
			g_nDialogX = GetDlgItemInt(hWnd, IDC_X, NULL, FALSE);
			g_nDialogY = GetDlgItemInt(hWnd, IDC_Y, NULL, FALSE);
			GetDlgItemText(hWnd, IDC_STR, g_szDialogStr, 100);
			InvalidateRect(g_hMainWnd, NULL, TRUE); // 데이터 변경을 메인윈도우의 화면에 반영
			break;
		case ID_CLOSE:
			DestroyWindow(g_hModelessDialog); // CreateDialog()로 열었으므로 DestroyWindow()로 닫는다.
			//EndDialog(hWnd, FALSE); // 닫히긴하지만 다시 열리지 않는다.
			return TRUE;
		default:
			break;
		}
	default:
		return FALSE;
		break;
	}
	return FALSE;
}

폼 기반의 윈도우 프로그래밍

#include "Windows.h"
#include "resource.h"

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow) {
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
	return 0;
}

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_COMMAND:
		switch (wParam)
		{
		case IDOK:
		case IDCANCEL:
			EndDialog(hWnd, 0);
			break;
		default:
			break;
		}
		break;

	default:
		break;
	}

	return false;
}

공통 대화상자(Common Dialog)

파일 열기 다이얼로그

OPENFILENAME 구조체
typedef struct tagOFNA {
   DWORD        lStructSize; // 
   HWND         hwndOwner; // 
   HINSTANCE    hInstance; // 
   LPCSTR       lpstrFilter; // 
   LPSTR        lpstrCustomFilter;
   DWORD        nMaxCustFilter;
   DWORD        nFilterIndex; // 
   LPSTR        lpstrFile; // 
   DWORD        nMaxFile; // 
   LPSTR        lpstrFileTitle; // 
   DWORD        nMaxFileTitle; // 
   LPCSTR       lpstrInitialDir; // 
   LPCSTR       lpstrTitle; // 
   DWORD        Flags; // 
   WORD         nFileOffset;
   WORD         nFileExtension; // 
   LPCSTR       lpstrDefExt;
   LPARAM       lCustData;
   LPOFNHOOKPROC lpfnHook;
   LPCSTR       lpTemplateName;
#ifdef _MAC
   LPEDITMENU   lpEditInfo;
   LPCSTR       lpstrPrompt;
#endif
#if (_WIN32_WINNT >= 0x0500)
   void *        pvReserved;
   DWORD        dwReserved;
   DWORD        FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAMEA, *LPOPENFILENAMEA;
파일 열기 다이얼로그 생성 - GetOpenFileName()
#include "Windows.h"
#include "resource.h"
#include <stdio.h> // sprintf_s()
#include <commdlg.h> // 없으면 GetOpenFileName() 호출 시 에러남

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

HINSTANCE g_hInstance;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow) {
	g_hInstance = hInstance;

	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);

	return 0;
}

//char lpstrFile[MAX_PATH];
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		SetWindowText(hWnd, "My Dialog");
		break;
	case WM_COMMAND:
		switch (wParam)
		{
		case IDOK:
		case IDCANCEL:
			EndDialog(hWnd, 0);
			break;
		case IDC_OPEN:
		{
			// static 또는 전역변수로 선언하지 않으면 다이얼로그가 열리지 않음
			static char lpstrFile[MAX_PATH];
			// static 또는 전역변수로 선언하지 않아도 다이얼로그가 열림(강의에서는 필요하다고 함)
			char lpstrFileTitle[MAX_PATH];

			OPENFILENAME ofn = { 0, };
			ofn.lStructSize = sizeof(OPENFILENAME);
			ofn.hwndOwner = hWnd;
			ofn.lpstrFilter = "Every File(*.*)\0*.*\0";
			ofn.lpstrFile = lpstrFile;
			ofn.lpstrFileTitle = lpstrFileTitle;
			ofn.nMaxFile = MAX_PATH;
			ofn.nMaxFileTitle = MAX_PATH;
			ofn.lpstrTitle = "title";
			ofn.lpstrInitialDir = "C:\\";

			if (GetOpenFileName(&ofn)) {
				char szResult[MAX_PATH];
				sprintf_s(szResult, "Path: %s\n%s", ofn.lpstrFile, ofn.lpstrFileTitle);
				MessageBox(hWnd, szResult, NULL, MB_OK);
			};
		}
		break;
		default:
			break;
		}
		break;

	default:
		break;
	}

	return false;
}
파일 저장 다이얼로그 생성 - GetSaveFileName()

이미지 뷰어(폼 기반)

#include "Windows.h"
#include "resource.h"

char g_szFile[MAX_PATH];
char g_szFileTitle[MAX_PATH];
HDC g_hMemDC;
BITMAP g_bitmapHeader;

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow) {

	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);

	return 0;
}

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);

		BitBlt(hdc, 0, 0, g_bitmapHeader.bmWidth, g_bitmapHeader.bmHeight, g_hMemDC, 0, 0, SRCCOPY);
		TextOut(hdc, 10, 200, g_szFile, strlen(g_szFile));
		TextOut(hdc, 10, 230, g_szFileTitle, strlen(g_szFileTitle));

		EndPaint(hWnd, &ps);
	}

	break;
	case WM_COMMAND:
		switch (wParam)
		{
		case IDOK:
		case IDCANCEL:
			EndDialog(hWnd, 0);
			break;
		case IDC_OPEN:
		{
			OPENFILENAME ofn = { 0, };
			ofn.lStructSize = sizeof(OPENFILENAME);
			ofn.hwndOwner = hWnd;
			ofn.lpstrFilter = "Image File(*.bmp)\0*.bmp\0";
			ofn.nFilterIndex = 1;
			ofn.lpstrFile = g_szFile;
			ofn.nMaxFile = MAX_PATH;
			ofn.lpstrFileTitle = g_szFileTitle;
			ofn.nMaxFileTitle = MAX_PATH;

			if (GetOpenFileName(&ofn) != 0) {
				strcpy_s(g_szFile, ofn.lpstrFile);
				strcpy_s(g_szFileTitle, ofn.lpstrFileTitle);

				// ===== Image Load =====
				// LoadImage
				HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, g_szFileTitle, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

				// bitmap 정보 읽기
				GetObject(hBitmap, sizeof(BITMAP), &g_bitmapHeader);

				// get current dc
				HDC hdc = GetDC(hWnd);

				// memory dc
				if (g_hMemDC != NULL) { // 해제하지 않아도 에러는 안난다.
					DeleteDC(g_hMemDC);
				}
				g_hMemDC = CreateCompatibleDC(hdc);

				// select object
				SelectObject(g_hMemDC, hBitmap);

				DeleteObject(hBitmap);
				ReleaseDC(hWnd, hdc);

				InvalidateRect(hWnd, NULL, true);
				// ===== Image Load ===== end
			};
		}
		default:
			break;
		}
		break;
	case WM_DESTROY:
		if (g_hMemDC != NULL) { // 해제하지 않아도 에러는 안난다.
			DeleteDC(g_hMemDC);
		}
		break;
	default:
		break;
	}

	return 0;
}