반응형

이번에는 윈도 프로그래밍을 이용한 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);
}

.

.

.

방향키 위를 눌렀을 경우 
눌렀다가 땠을 경우

반응형

+ Recent posts