1. WinAPI Basic

JUSTICE_DER·2024년 1월 16일

WinAPI

목록 보기
1/9

수업중에 WinAPI 프로젝트를 생성하기 위해
기존 Console application을 Desktop application으로 생성하였고,
추가로 Windows.h 를 추가하였다.

Windows.h를 추가하는 건 이전 포트폴리오에서도 진행했었지만,
WinAPI를 사용한 것은 아니라고 하셨다.

그렇다면 뭐가 WinAPI인거지?

https://www.youtube.com/watch?v=S4lQwJawOzI
여기에 잘 나왔다고 생각한다.

  1. API는 운영체제와 상호작용할 수 있는 다양한 함수들을 h파일로 구현해 놓았다.
  2. 헤더파일은 정의만 되어있고, 실행할 수는 없다.
  3. 실행은 dll 파일로 실행한다.

근데?? dll은 어떻게? 빌드시에 dll이 실행?

1. WinAPI란 ?

  • 운영체제가 응용프로그램개발을 위해 제공하는 "함수의 집합"
  • 운영체제는 가장 기본적인 동작을 할 수 있는 함수의 집합을 응용 프로그램에게 제공할 의무가 있다.

왜 제공을 해야하는가?
ㄴ함수를 사용하여, (응용프로그램이 운영체제에게 부탁하여)
운영체제가 관리하는 하드웨어의 기능들을 사용하기 위함.


API 정석
http://soen.kr/

  • 운영 체제는 하드웨어와 응용 프로그램 사이에 위치하며 응용 프로그램을 대신하여 하드웨어를 관리하고 메모리를 관리하는 시스템 소프트웨어이다.
  • WinAPI는 운영체제의 기본적인 대부분의 기능들을 사용한다는 점에서 운영체제 그 자체라고도 할 수 있다.
  • 비슷한 말로 SDK라는 것은 SDK(Software Development Kit)란 윈도우즈를 만든 마이크로소프트사에서 제공하는 윈도우즈용 프로그램 개발 킷이다.
    (SDK = 윈도우용 개발킷)
  • 윈도우즈 운영체제가 제공하므로, WinAPI를 호출하여 프로그램을 개발하는 tool kit이었는데,
    사실상 API함수와 같은 뜻이고,
    SDK로 만들었다는건 곧 순수 API로만 만들었다는 뜻이 된다고 함.
    SDK로만 만들면 운영체제를 직접 쥐고 흔들어 섬세한 처리를 할 수 있고, 속도에도 유리하지만,
    방대한 양의 함수들을 알아야하고, 내부동작도 알아야한다.
    생산성도 낮아서 SDK 개발방법은 많이 사용되지 않는다.
  • SDK 방식말고 클래스 라이브러리 로 API함수들 사용가능
    복잡하고 양이 많은 API 함수들을 좀 더 쉽고 빠르게 사용하기 위해 클래스로 잘 포장하여 클래스 위주로 프로그램을 작성하는 방법이다. 윈도우즈 프로그래밍에 필요한 클래스들을 미리 작성해 놓고 클래스를 조립하여 프로그램을 만들어 나간다. 클래스가 워낙 잘 설계되어 있기 때문에 사용하기도 무척 쉬울 뿐만 아니라 기능 또한 아주 막강하다. 윈도우즈용 클래스 라이브러리에는 마이크로소프트사의 MFC
  • 그거말고는 비주얼 툴이 있다.
  • API를 알아야 하는 이유
  1. 운영체제에 접근하여 다양한 기능 및 저수준의 프로그래밍을 하기 위함.
  2. 어짜피 알아야한다 ㅋㅋ
    클래스 라이브러리는 API함수 기반 위에 생성이 되어,
    API함수를 모르고서, 클래스라이브러리라는걸 이해하는 건 불가능.
  • 우선 언어는 선택의 여지없이 C(C++ 포함)언어이어야 한다. 왜냐하면 윈도우즈의 표준 언어가 C언어이기 때문이기도 하지만 API를 사용하는 대부분의 개발 툴이 C컴파일러이기 때문이다.

그 외에 변수 명명법, 핸들, 비트 OR 연산자에 대한 내용이 나온다..

2. 그래서 VC에서 어떻게 사용?

  • 비주얼 C++로 만들 수 있는 프로젝트의 종류가 나열되어 있는데 우리가 만들고자 하는 것은 순수한 Win32 API만을 사용한 프로젝트이므로 Win32 Application을 선택한다.

이게 WinDesktop application인 듯..??

실행하면,

  • Windows.h 헤더가 정의되어있다.
  • windows.h 헤더 파일은 기본적인 데이터 타입, 함수 원형 등을 정의하며 그 외 필요한 헤더 파일을 포함하고 있다.
    그래서 윈도우즈 프로그램의 첫 줄은 거의 항상 #include <windows.h> 로 시작된다.

