Windows 공부 내용 정리 (1)

2023. 1. 11. 15:29Windows API

전체 코드 

더보기
#include <Windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("RandGrp");

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)GetStockObject(WHITE_BRUSH);
	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;
	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;
}

 

많은 API 함수들이 hInstance 값을 인수로 요구하기 떄문에 위의 코드에서는 전달된 값은 전역변수로 g_hInst에 대입해 두었다.

lpszClass문자열을 저장하는데 저장한 문자열은 윈도우 클래스를 정의하는데 사용되며 타이틀 바에 표시되기도 한다.

 

 

1. 시작점 (Entry Point) : WinMain 

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

 

- > 윈도우즈 API의 main 함수이다.

 

1. APIENTRY

  윈도우즈의 표준 호출 규약인 __stdcall 을 사용한다는 뜻인데 일단은 없다고 생각해도 무방하다.

 

2. 4개의 인수를 갖는다.

    1) hInstance - 프로그램의 인스턴스 핸들

    2) hPrevInstance - 16비트 운영체제에서만 사용되는 인수이다. 신경 쓰지 말자

    3) lpszCmdParam - 명령행으로 입력된 프로그램 인수. 도스의 argvv인수에 해당되며 보통 실행 직 후에 열 파일의 경로가 전달된다.

    4) nCmdShow - 프로그램이 실행될 형태이며 최소화, 보통 모양등이 전달된다.

 

3. 윈도우 클래스 등록

 WinMain의 주요 역활은 윈도우를 만드는 일이다. 윈도우클래스를 등록하고 CreateWindow 함수를 호출하면된다.

윈도우 클래스를 등록하기 위해서는 10가지 속성을 설정해야한다.

 

1) style - 대표적으로 2가지가 있다.

CS_HREDRAW : 윈도우의 이동이나 크기 조절시 클라이언트의 가로 크기가 변경되면 다시 그린다.

CS_VREDAW : 윈도우의 이동이나 크기 조절시 클라이언트의 세로 크기가 변경되면 다시 그린다.

 

2) lpfnWndProc - 윈도우의 메시지 처리 함수를 지정한다. 거 WndProc으로 정해져 있는 편이다.

 

3) cbClsExtra, cbWndExtra

  - 일종의 예약 영역. 윈도우즈가 내부적으로 사용하며 특수한 목적에 사용되는 여분의 공간이다. 사용하지 않을 경우는 0으로 지정한다.

 

4) hInstance -  이 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance 값을 그대로 대입하면 된다.

 

5) hIcon, hCursor

  - 마우스 커서와 아이콘을 지정한다. LoadCursor 함수와 LoadIcom 함수를 사용하여 커서, 아이콘을 읽어와 이 멤버에 대입하면 된다. 

 

6) hbrBackground

   - 윈도우의 배경 색상을 지정한다. 좀 더 정확하게 표현하면 윈도우 배경 색상을 채색할 브러시를 지정하는 멤버이다.

   - GetStocObject 함수를 사용하여 윈도우즈에서 제공하는 브러시를 지정하거나 COLOR_WINDOW 같은 시스템 색상을 지정할 수도 있다. 

   - 일반적인 흰색 브러시(WHITE_BUSH)를 사용하며 윈도우의 배경이 흰색으로 칠해진다.

 

7) lpszMenuName

   - 이 프르그램이 사용할 메뉴를 지정한다. 메뉴를 사용하지 않는 경우 이 멤버에 NULL 을 사용한다.

 

8 ) lpszClassName

   - 윈도우 클래스의 이름을 문자열로 정의한다.

 

9) ATOM RegisterClass ( CONST WNDCLASS *lpWndClass );

   - 인수로 WNDCLASS 구조체의 번지를 전달한다. 이런 특성을 가진 윈도우를 앞으로 사용하겠다는 등록 과정.

 

4. 윈도우 생성 : CreateWindow

CreateWindow 함수를 통해 등록한 윈도우 클래스를 생성한다.

HWND CreateWindow(lpszClassName, lpszWindowName, dwSytle, x, y, nWidth, nHeight, hwndParent, hmenu, hinst, lpvParam)

1) lpszClassName

  생성하고자 하는 윈도우의 클래스를 지정하는 문자열이다.

  CreateWindow 함수는 윈도우 클래스에 정의된 속성대로 윈도우를 생성한다.

  앞에서 등록한 WNDCLASS 구조체의 lpszClassName 멤버의 이름을 여기에 기입한다.

 

2) lpszWindowName

  윈도우의 타이틀 바에 나타날 문자열이다.

 

3) dwStyle

  만들고자 하는 윈도우의 형태를 지정하는 인수이다.

  크기 조절이 가능하도록 할 것인가, 타이틀 바를 가질 것인가, 또는 스크롤 바의 유무 등등을 세세하게 지정할 수 있다.

 

4)  X, Y, nWIDTH, nHeight

  윈도우의 크기와 위치를 지정하며 픽셀 단위를 사용한다.

  정수값을 바로 지정해도 되며 CW_USEDEFAULT 를 사용하면 운영체제가 적당한 크기와 위치를 알아서 설정한다.

 

5) hWndParent

  부모 윈도우가 있을 경우 부모 윈도우의 핸들을 지정한다.  자신이 최상위 윈도우일 경우 이 값을 NULL로 지정.

 

