본문 바로가기
코스웨어/15년 스마트컨트롤러

2015-11-18 Win32 API 개인업무일지 - 천정호

by 알 수 없는 사용자 2015. 11. 18.
728x90
반응형

CreateFont

폰트를 지정하지 않고 문자열을 출력하면 기본 설정 폰트로 문자열을 출력한다. 하지만 폰트를 만들고 DC로 전송한 후 문자열을 출력하면 DC에 전송된 폰트를 사용하여 문자열이 출력된다. 기본 설정 폰트말고 다른 폰트를 사용할시에는 먼저 폰트 Object를 만들어 DC로 전송하여야 한다.

폰트를 만들기 위해서는 CreateFont 함수를 사용하여 함수가 반환해주는 핸들을 HFONT형 변수에 대입해주면 된다.


CreateFont 함수의 원형

HFONT CreateFont( int nHeight, 

int nWidth, 

int nEscapement, 

int nOrientation, 

int unweight

DWORD fdwItalic, 

DWORD fdwUnderline, 

DWORD fdwStrikeOut, 

DWORD fdwCharSet, 

DWORD fdwOutputPrecision, 

DWORD fdwClipPrecision, 

DWORD fdwQuality, 

DWORD fdwPitchAndFamily, 

LPCTSTR lpszFace ); 


CreateFont 함수의 인자와 설명

인수설명
nHeight폰트의 높이를 논리적인 단위로 지정한다. 이 값이 0일 경우는 디폴트 크기가 사용된다.
hWidth폰트의 폭을 지정하되 이 값이 0이면 nHeight에서 지정한 높이에 따라 폭을 자동으로 결정한다. 즉 이 값이 0이면 폰트의 종횡비(장평)가 일정하다.
nEscapement폰트의 각도를 0.1도 단위로 설정한다. 이 각도는 문자가 출력될 X출과 문자열과의 각도이며 일상적인 360분법의 각도 체계를 사용한다. 즉 세시 방향이 0도로 사용되며 반시계 방향으로 각도가 증가한다.
nOrientation글자 한자와 X축과의 각도를 지정한다. nEscapement는 전체 문자열의 기울기를 지정하는데 비해 이 인수는 개별 문자의 기울기를 설정한다.
nWeight폰트의 무게를 0~1000까지의 값으로 설정한다. 쉽게 말해서 폰트의 두께를 설정한다. 0~1000까지의 값을 지정할 수 있으며 보통 굵기인 FW_NORMAL이 400이다.
bItalic, bUnderline, cStrikeOut기울임체, 밑줄, 관통선 속성을 설정한다. 데이터형이 BYTE이지만 불린형처럼 사용한다. 속성을 주고 싶으면 0 이외의 값(TRUE)를 주고 속성을 주지 않으려면 0(FALSE)를 준다.
nCharSet문자 셋을 설정한다. 여러 가지 값이 있지만 실제 사용될 수 있는 옵션은 ANSI_CHARSET과 OEM_CHARSET가 있다. ANSI_CHARSET가 윈도우즈에서 사용하는 문자셋이고 OEM_CHARSET가 도스에서 사용하는 문자셋이라고 생각하면 된다.
nOutPrecision출력 정확도를 설정한다.
nClipPrecision클리핑 정확도를 설정한다.
nQuality논리적 폰트를 물리적 폰트에 얼마나 근접시킬 것인가를 지정한다.
nPitchAndFamily폰트의 피치와 그룹을 설정한다.
lpszFacename글꼴의 이름을 나타내는 문자열을 설정한다.

방식 1

방식 2


String Color

글자의 색을 변경하는 함수

COLORREF SetTextColor( HDC hdc, COLORREF crColor );

글자의 배경을 변경하는 함수
COLORREF SetBkColor( HDC hdc, COLORREF crColor );

배경색상을 사용할 방법을 설정하는 함수
int SetBkMode( HDC hdc, int iBkMode );

SetBkMode의 인자값과 설명

옵션의 선택이 없으면 기본 설정인 OPAQUE로 설정된다.

