이번에는 윈도 프로그래밍을 이용한 MFC 프로그래밍의 구조 및 간단한 예제에 대해서 알아보도록 하겠습니다.
.
.
.
MFC 프로그래밍의 구조는 크게 2가지로 나눌 수 있습니다.
.
1. WinMain() , 2. WinProc()
.
.
.
1. WinMain() 의 역할
WinMain() 부분은 윈도를 생성하고 메시지 전송을 담당하고 있습니다.
그밖에..
윈도 구조체, 클래스 만들기 : 윈도우 함수, 아이콘, 커서, 배경색
윈도우 구조체, 클래스를 등록하기 생성
윈도를 화면에 보이기
윈도에서 발생한 이벤트에 관한 메시지 보내기
클래스 생성과 커널에 등록
등등의 역할이 있습니다.
.
.
.
WinMain() 구조- 순차적 진행
WinMain()
{
윈도우 구조체 설정 및 등록 --> 한번만 수행
윈도우 생성과 출력
메시지 루프 --> 메시지가 없다면 Main() 종료 , 반복문이 있어야 함
}
.
.
.
.
.
2. WinProc()
WinProc() 부분은 메시지 처리(OS가 관여하고 실행) Call-back 함수
그 밖에..
메시지 처리
WM_xx , CB_xx, LM_xx, PBM_xx 등등이 있습니다.
메시지의 값은 positive integer로 (UINT형)입니다.
.
.
WinProc() 구조- 메시지 값을 분류하고 처리를 위해 switch 문이 활용
.
.
.
Switch(message)
{
case WM1:
break;
case WM2:
break;
default:
DefWndProc();
}
.
.
.
메시지 전달과 처리 과정
while( GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);// 메시지전달
}
WndProc(…, UINT msg, … )// CALLBACK 함수
{
return;
DIspatchMessage에서 메시지를 전달하여 CALLBACK 함수에게 전달해주고 메시지가 없을 때까지 계속 루프가 돕니다.
.
.
.
메시지 처리 과정
.
.
.
.
.
이렇게 MFC프로그래밍의 구조를 알아보았으므로
간단한 입출력문을 알아보도록 하겠습니다.
.
.
.
디바이스 콘텍스트
디바이스 콘텍스트(DC)를 얻고 해제 하기
BeginPaint()와 EndPaint()는 WM_PAINT 메시지가 발생했을 경우에만 사용합니다.
.
.
GetDC()와 ReleaseDC()는 잠시 출력할 때 사용합니다.
GetDC()를 사용했으면 사용 후 에는 반드시 ReleaseDC() 함수를 호출해 출력을 마쳤음을 알려야 합니다.
.
.
CreateDC()와 DeleteDC()
DC를 만들어서 사용합니다.
출력이 목적이 아니라 DC의 정보를 얻고자 할 때 사용합니다.
.
.
HDC
디바이스 콘텍스트 핸들이라고 부르며, 출력할 영역을 지정할 수 있는 타입입니다.
화면의 경우 윈도로부터 얻어 올 수 있습니다.
HDC의 변수는 출력할 영역을 얻어오면 얻어온 영역을 지정할 수 있습니다.
.
.
.
★ InvalidateRgn() ★
제가 생각하기에 MFC입출력에서 가장 많이 쓰이고 중요하다고도 생각하는 InvalidateRgn()은 화면 영역 수정 함수로, 이벤트를 처리하고 남은 WM_PAINT부분을 지울지 남길지를 결정하는 중요한 함수입니다.
.
.
BOOL InvalidateRgn(
HWND hwnd,
GRGN hRgn,
BOOL bErase
);
// hwnd : 수정 영역이 포함된 윈도우릐 핸들 값
// hRgn : 수정 영역에 대한 핸들 값으로 NULL을 주면 클라이언트 영역 전체를 수정하는데,
// 여기서는 주로 NULL 값을 이용합니다.
// bErase : 수정 영역을 모두 삭제하고 다시 그릴지, 수정 부분만 추가할지를 나타내는 bool값으로,
// true면 모두 삭제하고 false면 삭제하지 않습니다.
기본적인 입출력에 대해서 알아보았으며, 나머지는 예제를 통해서 알아보도록 하겠습니다.
.
.
.
좌표 (100,100)에 'i love you'를 출력하는 프로그램
#include <windows.h>
#include <TCHAR.H>
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 아이콘 변경
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 커서변경
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 색 변경
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass);
hwnd = CreateWindow(_T("Window Class Name"),
_T("Jung-story"), // 타이틀바 변경
WS_OVERLAPPEDWINDOW,
//// 윈도우 위치 변경
600,
400,
// 윈도우 크기 변경
600,
400,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (iMsg)
{
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
rect.left = 100;
rect.top = 100;
rect.right = 100;
rect.bottom = 100;
DrawText(hdc, _T("i love you"), -1, &rect, DT_NOCLIP | DT_LEFT);
EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
.
.
.
.
.
.
2. 중심 좌표가 (200,120)이고 반지름이 20인 원을 그려보자
.
.
.
#include <windows.h>
#include <TCHAR.H>
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 아이콘 변경
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 커서변경
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 색 변경
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass);
hwnd = CreateWindow(_T("Window Class Name"),
_T("Jung-Story"), // 타이틀바 변경
WS_OVERLAPPEDWINDOW,
600,
400,
600,
400,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HPEN hPen, oldPen;
HBRUSH hBrush, oldBrush;
RECT rect;
switch (iMsg)
{
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
hPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));
oldPen = (HPEN)SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(255, 0, 255));
oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Ellipse(hdc, 180, 100, 220, 140);
SelectObject(hdc, oldBrush);
DeleteObject(hBrush);
SelectObject(hdc, oldPen);
DeleteObject(hPen);
EndPaint(hwnd, &ps);
break;
case WM_KEYDOWN:
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
.
.
.
.
.
.
3. 방향키를 눌러 누르면 빨간색이 나오도록 때면 원상태로 돌아오도록 사각형 4개 만들기
#include <windows.h>
#include <TCHAR.H>
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 아이콘 변경
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 커서변경
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 색 변경
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass);
hwnd = CreateWindow(_T("Window Class Name"),
_T("Jung-Story"), // 타이틀바 변경
WS_OVERLAPPEDWINDOW,
600,
400,
600,
400,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush, oldBrush;
RECT rect1 = { 100,0,150,100 };
RECT rect2 = { 50,100,100,200 };
RECT rect3 = { 150,100,200,200 };
RECT rect4 = { 100,200,150,300 };
switch (iMsg)
{
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
Rectangle(hdc, 100, 0, 150, 100); // 위쪽
DrawText(hdc, _T("위쪽"), -1, &rect1, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
Rectangle(hdc, 50, 100, 100, 200); // 왼쪽
DrawText(hdc, _T("왼쪽"), -1, &rect2, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
Rectangle(hdc, 150, 100, 200, 200); // 오른쪽
DrawText(hdc, _T("오른쪽"), -1, &rect3, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
Rectangle(hdc, 100, 200, 150, 300); // 아래쪽
DrawText(hdc, _T("아래쪽"), -1, &rect4, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
break;
case WM_KEYDOWN: // 키가 눌렸을 때
hdc = GetDC(hwnd);
if (wParam == VK_UP) {
hBrush = CreateSolidBrush(RGB(255, 0, 0));
oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc, 100, 0, 150, 100); // 위쪽
SelectObject(hdc, oldBrush);
DeleteObject(hBrush);
}
else if (wParam == VK_LEFT) {
hBrush = CreateSolidBrush(RGB(255, 0, 0));
oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc, 50, 100, 100, 200); // 왼쪽
SelectObject(hdc, oldBrush);
DeleteObject(hBrush);
}
else if (wParam == VK_RIGHT) {
hBrush = CreateSolidBrush(RGB(255, 0, 0));
oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc, 150, 100, 200, 200); // 오른쪽
SelectObject(hdc, oldBrush);
DeleteObject(hBrush);
}
else if (wParam == VK_DOWN) {
hBrush = CreateSolidBrush(RGB(255, 0, 0));
oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc, 100, 200, 150, 300); // 아래쪽
SelectObject(hdc, oldBrush);
DeleteObject(hBrush);
}
ReleaseDC(hwnd, hdc);
break;
case WM_KEYUP: // 키가 눌렀다 뗐을때
hdc = GetDC(hwnd);
if (wParam == VK_UP) {
Rectangle(hdc, 100, 0, 150, 100); // 위쪽
DrawText(hdc, _T("위쪽"), -1, &rect1, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
else if (wParam == VK_LEFT) {
Rectangle(hdc, 50, 100, 100, 200); // 왼쪽
DrawText(hdc, _T("왼쪽"), -1, &rect2, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
else if (wParam == VK_RIGHT) {
Rectangle(hdc, 150, 100, 200, 200); // 오른쪽
DrawText(hdc, _T("오른쪽"), -1, &rect3, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
else if (wParam == VK_DOWN) {
Rectangle(hdc, 100, 200, 150, 300); // 아래쪽
DrawText(hdc, _T("아래쪽"), -1, &rect4, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
ReleaseDC(hwnd, hdc);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
.
.
.
'윈도우 프로그래밍 > MFC_프로그래밍' 카테고리의 다른 글
윈도우 프로그래밍 (MFC 비트맵 더블 버퍼링 bitmap 개념 및 예제) (0) | 2021.04.16 |
---|---|
윈도우 프로그래밍 (MFC 리소스 윈도우 메뉴 만들기 개념 및 예제) (0) | 2021.04.14 |
윈도우 프로그래밍 ( MFC 프로그래밍 제어 메시지 (키보드,마우스 입출력)처리 및 예제 ) (0) | 2021.04.02 |