6) hmenu

  윈도우에서 사용할 메뉴의 핸들을 지정한다. 

  윈도우 클래스의 메뉴는 그 윈도우 클래스를 기반으로 하는 모둔 윈도우에서 공통적으로 사용되는 반면

  이 인수로 지정된 메뉴는 현재 CreateWindow 함수로 만들어지는 윈도우에서만 사용된다.

  왼도우 클래스에서 지정한 메뉴를 그대로 사용하려면 이 인수를 NULL 로 지정.

 

7) hinst

  윈도우를 만드는 주체, 즉 프로그램의 핸들은 지정한다. WinMain의 인수로 전달된 hInstance를 대입하면 된다. 운영체제는 누가 윈도우를 만들었는지 기어해 두었다가 프로그램이 종료될 때 파괴되지 않는 윈도우를 자동으로 파괴한다.

 

8 ) lpvParam

  CREATESTRUCT라는 구조체의 번지이며 여러 개의 윈도우를 만들 때 각 윈도우에 고유의 파리미터를 전달하는 특수한 목적에 사용된다. 보통은 NULL 값을 사용한다.

 

5. 윈도우 출력 : ShowWindow

CreateWindow함수로 만든 윈도우는 메모리상에만 있을 뿐이며 아직은 화면에 출력되지는 않는다.

메모리에 만들어진 윈도우를 화면으로 보이게 하려면 다음 함수를 사용해야 한다.

BOOL ShowWindow(hWnd, nCmdShow);

1) hWnd

   - 화면으로 출력하고자 하는 윈도우의 핸들

 

2) nCmdShow

   - 윈도우를 화면에 출력하는 방법. WinMain 함수의 인수로 전달된 nCmdShow를 그대도 전달하면 된다.

 

6. 메시지 루프

While (GetMessage(&Message, NULL, 0, 0)) { 
    TranslaeMessage(&Message);
    DispatchMessage(&Message);
}

메시지 루프는 세 개의 함수 호출로 이루어져 있으며 전체 루프는 while문으로 싸여져 있어 무한히 반복되는 구조를 가지고 있다. 

 

1. GetMessage

BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFiterMin, UINT wMsgFiterMax);

메시지 큐에서 메시지를 읽어들인다. 발생된 메시지가 잠시 대기하는 일종의 메시지 임시 저장 영역이다. 

 

2. TranslateMessage

키보드 입력 메시지를 가공하여 프로그램에서 쉽게 쓸 수 있도록 한다. 윈도우즈는 키보드의 어떤 키가 눌러지거나 떨어졌을 때 키보드 메시지를 발생시키는데 TranslateMessage 함수는 키보드 눌림(WM_KEYDOWN) 메시지가

발생할 때 문자가 입력되었다는 메시지 (WM_CHAR)를 만드는 역할을 한다.

 

3. DispatchMessage

메시지 큐에서 꺼낸 메시지를 윈도우 메시지 처리 함수(WndProc)로 전달한다. 

이 함수가 메시지를 전달하면 다시 루프의 선두로 돌아가 다음 메시지를 기다린다.

 

2. 메시지 처리 함수  :  WndProc

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

WinMain은 메인 윈도우를 만들고 화면에 윈도우를 표시하기만 할 뿐이며 대부분의 일은 WndProc에서 이루어진다.

 

1. CALLBACK

CALLBACK이라는 매크로가 사용되었는데 이 매크로도 APIENTRY와 마찬가지로 __stdcall 로 정의되어있다. 

이런 매크로들은 그 자체로 어떤 의미를 가진다고 하기 보다는 호환성 과 이식성을 위해 존재하는 것이다.

 

2. 윈도우 프로시저 : WndProc

메시지 처리 함수란 메시지가 발생할 때 프로그램의 반응을 처리하는 일을 한다. 

WinMain 내의 메시지 루프는 메시지를 메시지 처리 함수로 보내기만 할 뿐이며 WndProc은 메시지가 입력되면 운영체제에 의해 호출되어 메시지를 처리한다. 

 

WndProc의 인수는 모두 4개이며 MSG 구조체의 앞쪽 맴버 4개와 동일하다. 

hWnd는 메시지를 받을 윈도우 헨들

iMessage는 어떤 종류의 메시지인가

wParam, IParam은 iMessage의 메시지에 따라 부가적인 정보를 가진다. 실제로 어떤 값이 전달되는지는 메시지별로 다르다.

 

3. PostQuitMessage(0)

 WM_QUIT 메시지를 보낸다.

메시지 루프의 GetMessage 함수의 리턴값이 FALSE가 되어 while 루프를 빠져나오며 WinMain이 종료된다.

 

4. DefWindowProc

사용자가 직접처리하지 않은 나머지 메시지에 관한 처리를 한다.

 

 

 

 

[ 출처 ]

해당 내용은 윈도우즈 API 정복 volume 1 개정판을 바탕으로 작성하였습니다.

'Windows API' 카테고리의 다른 글

Windows(12)  (0) 2023.01.13
Windows(11)  (0) 2023.01.11
Windows(10)  (0) 2023.01.11
Windows(9)  (0) 2023.01.10
Windows(8)  (0) 2023.01.06