인수설명
OPAQUE불투명한 배경을 사용한다. 그래서 배경 색상에 의해 뒷쪽의 그림이 지워진다. 이 모드가 디폴트이다.
TRANSPARENT투명한 배경색상을 사용한다. 그래서 문자를 출력한 후에도 배경이 바뀌지 않는다. 즉 문자 사이 사이의 여백에 있는 원래 배경이 지워지지 않는다.





PushPush Game

Message Map
Map Mapping
파일 분할


Win32.h

 

#ifndef __WIN32_H__

#define __WIN32_H__


#include <Windows.h>

#include "resource.h"



typedef struct _MsgMap {


UINT uiMsg;

LRESULT(*FP)(HWND, WPARAM, LPARAM);


}ST_MsgMap;


HINSTANCE g_hInst;


static HDC MemDC;

static PAINTSTRUCT Ps;


static HBITMAP HbmFront;

static HBITMAP HbmLeft;

static HBITMAP HbmRight;

static HBITMAP HbmBack;

static HBITMAP HbmGround;

static HBITMAP HbmRoad;

static HBITMAP HbmHero;

static HBITMAP HbmBox;

static HBITMAP HbmDot;


// 배경의 한조각 크기

#define XTILE 48

#define YTILE 48


// 한번에 이동가능한 공간 크기

#define XMOVE XTILE

#define YMOVE YTILE


// 가로 세로의 타일 개수

#define XFRAME 15

#define YFRAME 10


// 창의 가로, 세로의 크기

#define XSIZE (XTILE * XFRAME)

#define YSIZE (YTILE * YFRAME)


// 전체 창의 크기

#define XWINSIZE (XSIZE + 16)

#define YWINSIZE (YSIZE + 38)


int iX_Pos;

int iY_Po



// unsigned cahr Type

// 문자열로 저장되므로 + 1을 해야한다.

UCHAR ucMap[YFRAME][XFRAME + 1] = { "###############",

"# ####     ####",

"# ######## ####", 

"#     #### ####",

"##### #### ####",

"##### #    ###",

"##### # #######",

"##    # #######",

"##      #######",

"###############" };



// --------------------     함수의 선언부     -------------------- //

// LRESULT - 반환값을 의미 L(Long) RESULT(반환값)

// CALLBACK은 Complie 후에 사라지며, OS가 함수를 호출한다라는 뜻

// CALLBACK은 STD Call, CDECL Call 둘 중의 하나의 호출 방식을 결정

// 함수의 이름 - WndProc

// 첫 번째 인자 - HWND 구조체 Window Handler

// 두 번째 인자 - unsigned int 자료형의 Typedef 형식

// 세 번째 인자 - Word Parameter로 키보드로부터 입력받은 문자를 저장

// 네 번째 인자 - Long Parameter로 마우스의 X, Y 좌표 값을 저장

// Word Parameter, Long Parameter는 모두  4Byte로 동작

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

LRESULT ON_DISTORY(HWND, WPARAM, LPARAM);

LRESULT ON_CREATE(HWND, WPARAM, LPARAM);

LRESULT ON_PAINT(HWND, WPARAM, LPARAM);

LRESULT ON_KEYDOWN(HWND, WPARAM, LPARAM);



#endif /* __WIN32_H__ */



WinMain.c 

 

// 문자열 시작 " 앞에 L은 Win32에서 문자 하나는 2Byte 단위로 인식을 한다.

// 문자열 시작 " 앞에 L을 사용하지 않으면 Compiler가 1Byte ASCII Code를 2Byte 유니코드로 인식하기 때문이다.

// 문자열 시작 " 앞에 L을 사용하여 Compiler가 1byte ASCII Code를 2byte 유니코드로 변경하여 Compile하게 한다.

// 방법은 L, TEXT, _T 세 가지가 존재한다.


#include "Win32.h"


// 창 설정 지정 옵션

// 타이틀바, 수평 수직 스크롤, 최소 최대화 버튼

// 시스템 메뉴, 크기조절 경계선 등의 옵션이 존재한다.

#define WS_OVERLAPPEDWINDOW ( WS_OVERLAPPED |\

WS_CAPTION |\

WS_SYSMENU |\

WS_MINIMIZEBOX )


/*

#define WS_OVERLAPPEDWINDOW ( WS_OVERLAPPED |\

WS_CAPTION |\

WS_SYSMENU |\

WS_THICKFRAME |\

WS_MINIMIZEBOX |\

WS_MAXIMIZEBOX |\

WS_HSCROLL |\

WS_VSCROLL )

*/


