소프트웨어학부/윈도우 프로그래밍

01장. 윈도우 프로그래밍의 이해

Mt.Hwang 2024. 10. 23. 18:29

 * 메시지 기반 message driven (이벤트 기반 event driven)
사용자가 발생시키는 이벤트에 의한 메시지를 처리하는 방식의 프로그래밍

윈도우 시스템의 모든 애플리케이션은 메시지 기반임

운영체제인 윈도우가 애플리케이션으로 메시지를 보내다
애플리케이션이 윈도우 시스템에게 메시지를 보내는 것이 x

윈도우 시스템이 애플레케이션의 함수를 호출한다는 것


 * 윈도우 애플리케이션의 메시지 처리 방식
윈도우 시스템에서 메시지 발생
-> 메시지 큐
->애플리케이션
(1) 메시지 루프
(2) 윈도우 프로시저 WinProc()
-> 실행 화면


 * 윈도우 프로그래밍
사용자가 발생시키는 메시지에 대한 처리루틴을 만들어주는 것


 * Win32 SDK와 MFC

 Win32 SDK
윈도우에서 애플리케이션 프로그램을 개발할 때 필요한
C언어용 표준 라이브러리

 MFC
윈도우에서 애플리케이션 프로그램을 개발할 때 필요한
C++로 작성된 클래스 라이브러리

 Win32 SDK 프로그래밍
 1. 윈도우 클래스를 만들어 등록하고
 2. 프레임 윈도우를 생성
모든 과정을 일일이 코딩해주어야 한다

 MFC
프레임 워크 사용
구조적으로 되어 있어
코드를 자동으로 생성해줌


 * 윈도우 프로그램 구조
 1. 초기화 부분
 2. 메시지 처리 부분

초기화는 WinMain()에서 담당
메시지 처리는 WinProc()에서 담당


 * WinMain()
 1. 윈도우 창(클래스)을 만들어 운영체제에 등록
 2. 프레임 윈도우를 생성해서 화면에 표시
 3. 메시지 큐로부터 메시지를 받아와 해당 윈도우 프로시저로 보냄

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow) {
 윈도우 클래스 생성
 윈도우 클래스 등록
 프레임 윈도우 생성
 프레임 윈도우 화면에 표시
 메시지 큐로부터 메시지를 받아 해당 프로시저로 보냄
}

 WINAPI형
윈도우 애플리케이션이라는 의미

 HInstance
애플리케이션 프로그램의 ID

 hPrevInstance
항상 NULL 값
프로그램 중복 실행을 방지하기 위해 만든
이전에 구동되었을 때의 인스턴스 핸들

 IpszCmdLine
실행 파일의 경로

 nCmdShow
윈도우가 처음 화면에 표시될 때의 표시 방법 초기화

즉, int WINAPI WinMain(프로그램 id, NULL, 실행 파일 경로, 초기화 방법)


 * WndProc()
switch()문을 이용해서 메시지 처리

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam) {
 switch(message) {
  메시지 처리
 }
}

 LRESULT
결과값을 저장하는 32bit 자료형

 CALLBACK
역으로 호출받는 함수
어떤 메시지에 의해 감추어진 형태로 구동되는 함수라는 뜻

WndProc()는 CALLBACK 함수이므로
WndProc()는 WinMain()의 while() 메시지 루프에 의하여
뒤에서 감추어진 형태로 구동된다

 hwnd
윈도우의 핸들러

 message
WinMain()에서 보내주는 메시지

 wParam과 IParam
메시지와 함께 필요한 정보

 DispatchMessage()
실제로 WndProc() 함수를 호출하는 함수

즉, 
LRESULT CALLBACK WndProc(핸들러, 메시지, 메시지 정보, 메시지 정보)


 * Win32 SDK 프로젝트
Window 데스크톱 마법사 이용

애플리케이션 종류는
데스크톱 애플리케이션(.exe)


 * 유니코드
국제 표준으로 제정된
2byte 계의 만국 공통의 문자 부호 체계


 싱글 바이트 문자 체제
1byte로 영문 알파벳 하나를 표기하는 것
ACII 코드 이용

 멀티바이트 문자 체제
2byte로 문자 하나를 표기하는 것
ex) 한글, 일본어


 * Visual Studio의 문자열
CString 클래스로 문자열 처리

_T() 매크로로 문자열을 표기

 _T() 매크로
TEXT() 매크로와 같은 매크로
유니코드가 정의되어 있으면 유니코드 문자열로 컴파일
유니코드가 정의되어 있지 않으면 ANSI 문자열로 컴파일 (멀티바이트 포함)


 * 윈도우의 문자열 표현 형식

 LPSTR