하지만 현재 버전에서는 자동으로 windowAPI.h 헤더만 추가되고,
해당 헤더 안에 windows.h헤더가 존재하게 된다.
(tchar.h 도 포함)

3. WindowAPI의 3요소

3-1. WinMain (Entry Point)

A. WinMain 함수

int APIENTRY WinMain
(
	_In_ HINSTANCE hInstance,   
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR    lpszCmdParam,                   
    _In_ int       nCmdShow)
{
  1. hInstance
  • 프로그램 인스턴스 핸들 값
  • 어떤 프로그램 실행할지 정보
  1. hPrevInstance
  • 이전에 실행된 인스턴스 핸들
    ㄴ호환성을 위해서만 존재. 무시해도 됨.
    ㄴ가상메모리 - 추가할 부분
  1. lpszCmdParam
  • 명령행으로 입력된 프로그램 인자 - argv 인수에 해당..?
  1. nCmdShow
  • 프로그램 실행 형태 (최소화/최대화/보통모양 등..)

>> hInstance 외에는 중요하게 사용되지 않는다.
여기서의 인스턴스란, 프로그램 인스턴스를 의미한다.
실행되고 있는 각각의 프로그램을 말하는 것이다.

메모장이라는 프로그램을 2개 실행한다고 해서, 같은 인스턴스가 아니다.
같은 인스턴스가 아님을 구분하는 것을 hInstance를 통해 하는 것이고,
같은 메모장이라도, 서로 다른 인스턴스 핸들값을 가지고,
운영체제는 다른 걸 바탕으로 서로 구별한다.

hInstance란 프로그램 자체를 일컫는 정수값이며
API 함수에서 수시로 사용된다.
그래서 보통 WinMain의 인수로 전달된 hInstance값을 전역 변수 _hInstance에 대입

_lpszClass라고 전역 문자열도 정의되어 있는데 이 문자열은 윈도우 클래스를 정의하는데 사용된다

  • 프로그램을 자세히 보면 두개의 함수만 있다.
    WinMain, WinProc이고,
    WinMain에서는 윈도우를 만들고 화면에 출력하기만 할 뿐
    대부분의 일은 WndProc에서 이루어진다.
  • 따라서 윈도우즈에서는 아주 특별한 경우를 제외하고는 이 두개의 함수가 모두 있어야 한다.
  • WinMain의 모양은 대체로 일정하며 특별한 일을 하지 않지만
    WndProc는 프로그램에 따라 형태가 천차만별로 달라진다.
    따라서 윈도우 API 프로젝트를 확인할 때,
    WndProc를 분석하는 것부터 시작한다.

B. 윈도우 클래스

  • WinMain 함수에서 하는 가장 중요한 일은 윈도우를 만드는 일이다. 윈도우가 있어야 사용자로부터 입력을 받을 수 있고 출력을 보여줄 수도 있기 때문이다.
  • 윈도우를 만드려면 윈도우 클래스를 먼저 등록한 후 CreateWindow 함수를 호출해야 한다.

1. 클래스를 설정하고, (레지스터) 등록한다.

  • 윈도우 클래스를 그냥 사용하지 않고,
    RegisterClass함수의 인자로 WndClass 구조체의 주소를 넘겨주어
    이런 특성을 가진 윈도우를 앞으로 사용하겠다는 등록 과정을 거친다.
 WNDCLASS WndClass;
	
	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)WndProc;
	WndClass.lpszClassName=lpszClass;
	WndClass.lpszMenuName=NULL;
	WndClass.style=CS_HREDRAW | CS_VREDRAW;
	RegisterClass(&WndClass);
    
RegisterClass(&wndClass);

Window클래스를
생성하여,
설정하고,
RegisterClass에 주소를 넘겨준다.


2. 클래스를 실제 메모리상에 올리고, 화면에 출력한다

  • CreateWindow 함수는 윈도우에 관한 모든 정보를 메모리에 만든 후 윈도우 핸들을 리턴값으로 넘겨준다.
  • 넘겨지는 윈도우 핸들은 hWnd라는 지역 변수에 저장되었다가 윈도우를 참조하는 모든 함수의 인수로 사용된다.
    (수업에서는 hWnd가 전역으로 선언)
 _hWnd = CreateWindow
 (
     _lpszClass,                                
     _lpszClass,                                
     WS_OVERLAPPEDWINDOW,                       
     400,                                       
     100,                                       
     800,                                       
     800,                                       
     NULL,                                      
     (HMENU)NULL,                               
     hInstance,                                 
     NULL                                       
 );
 
 
ShowWindow(_hWnd, nCmdShow);

