1.Win32 API 프로그래밍 구조
#WinMain()
1)윈도우 구조체 설정, 등록
2)윈도우 생성과 출력
3)메시지 루프
: 프로그램이 종료될때까지
자신에게 보내진 메세지가 있는지 계속 확인하면서
받은 메세지가 있으면 전달함
#WndProc() 윈도우 프로시져
- 메시지 처리
- 메시지? => WM_xxx, CB_xxx, LM_xxx, PBM_xxx 등으로 모두 양의 값
윈도우 프로시져가 메세지를 처리하는 코드는 다음과 같다.
//프로시져의 메시지 처리 방식
switch(message)
{
//각각의 메시지에 해당하는 처리
case 메시지1:
break;
case 메시지2:
break;
case 메시지3:
break;
//처리하지 않은 메시지에 대한 기본적인 처리
default:
DefWndProc();
}
#메시지 전달과 처리 과정
-메시지 루프와 WndProc()
while( GetMessage(&msg, NULL, 0, 0))
//메시지를 큐를 검사하면서 해당 응용프로그램의 메세지가 있는지 체크한다
{
TranslateMessage(&msg);//키보드 입력이 들어왔을때 어떤 문자가 눌렸는지 정보를 생성
DispatchMessage(&msg);//메세지를 윈도우 프로시져에게 보내주고
//윈도우 프로시져에게 처리되어 리턴된 값을 받아온다.
}
2. 프로젝트 생성, 문자집합
#멀티 바이트 문자 집합(MBCS)
- 1 ~ 2 Byte 크기의 문자 집합
(1 Byte로 표현할 수 없는 중국어, 일본어 등 지원)
- 영문과 한글 지원
- 일반 C함수는 MBCS 문자집합 사용
#유니코드 문자 집합
-2Byte로 전세계 언어를 표현하는 문자집합
-유니코드는 멀티바이트에 비해 메모리는
많이 차지하지만 처리속도는 더 빠름
-ASCII 코드 값의 일부는 유니코드와 같다. (문자, 숫자)
#문자 집합에 따른 데이터형 변환
-문자
TCHAR (ANSI,아스키) => CHAR(char)
TCHAR(Unicode) => WCHAR(wchar_t)
-문자열
LPTSTR(ANSI, 아스키) => LPSTR(char*)
LPTSTR(Unicode) => LPWSTR(wchar_t*)
-ANSI 문자열을 유니코드로 변환 매크로 함수, TEXT()
LPTSTR str = TEXT("문자열")
3. 윈도우 프로그래밍 기본 함수
#WinMain() 함수의 원형
#include<Windows.h>
#define WINAPI __stdcall
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR IpCmdLine,
int nCmdShow){}
int APIENTRY _tWinMain() //Unicode 사용에 따라 달라지는 함수
- hInstance : 응용 프로그램 종류의 인스턴스 값
- hPrevInstance : 이전 인스턴스 값
- IpCmdLine : 프로그램 외부에서 내부로 값 설정
- nCmdShow : 윈도우 출력 형태에 관한 값
#WndProc() 함수의 원형
LRESULT CALLBACK WndProc(HWND hWnd,
UINT message, WPARAM wParam,
LPARAM lParam)
{
return 0;
}
4. 윈도우 프로그래밍 WinMain() 작성 순서
#WinMain() 작성 순서 1단계, 구조체 설정
WNDCLASSEX wcex;
{
wcex.cbSize = sizeof(WNDCLASSEX); //구조체의 크기
wcex.style = CS_HREDRAW | CS_VREDRAW; //윈도우 이동 또는 크기가 가로세로 변할 때 윈도우 그리기
wcex.lpfnWndProc = WndProc; //함수 포인터(호출하고자 하는 함수를 연결)
wcex.cbClsExtra = 0; //여유분
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; //매개변수로 받은 인스턴스 값을 받음
wcex.hIcon = LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_APPLICATION)); //아이콘
//MAKEINTRESOURCE : 값을 양의 정수로 바꿔주는 매크로
//IDI_APPLICATION : 기본 아이콘
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
//커서
//IDC_ARROW : 기본 커서
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
//배경
//COLOR_WINDOW + 1 : 흰색
wcex.lpszMenuName = NULL;
//메뉴
//NULL : 기본메뉴
wcex.lpszClassName = (LPWSTR)"basic";
//구조체를 OS에 등록할 때 이름
wcex.hIconSm = LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_APPLICATION));
//Sm(all)아이콘
}
#WinMain() 작성 순서 2단계, 구조체 등록
{
RegisterClassEx(&wcex);
//구조체 등록 매크로 함수, 매개 변수 : 구조체 주소
}
#WinMain() 작성 순서 3단계, 윈도우 생성
HWND hWnd;
{
hWnd = CreateWindow((LPCWSTR)"basic", (LPCWSTR)"HelloWorld",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
800, 600, NULL, NULL,
hInstance, NULL);
//#define CW_USEDEFAULT : 운영체제의 기본 위치값으로 설정
}
#WinMain() 작성 순서 4단계, 윈도우 출력
{
ShowWindow(hWnd, nCmdShow);
//윈도우 출력
UpdateWindow(hWnd);
//윈도우 업데이트
//또는
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
}
#WinMain() 작성 순서 5단계, 메시지 루프
{
//# 메시지 루프를 구성하는 함수
BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax);
//GetMessage()
//메시지 큐에서 메시지를 가져오는 역할
//WM_QUIT(완전히 프로그램을 빠져나갈때)가 발생할 때만 FALSE 리턴
//그 외에는 TRUE 리턴
BOOL TranslateMessage(const MSG * lpMsg);
//문자 키 또는 키 입력에 대한 메시지 변환
//WM_KEYDOWN => WM_CHAR
LRESULT DispatchMessage(const MSG * lpMsg);
//WndProc() 함수 호출
//WndProc()가 종료될 때까지 대기
//WndProc()로 메시지 전달
//MSG 구조체
typedef struct {
HWND hwnd;
UINT message; //메세지
WPARAM wParam;//메시지와 함께 전달되는 정보
LPARAM lParam;//메시지와 함께 전달되는 정보
DWORD time;
POINT pt;
} MSG, *PMSG;
//메시지 루프 전체 구조
LPMSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
5. WndProc() 작성
# WndProc() 기본 메세지
-WM_PAINT
:최초 UpdateWindow() 함수에 의해 발생,
윈도우의 일부 영역을 새로 출력할 때 발생
-WM_DESTROY
:윈도우가 화면에서 사라진 후에 보내지는 메시지,
메모리에서 제거되기 직전에 보내짐
# WndProc() 구성
LRESULT CALLBACK WndProc(HWND hWnd,
UINT message, WPARAM wParam,
LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps); //화면 그리기 준비
EndPaint(hWnd, &ps); //화면 그리기 종료
break;
case WM_DESTROY:
//메모리 해제에 대한 코드가 들어가는 곳//
PostQuitMessage(0); //WM_QUIT 발생
break;
default:
return DefWindowProc(hWnd, message,
wParam, lParam);
return 0;
}
return 0;
6. 자동 생성 (VS 2022 버전)
// Windows API_AUTO.cpp : 애플리케이션에 대한 진입점을 정의합니다.
//
#include "framework.h"
#include "Windows API_AUTO.h"
#define MAX_LOADSTRING 100
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
WCHAR szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
WCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 여기에 코드를 입력합니다.
// 전역 문자열을 초기화합니다.
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSAPIAUTO, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 애플리케이션 초기화를 수행합니다:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSAPIAUTO));
MSG msg;
// 기본 메시지 루프입니다:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 함수: MyRegisterClass()
//
// 용도: 창 클래스를 등록합니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSAPIAUTO));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSAPIAUTO);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 함수: InitInstance(HINSTANCE, int)
//
// 용도: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
// 주석:
//
// 이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
// 주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 용도: 주 창의 메시지를 처리합니다.
//
// WM_COMMAND - 애플리케이션 메뉴를 처리합니다.
// WM_PAINT - 주 창을 그립니다.
// WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 메뉴 선택을 구문 분석합니다:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
#MyRegisterClass()
: 윈도우 구조체 설정 및 등록
#InitInstance()
: 윈도우 생성 및 출력
#About()
: 정보 대화 상자의 메시지 처리기, 애플리케이션 정보 같은 것들 표시
# HACCEL hAccelTable;
: 단축기에 대한 것
# LoadString()
: 문자열을 리소스를 다루기 위해, 문자열에 대한 아이디를 부여하고, 프로그램을 쓸 때
아이디를 이용해 문자열을 해당 배열에 복사한다.
솔루션 탐색기/리소스 파일/rc파일/String Table
경로에 저장 되어 있다.
위의 모든 내용은
유튜브 아워즈팜X나우캠퍼스, "Win32 API 2강. Win32 API 프로그래밍 구조",
'Win32 API' 카테고리의 다른 글
윈도우 프로그래밍 기초 (1) | 2023.04.17 |
---|