char * 을 의미

 LPCSTR
const char * 을 의미

 LPWSTR
wchar_t * 을 의미

 LPCWSTR
const wchar_t * 을 의미

 LPTSTR
TCHAR * 을 의미

 LPCTSTR
const TCHAR * 을 의미
 

 * WIN32 SDK 프로그래밍

 <window.h>
윈도우 애플리케이션을 작성할 때 필요한 헤더 파일

 윈도우 등록
1. WinMain()이 윈도우 구조체 생성
 ㄴ WNDCLASSEX 데이터 구조체
2. 구조체 멤버에 값을 채워 초기화
3. 운영체제에 등록
 ㄴ RegisterClassEx() API 함수 호출
 ㄴ 윈도우를 윈도우 프로시저에 연관시키는 것

 프레임 윈도우 생성 후 화면에 표시
1. 프레임 윈도우 생성
 ㄴ CreateWindow() API 함수 호출
 ㄴ 이 때 윈도우의 형태를 좀 더 세부적으로 정의
 ㄴ 윈도우 스타일, 좌표, 너비, 높이, 부모 윈도우의 핸들, 자식 윈도우의 핸들, 애플리케이션 인스턴스 핸들, 윈도우 생성 데이터 주소 등등..

 메시지를 윈도우 프로시저로 보냄
 1. 메시지 루프가 해당 윈도우에 대한 메시지를 메시지 큐로부터 받아와
해당 윈도우 프로시저로 보냄
 ㄴ while()문 사용
 2. GetMessage() 
 ㄴ 메시지 큐에서 메시지를 꺼내와 MSG 데이터 구조체에 저장
 3. TranslateMessage()
 ㄴ 가상 키 메시지를 문자 메시지로 변환
 4. DispatchMessage()
 ㄴ 내부적으로 윈도우 프로시저 함수를 호출
 ㄴ 윈도우 프로시저 함수에게 메시지 전달

while (GetMessage(&msg, NULL, 0, 0)) {
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}


 * 메시지

 WM_CREATE 
윈도우가 처음 생성될 때 발생하는 메시지

 WM_PAINT
윈도우를 다시 그려야 할 때 발생 발생하는 메시지

 WM_KEYDOWN
키보드의 키 하나를 눌렀을 때 발생하는 메시지

 WM_KEYUP
키보드의 키 하나를 뗄 때 발생하는 메시지

 WM_LBUTTONDBLCLK
왼쪽 마우스를 더블 클릭할 때 발생하는 메시지

 WM_DESTROY
윈도우가 종료될 때 발생하는 메시지


 * 윈도우에서 문자열 출력
디바이스 컨텍스트 핸들이 필요
디바이스 컨텍스트를 통해서 문자열 출력

 1. TextOut()
 2. DrawText()


 * GetClientRect()
윈도우 클라이언트 영역의 크기 알아냄

CWnd 클래스에 있음

RECT 구조체로 반환


 * 메시지 박스
사용자에게 간단한 메시지를 출력하는데 사용

MessageBox()로 출력


 * TextOut()
화면의 지정된 위치에 기본적인 문자열 출력

BOOL TextOut(HDC hdc, int nXStart, int nYStart, LPCSTR lpString, int cbString);

 hdc
디바이스 컨텍스트 핸들

 nXStart
문자열 출력 시작점 x 좌표

 nYStart
문자열 출력 시작점 y 좌표

 lpString
출력할 문자열

 cbString
문자열의 길이

즉, 
BOOL TextOut(디바이스 컨텍스트 핸들러, x좌표, y좌표, 문자열, 문자열 길이);


 * DrawText()
영역을 정하고 출력 형식에 맞게 문자열 출력

BOOL DrawText(HDC hdc, LPCTSTR lpString, int nLength, LPRECT lpRect, UINT Flags);

 hdc
디바이스 컨텍스트 핸들러

 lpString
출력할 문자열

 nLength
문자열 길이

 lprect
출력할 영역의 주소

 Flags
출력 형식의 플로그

즉,
BOOL DrawText(디바이스 컨텍스트 핸들러, 문자열, 문자열 길이, 출력 영역, 출력 형식)


 * DrawText()의 출력 형식 플러그

 DT_TOP
상단으로 정렬

 DT_BOTTOM
하단으로 정렬

 DT_LEFT
좌측으로 정렬

 DT_RIGHT
우측으로 정렬
다만 DT_SINGLELINE과 함께 써야 한다

 DT_CENTER
가로 중앙에 정렬

 DT_VCENTER
