WINAPI - 대화상자
내장형 하드웨어/WINAPI / 2011. 9. 27. 15:35
- 대화상자는 프로그램과 사용자간의 대화, 곧 명령 및 정보 전달을 위한 특별한 윈도우이다.
- 대화 상자에는 버튼, 에디트 등의 컨트롤들이 배치되는데 그래서 대화상자를 컨트롤의 컨테이너라고도 한다.
- 사용자는 대화상자를 호출한 후 컨트롤을 통해 자신의 의사를 표시하고 명령을 내리며 프로그램은 대화상자에 배치된 컨트롤을 통해 션재 상태를 사용자에게 보여준다.
- 카드놀이 게임의 옵션 대화상자를 예로 들어 생각해 보면
→ 카드놀이 게임은 이 대화상자를 통해 현재 설정된 옵션 정보를 사용자에게 보여주고
→ 사용자는 이 대화상자에 배치된 라디오 버튼, 체크 박스 등의 컨트롤로 옵션을 변경하라는 명령을 내린다.
→ 즉, 대화상자를 통해 프로그램과 사용자가 양방향으로 대화를 하는 것
- 대화상자는 동작 방식에 따라 모달형과 모델리스형으로 나뉘어 진다.
→ 모달(Modal)형은 대화상자를 닫기 전에 다른 윈도우로 전환할 수 업으며 반드시 확인(또는 OK) 버튼이나 취소(또는 Cancel) 버튼을 눌러 대화상자를 닫아야 다른 윈도우로 전환할 수 있다.
→ 모델리스(Modeless) 형은 대화상자를 열어 놓은 채로 다른 윈도우로 전환할 수 있는 대화상자이다. 프로그램의 상태를 나타내거나 작업을 하면서 참조해야 할 여러가지 정보를 표시하는 윈도우가 모델리스형으로 만드어 진다.
→ 개발자 입장에서는 다른 작업을 하면서도 열려 있을 수 있기 때문에 어려가지 문제가 생길 수 있으며 프로그래밍하기 훨씬 더 까다롭다.
- 실습(About)
- 대화상자를 만들기 위해서는 기본적으로 다음 두가지가 있어야 한다.
→ 대화상자 템플릿 : 대화상자의 모양과 대화상자 내의 컨트롤 배치 상태가 저장되는 이진 정보이며 리소스로 작성된다. 개발자 스튜디오에 별도의 대화상자 편집기가 제공된다.
→ 대화상자 프로시저 : 윈도우 프로시저가 윈도우에서 발생하는 메시지를 처리하는 것과 마찬가지로 대화상자 프로시저는 대화상자에서 발생하는 메시지를 처리한다.
- 작성
→ About 프로젝트를 만들고 About.cpp 소스 파일을 추가한 후 ApiStart.txt 파일을 복사해 붙인다. lpszClass "About"으로 변경해 둔다.
→ 대화상자의 겉모습을 만들기 위해 대화상자 템플릿 리소스를 작성한다. About.rc 리소스 스크립트를 먼저 추가하고 리소스 추가 대화상자에서 Dialog를 선택한다. 그러면 IDD_DIAGLOG1이라는이름을 가지는 빈 대화상자와 컨트롤 도구모음이 열린다.
→ 각 편집기의 컨트롤 도구 모음에서 여러 컨트롤을 선택할 수 있는데 이중 Static Text를 선택후 대화상자의 적당한 곳을 클릭하여 문자열을 대화상자에 배치한다.
→ 대화상자에 배치된 스태틱 컨트롤의 팝업 메뉴에서 속성(Properties)를 선택하면 속성 편집기가 열린다.
→ Caption에 원하는 문자열을 입력한다.
→ 리소스 파일에 대화상자 탬플릿 이 포함되었으며 이 템플릿에서는 대화상자와 대화상자에 배치된 컨트롤에 관한 정보가 기록되어 있다. 실행중에 대화상자를 만들면 이 정보대로 컨트롤을 생성하고 스타일을 설정할 것이다.
→ 다음 소스는 WndProc에서 함수를 참조하므로 WinMain과 WndProc 사이에 작성해야 한다.
- 대화 상자 프로젝트
→ 대화상자가 메인 윈도우가 되는 형태의 프로그램을 대화상자 기반의 프로그램(Dialog Base)라고 하며 컨트롤을 많이 사용하는 프로그램들이 주로 대화상자 기반으로 만들어 진다.
- 대화 상자에는 버튼, 에디트 등의 컨트롤들이 배치되는데 그래서 대화상자를 컨트롤의 컨테이너라고도 한다.
- 사용자는 대화상자를 호출한 후 컨트롤을 통해 자신의 의사를 표시하고 명령을 내리며 프로그램은 대화상자에 배치된 컨트롤을 통해 션재 상태를 사용자에게 보여준다.
- 카드놀이 게임의 옵션 대화상자를 예로 들어 생각해 보면
→ 카드놀이 게임은 이 대화상자를 통해 현재 설정된 옵션 정보를 사용자에게 보여주고
→ 사용자는 이 대화상자에 배치된 라디오 버튼, 체크 박스 등의 컨트롤로 옵션을 변경하라는 명령을 내린다.
→ 즉, 대화상자를 통해 프로그램과 사용자가 양방향으로 대화를 하는 것
- 대화상자는 동작 방식에 따라 모달형과 모델리스형으로 나뉘어 진다.
→ 모달(Modal)형은 대화상자를 닫기 전에 다른 윈도우로 전환할 수 업으며 반드시 확인(또는 OK) 버튼이나 취소(또는 Cancel) 버튼을 눌러 대화상자를 닫아야 다른 윈도우로 전환할 수 있다.
→ 모델리스(Modeless) 형은 대화상자를 열어 놓은 채로 다른 윈도우로 전환할 수 있는 대화상자이다. 프로그램의 상태를 나타내거나 작업을 하면서 참조해야 할 여러가지 정보를 표시하는 윈도우가 모델리스형으로 만드어 진다.
→ 개발자 입장에서는 다른 작업을 하면서도 열려 있을 수 있기 때문에 어려가지 문제가 생길 수 있으며 프로그래밍하기 훨씬 더 까다롭다.
- 실습(About)
- 대화상자를 만들기 위해서는 기본적으로 다음 두가지가 있어야 한다.
→ 대화상자 템플릿 : 대화상자의 모양과 대화상자 내의 컨트롤 배치 상태가 저장되는 이진 정보이며 리소스로 작성된다. 개발자 스튜디오에 별도의 대화상자 편집기가 제공된다.
→ 대화상자 프로시저 : 윈도우 프로시저가 윈도우에서 발생하는 메시지를 처리하는 것과 마찬가지로 대화상자 프로시저는 대화상자에서 발생하는 메시지를 처리한다.
- 작성
→ About 프로젝트를 만들고 About.cpp 소스 파일을 추가한 후 ApiStart.txt 파일을 복사해 붙인다. lpszClass "About"으로 변경해 둔다.
→ 대화상자의 겉모습을 만들기 위해 대화상자 템플릿 리소스를 작성한다. About.rc 리소스 스크립트를 먼저 추가하고 리소스 추가 대화상자에서 Dialog를 선택한다. 그러면 IDD_DIAGLOG1이라는이름을 가지는 빈 대화상자와 컨트롤 도구모음이 열린다.
→ 각 편집기의 컨트롤 도구 모음에서 여러 컨트롤을 선택할 수 있는데 이중 Static Text를 선택후 대화상자의 적당한 곳을 클릭하여 문자열을 대화상자에 배치한다.
→ 대화상자에 배치된 스태틱 컨트롤의 팝업 메뉴에서 속성(Properties)를 선택하면 속성 편집기가 열린다.
→ Caption에 원하는 문자열을 입력한다.
→ 리소스 파일에 대화상자 탬플릿 이 포함되었으며 이 템플릿에서는 대화상자와 대화상자에 배치된 컨트롤에 관한 정보가 기록되어 있다. 실행중에 대화상자를 만들면 이 정보대로 컨트롤을 생성하고 스타일을 설정할 것이다.
→ 다음 소스는 WndProc에서 함수를 참조하므로 WinMain과 WndProc 사이에 작성해야 한다.
//main.cpp
#include<windows.h>
#include "MsgProc.h" // add
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("About");
// add
typedef struct MESSAGEMAP
{
UINT iMessage;
LRESULT (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
}MESSAGEMAP;
////////////////////////////
//CALLBACKAboutDlgProc
typedef struct DLGMESSAGEMAP
{
UINT iMessage;
BOOL (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
}DLGMESSAGEMAP;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst = hInstance;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc;
WndClass.lpszClassName = lpszClass;
WndClass.lpszMenuName = NULL;
WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
RegisterClass(&WndClass);
hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);;
ShowWindow(hWnd, nCmdShow);
while(GetMessage(&Message, NULL, 0, 0))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
//add
int i;
static MESSAGEMAP MessageMaps[] = {
{WM_CREATE, OnCreate},
{WM_COMMAND, OnCommand},
{WM_LBUTTONDOWN, OnLButtonDown},
{WM_RBUTTONDOWN, OnRButtonDown},
{WM_MOUSEMOVE, OnMouseMove},
{WM_LBUTTONUP, OnLButtonUp},
{WM_LBUTTONDBLCLK, OnLButtonBlclk},
{WM_CHAR, OnChar},
{WM_HSCROLL, OnHscroll},
{WM_PAINT, OnPaint},
{WM_DESTROY, OnDestroy}
};
for(i=0; i<sizeof(MessageMaps)/sizeof(MessageMaps[0]); ++i)
{
if(MessageMaps[i].iMessage == iMessage)
{
return (*MessageMaps[i].lpfnMsgProc)(hWnd, wParam, lParam);
}
}
///////////////////////////
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT iMessage, WPARAM wParam, LPARAM lParam)
{
int i;
static DLGMESSAGEMAP DlgMessageMaps[] = {
{WM_INITDIALOG, OnInitDialog},
{WM_COMMAND, OnDlgCommand}
};
for(i=0; i<sizeof(DlgMessageMaps)/sizeof(DlgMessageMaps[0]); ++i)
{
if(DlgMessageMaps[i].iMessage == iMessage)
return (*DlgMessageMaps[i].lpfnMsgProc)(hDlg, wParam, lParam);
}
return FALSE;
}
#include<windows.h>
#include "MsgProc.h" // add
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("About");
// add
typedef struct MESSAGEMAP
{
UINT iMessage;
LRESULT (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
}MESSAGEMAP;
////////////////////////////
//CALLBACKAboutDlgProc
typedef struct DLGMESSAGEMAP
{
UINT iMessage;
BOOL (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
}DLGMESSAGEMAP;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst = hInstance;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc;
WndClass.lpszClassName = lpszClass;
WndClass.lpszMenuName = NULL;
WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
RegisterClass(&WndClass);
hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);;
ShowWindow(hWnd, nCmdShow);
while(GetMessage(&Message, NULL, 0, 0))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
//add
int i;
static MESSAGEMAP MessageMaps[] = {
{WM_CREATE, OnCreate},
{WM_COMMAND, OnCommand},
{WM_LBUTTONDOWN, OnLButtonDown},
{WM_RBUTTONDOWN, OnRButtonDown},
{WM_MOUSEMOVE, OnMouseMove},
{WM_LBUTTONUP, OnLButtonUp},
{WM_LBUTTONDBLCLK, OnLButtonBlclk},
{WM_CHAR, OnChar},
{WM_HSCROLL, OnHscroll},
{WM_PAINT, OnPaint},
{WM_DESTROY, OnDestroy}
};
for(i=0; i<sizeof(MessageMaps)/sizeof(MessageMaps[0]); ++i)
{
if(MessageMaps[i].iMessage == iMessage)
{
return (*MessageMaps[i].lpfnMsgProc)(hWnd, wParam, lParam);
}
}
///////////////////////////
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT iMessage, WPARAM wParam, LPARAM lParam)
{
int i;
static DLGMESSAGEMAP DlgMessageMaps[] = {
{WM_INITDIALOG, OnInitDialog},
{WM_COMMAND, OnDlgCommand}
};
for(i=0; i<sizeof(DlgMessageMaps)/sizeof(DlgMessageMaps[0]); ++i)
{
if(DlgMessageMaps[i].iMessage == iMessage)
return (*DlgMessageMaps[i].lpfnMsgProc)(hDlg, wParam, lParam);
}
return FALSE;
}
// MsgProc.cpp
#include "MsgProc.h"
#include "resource.h"
HWND hWndMain;
LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
hWndMain = hWnd;
return 0;
}
LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG1),hWnd,AboutDlgProc);
return 0;
}
LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnLButtonBlclk(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnChar(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnHscroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
hdc=BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
}
LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
/////////////////////////////////////////////////////////////////////////////////
BOOL OnInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
return TRUE;
}
BOOL OnDlgCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg,IDOK);
break;
case IDCANCEL:
EndDialog(hDlg,IDCANCEL);
break;
}
return TRUE;
}
#include "MsgProc.h"
#include "resource.h"
HWND hWndMain;
LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
hWndMain = hWnd;
return 0;
}
LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG1),hWnd,AboutDlgProc);
return 0;
}
LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnLButtonBlclk(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnChar(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnHscroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0;
}
LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
hdc=BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
}
LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
/////////////////////////////////////////////////////////////////////////////////
BOOL OnInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
return TRUE;
}
BOOL OnDlgCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg,IDOK);
break;
case IDCANCEL:
EndDialog(hDlg,IDCANCEL);
break;
}
return TRUE;
}
→ 실행 결과
- 대화 상자 프로젝트
→ 대화상자가 메인 윈도우가 되는 형태의 프로그램을 대화상자 기반의 프로그램(Dialog Base)라고 하며 컨트롤을 많이 사용하는 프로그램들이 주로 대화상자 기반으로 만들어 진다.
#include<windows.h>
#include "resource.h"
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam);
HWND hDlgMain;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), HWND_DESKTOP, MainDlgProc);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage)
{
case WM_INITDIALOG:
hDlgMain = hDlg;
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, IDOK);
return TRUE;
}
return FALSE;
}
return FALSE;
}
→ 실행 결과#include "resource.h"
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam);
HWND hDlgMain;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), HWND_DESKTOP, MainDlgProc);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage)
{
case WM_INITDIALOG:
hDlgMain = hDlg;
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, IDOK);
return TRUE;
}
return FALSE;
}
return FALSE;
}
'내장형 하드웨어 > WINAPI' 카테고리의 다른 글
WINAPI - DlgCheck (0) | 2011.09.29 |
---|---|
WINAPI - 컨트롤과의 통신 (0) | 2011.09.28 |
WINAPI - 스크롤 바 (0) | 2011.09.26 |
WINAPI - EDIT (1) | 2011.09.23 |
WINAPI - Static (1) | 2011.09.22 |