// --------------------     전역변수 선언     -------------------- //

// LPSTR -> Long Pointer String 형식으로 해당 Class의 이름을 저장

LPSTR lpszClass = L"First";


// --------------------     Entry Point     -------------------- //

// APIENTRY -> Entry Point를 의미한다.

// WinMain - Entry Code에서는 Application의 설정을 담당한다.

// HINSTANCE hPrevInstance - 고전방식이라 인자만 넣어주는 것이지 거의 사용하지 않는다.

// LPSTR lpszCmdParam - C에서 Main 함수의 문자열 매개변수와 비슷한 역할을 한다.

// int nCmdShow - 해당 인자값을 통하여 창을 보일것인지 숨길것인지를 설정한다.

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) {

HWND hWnd;

MSG Message;

// WindowClass 구조체로 기본 설정정보를 담는 역할을 한다.

WNDCLASS WndClass;

// 프로그램 실행시 HINSTANCE hInstance 인자에 OS가 임의의 값을 대입

// hInstance 인자 값을 전역변수에 대입하여 모두 사용이 가능하다.

g_hInst = hInstance;


// WindowClass 구조체 멤버 초기화

WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;


// 창의 기본 배경색 결정

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

// 마우스 커서모양 결정

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

// 창의 아이콘 설정

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

// 구조체 hInstance 멤버에 인자의 값 대입

WndClass.hInstance = hInstance;

// 함수 주소를 가지는 멤버 - Long Pointer Function WndProc

// lpfnWndProc 멤버는 OS가 보내는 메세지를 받는 WndProc 함수의 주소를 가짐

// WndProc 함수는 사용자가 만드는 함수로 사용자에 따라 함수의 이름은 변경 가능

WndClass.lpfnWndProc = (WNDPROC)WndProc;

// 실행중인 하나의 영역을 클래스라 함

// 창의 구분은 클래스에 이름을 부여하여 구분

WndClass.lpszClassName = lpszClass;

// 메뉴 이름

WndClass.lpszMenuName = NULL;

// 창의 가로와 세로의 값을 재설정

WndClass.style = CS_HREDRAW | CS_VREDRAW;

// 창의 정보를 받아서 설정하는 레지스터 함수

// 창의 정보를 등록하면 Register 함수는 사용X

RegisterClass(&WndClass);


// 인자가 많을때 하나의 인자마다 줄을 바꾸어 구분

// 첫 번째 인자 - 클래스 이름 설정

// 두 번째 인자 - 창 제목 설정

// 세 번째 인자 - 창 스타일 설정(타이틀바, 스크롤, 최소화, 최대화 등)

// 네 번째 ~ 다섯 번째 인자 -  창의 시작 X, Y 좌표와 가로, 세로의 길이를 설정

// CW_USEDEFAULT 네 개는 가로, 세로 시작점 설정으로 모두 0으로 설정하면 OS가 자동으로 위치를 잡는다.

hWnd = CreateWindow(lpszClass,

L"Windows API",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,

CW_USEDEFAULT,

XWINSIZE,

YWINSIZE,

NULL,

(HMENU)NULL,

hInstance,

NULL);


/*

// 기본 CreateWindow

hWnd = CreateWindow(lpszClass,

lpszClass,

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

NULL,

(HMENU)NULL,

hInstance,

NULL);

*/


// 창을 보일것인지, 숨길것인지를 결정하는 함수

// WinProc의 nCmdShow인자를 통하여 결정된다.

ShowWindow(hWnd, nCmdShow);


// --------------------     메세지 처리의 반복     -------------------- //

// Windows의 메세지 전송과정은 원형 큐 원리로 동작

// Windows가 보낸 메세지가 너무 많아 Application이 처리를 못할시에는 

// 가장 최근의 메세지를 받으려고 한다.


// Windows와 반대 방식 RTOS - OS가 보내는 메세지를 모두 다 처리


// GetMessage가 Windows에서 보낸 메세지를 모두 받는다.

// 메세지의 내용이 0이면 종료 -> 프로그램 종료

// 큐에서 가져온 메세지를 첫 번째 인자에 저장

while (GetMessage(&Message, 0, 0, 0)) {

// 메세지를 가장 먼저 처리하는 함수

TranslateMessage(&Message);

// TranslateMessage가 처리 못한 메세지를 DispatchMessage 함수가 처리한다.

DispatchMessage(&Message);

}

// wParam을 확인하여 정상 종료인지 비정상 종료인지를 판별

return Message.wParam;

}