세로 중앙에 정렬
다만 DT_SINGLELINE과 함께 써야 한다

 DT_SINGLELINE
한 줄로 출력
행 바꿈과 라인 피드를 무시

 DT_NOCLIP
클리핑 없이 문자 출력

 DT_EXPANDTABS
문자열에 있는 탭이 포함되어 있을 때 공백 출력


 * 클리핑 기법 Clipping
특정한 범위 내에 속하는 것들은 그대로 살리고
범위 바깥에 속하는 것들은 범위 경계값으로 대체

ex)
img = {80, 60, 75, 95, 50}
clipped = img > 70
이 경우 80 70 75 95 70으로 출력됨


 * MessageBox()
사용자에게 간단한 메시지를 출력할 때 사용하는 대화 상자를 출력

int WINAPI MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT nType);

 hWnd
상위 윈도우의 핸들

 lpText
출력할 메시지의 문자열

 lpCaption
메시지 박스 타이틀에 나타날 문자열

 nType
메시지 박스의 동작 방식, 아이콘 모양, 버튼 종류

즉,
int WINAPI MessageBOx(상위 윈도우 핸들, 문자열, 타이틀 문자열, 메시지 박스 설정)


 * 윈도우 프로그램의 기본 형식

H로 시작하지 않는 자료형은 모두 구조체

 핸들
자원을 식별하기 위한 정수 번호
윈도우 프로그램이 구조체를 이용해 모든 것을 객체화하였고
만든 객체들을 조정하기 위한 것

 핸들 자료형
H로 시작

윈도우 프로그램은 핸들을 받거나 만들어서 사용한다고 생각


 * MSG 구조체
메시지 큐에 저장되는 메시지 정보를 담고 있는 구조체


 * WNDCLASSEX 구조체
윈도우 속성 정보를 담고 있는 구조체


 * PAINTSTRUCT 구조체
윈도우 클라이언트 영역에 텍스트나 이미지를 그리고자 할 때 사용할 정보가 있음


 * RECT 구조체
사각형 형태의 좌표 지정
왼쪽 상단 좌표와 오른쪽 하단 좌표를 저장


 * 헝가리언 표기법 Hungarian Notation

 변수 이름
소문자로 시작

접두어에 따라 데이터 형식 구분 가능

c 혹은 ch : char

by : BYTE (unsined char)

i 혹은 n : int

f : float

d : double

ld : long double

b : BOOL (int)

dw : DWORD (unsigned long)

w : WORD (unsigned long)

l : LONG (long)

p : pointer

lp : long pointer

h : handle

fn : function

lpfn : function pointer (64bit)

str : string

sz : null문자로 끝나는 문자열

lpsz : 문자열을 가리키는 포인터 (64bit)


 * 윈도우 시스템 특징
 1. GUI
 2. 멀티 태스킹 지원
 4. 메시지 기반 구조
 5. 윈도우 프로시저를 호출

 멀티 태스킹 지원 Multi-Tasking
선점형 멀티 태스킹 지원
프로그램에 대해 처리 시간 타이머를 할당
프로그램 자체가 병행으로 실행되는 것처럼 보임
작업을 세분화해서 수행 -> 퍼포먼스 향상

 메시지 기반 구조 Message-Driven Architecture
!!!! 윈도우가 애플리케이션으로 메시지를 보냄 !!!!
윈도우 시스템이 애플리케이션의 함수를 호출

 윈도우 프로시저 Window Procedure
애플리케이션 안에 있는 함수

윈도우 시스템은 운영체제가 프로그램을 호출한다
모든 윈도우 애플리케이션은 윈도우 프로시저를 가지고 있다
애플리케이션이 실행될 때 애플리케이션에 대한 메시지 큐를 생성
메시지 큐에 윈도우 시스템의 모든 메시지 저장
메시지 루프를 통해 메시지와 윈도우 프로시저를 매핑해서 연결


 * InvalidateRect()
윈도우의 클라이언트 영역을 다시 그리는 함수

BOOL InvalidateRect(HWND hwnd, CONST RECT * lpRect, BOOL bErase);

 hwnd
다시 그려질 영역을 설정하는 윈도우 핸들러

 lpRect
다시 그려질 사각 영역의 좌표를 포함하는 RECT 혹은 CRECT의 포인터
NULL일 경우 전체 클라이언트 영역 사용

 bErase
다시 그려질 영역이 백그라운드인지 명시
TRUE이면 기존 거를 지우고 다시 그리라는 의미

즉,
BOOL InvalidateRect(영역 설정 핸들러, 영역 좌표 RECT, 백그라운드 명시)


 * POINT 구조체
한 점의 x 좌표와 y 좌표를 정의