hWnd라는 메모리에 올라간 핸들을
nCmdShow라는, winMain에서 받은 매개변수(최대화,최소화 등)의 형태로 표시한다.


3-2. Message Loop

  • 윈도우즈를 메시지 구동 시스템(Message Driven System)이라고 하는데,
  • 프로그램의 실행 순서가 명확하게 정해져 있지 않으며 상황에 따라 실행 순서가 달라지는 데 여기서 말하는 상황이란 바로 어떤 메시지가 주어졌는가를 말한다.
  • 메시지란 사용자나 시스템 내부적인 동작에 의해 발생된 일체의 변화에 대한 정보를 말한다. 예를 들어 사용자가 마우스의 버튼을 눌렀다거나 키보드를 눌렀다거나
   MSG message;
   while (GetMessage(&message, 0, 0, 0))
   {
       TranslateMessage(&message);
       DispatchMessage(&message);
   }

Message Loop는 3개의 함수만 사용하면 끝이다.


3-3. WndProc

  • LRESULT CALLBACK
  • 메시지 처리 함수란 메시지가 발생할 때 프로그램의 반응을 처리하는 일을 수행
  • 윈도우 프로시저, 윈드프록 이라고 읽는다.
  • WinMain에서 호출하는 것이 아니라 윈도우즈에 의해 호출된다.
  • WinMain내의 메시지 루프는 메시지를 메시지 처리 함수로 보내주기만 할 뿐이며
    WndProc은 메시지가 입력되면 윈도우즈에 의해 호출되어 메시지를 처리한다.
    이렇게 운영체제에 의해 호출되는 응용 프로그램내의 함수를 콜백(CallBack) 함수라고 한다.
  • 매개변수는 MSG의 매개변수 4개와 같다.
    그 중, message 매개변수에 의해, switch문을 돌고,
    수행해야할 것들을 처리한다.

기본 메세지만을 처리하고 있는 셈인데,
나머지 처리되지 않은 메세지에 대해서는
모두 DefWindowProc 함수로 전달되며 이 함수에서 디폴트 처리를 수행해 준다.
= default procedure

  • 또한 DefWindowProc 함수가 메시지를 처리했을 경우 이 함수가 리턴한 값을 WndProc 함수가 다시 리턴해 주어야 한다.

  • WM_DESTROY 메시지는 사용자가 시스템 메뉴를 더블클릭하거나 Alt+F4를 눌러 프로그램을 끝내려고 할 때 발생하는 메시지이다. WndProc에서 이 메시지가 발생하면 PostQuitMessage 함수를 호출하여 WM_QUIT 메시지를 보낸다. WM_QUIT 메시지가 입력되면 메시지 루프의 GetMessage 함수 리턴값이 False가 되어 프로그램이 종료된다.

4. LCSTR / LCTCSTR

준수모드 멀티바이트 유니코드 바꾼 이유
tchar.h는 뭐하는거

현재 프레임워크 구조 분석

뭘 하는 거고 어떻게 유기적 연결
객체지향 어떻게 클래스끼리 연결하는지 - 상속 없이

  • WinMain.cpp
    ㄴ#include "Stdafx.h"

  • Stdafx.h : 미리 컴파일된 헤더
    ㄴwindows, tchar등 헤더 다 포함.
    ㄴCommonMacroFunction도 포함
    ㄴ그 외에 간단한 메모리 지우기 매크로함수, HINSTANCE,HWND,POINT 전역변수 등 선언
    ㄴ왜 매크로? inline 아님?

  • CommonMacroFunction
    ㄴinline함수들 - 왜 inline?

  • C3DMatrix
    ㄴ행렬

  • C3DVector
    ㄴclass C3DMatrix; // 클래스 전방선언으로, CPP에서 헤더를 선언해준다.
    ㄴ전방선언을 해야하는 이유 - 클래스에 적힌헤더의 중복을 방지하기 위함
    ㄴ특정 클래스에서 다른 클래스를 포인터로 사용할 때, 미리 해당 클래스가 필요하다는 것을 알려줌.
    ㄴ클래스 멤버 함수가 정의된 cpp 파일에서 다른 클래스 헤더 파일이 필요한 경우 include 수행.
    ㄴ 추가

#pragma once

class C3DMatrix;	// 클래스 전방선언으로, CPP에서 헤더를 선언해준다.

class C3DVector
{

};

참고 사이트
https://blog.naver.com/mincoding/221707050373

아직 이해안됨
https://rninche01.tistory.com/entry/Window-API-%ED%98%B8%EC%B6%9C-%ED%9D%90%EB%A6%84

클래스 전방선언
https://c1oud9.tistory.com/105
https://velog.io/@taeil314/C-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%A0%84%EB%B0%A9-%EC%84%A0%EC%96%B8

profile
Time Waits for No One

0개의 댓글