WinProc.c 

 

#include "Win32.h"


// Message Map에서 가장 많이 쓰는 항목을 상위에 올려놓는 것이 좋다.

ST_MsgMap MsgMap[] = {

{ WM_PAINT, ON_PAINT },

{ WM_KEYDOWN, ON_KEYDOWN },

{ WM_DESTROY, ON_DISTORY },

{ WM_CREATE, ON_CREATE },

{ WM_NULL, 0 }


};


// --------------------     WndProc     -------------------- //

// 실제 Application에서 메인과 같은 함수이다.

// WndProc 함수에서는 실질적인 기능이 들어간다.

// 첫 번째 인자 - hWnd는 Window Handler 값이 저장된다.

// 두 번째 인자 - iMessage는 이벤트 메세지가 저장된다.

// 세 번째 인자 - wParam은 키보드로부터 입력받은 문자가 저장된다.

// 네 번째 인자 - lParam은 마우스의 좌표 정보가 저장된다.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {

HDC hdc;

ST_MsgMap *Stp_Map = MsgMap;


// 메세지가 있을때 while문 진입

while ((*Stp_Map).uiMsg != WM_NULL) {


// 해당 메세지가 존재할 경우에 함수 실행

if ((*Stp_Map).uiMsg == iMessage) {

// 내부적으로 함수가 실행되어 처리되었을 경우 다른 메세지를 찾을 필요가 없다.

return (((*Stp_Map).FP)(hWnd, wParam, lParam));

}


// MessageMap의 위치 이동

++Stp_Map;

}


// 설정하지 않은 이벤트가 발생하면 WinMain의 GetMessage 함수로

// 메세지를 재전송시켜 다시 처리한다.

return (DefWindowProc(hWnd, iMessage, wParam, lParam));

}


// MFC에서는 WM_가 아니라 ON_로 메세지가 생성된다.

LRESULT ON_PAINT(HWND hWnd, WPARAM wParam, LPARAM lParam) {

HDC hdc;


hdc = BeginPaint(hWnd, &Ps);


BitBlt(hdc, iX_Pos, iY_Pos, 48, 48, MemDC, 0, 0, SRCCOPY);


EndPaint(hWnd, &Ps);


}


LRESULT ON_KEYDOWN(HWND hWnd, WPARAM wParam, LPARAM lParam) {

// 키보드 방향키 입력에 따른 이동

switch (wParam) {

case VK_LEFT:

iX_Pos = iX_Pos - XMOVE;


break;


case VK_RIGHT:

iX_Pos = iX_Pos + XMOVE;


break;


case VK_UP:

iY_Pos = iY_Pos - YMOVE;


break;


case VK_DOWN:

iY_Pos = iY_Pos + YMOVE;


break;


}


InvalidateRect(hWnd, NULL, TRUE);



return 0;

}


LRESULT ON_CREATE(HWND hWnd, WPARAM wParam, LPARAM lParam) {

HDC hdc;


hdc = GetDC(hWnd);

MemDC = CreateCompatibleDC(hdc);


HbmFront = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));

HbmLeft = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP2));

HbmRight = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP3));

HbmBack = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP4));

HbmGround = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP5));


ReleaseDC(hWnd, hdc);


HbmHero = (HBITMAP)SelectObject(MemDC, HbmFront);


return 0;

}


LRESULT ON_DISTORY(HWND hWnd, WPARAM wParam, LPARAM lParam) {

DeleteObject(HbmFront);

DeleteObject(HbmBack);

DeleteObject(HbmLeft);

DeleteObject(HbmRight);

DeleteObject(HbmGround);

DeleteDC(MemDC);


// 종료 전에 마지막으로 처리할 일이 존재하면 그 일을 마치고 

// PostQuitMessage 함수로 GetMessage에 0을 보내어 종료

PostQuitMessage(0);

return 0;

}






















728x90