tWinMain
윈도우 API 예제를 만들어보겠습니다. 프로그램의 시작점인 엔트리 포인트 함수를 분석해 보고자 합니다.
#include <windows.h>
#include <tchar.h>
int WINPAI_tWinMain( HINSTANCE hinst, HINSTANCE hPrev,
LPTSTR IpCmdLine, int nShowCmd)
{
MessageBox(0, TEXT("Hello,API"), TEXT("First"), MB_OK)
return 0;
}
// winMain함수
헤더 파일
첫 행을 보면 windows.h 가 인클루드 되어 있습니다. 하나의 헤더 파일에 모든 API 함수둘의 원형과 사용하는 상수들이 정의가 되어 있기 때문에 windows.h 만 포함하면 됩니다. 물론 특별한 경우에는 해당하는 헤더 파일을 포함해야 하지만 예제 수준에서는 windows.h 만 포함하면 거의 문제가 없습니다.
Windows.h 파일은 기본적으로 데이터 타입, 함수 원형, 매크로 상수등을 정의하며 그 외 윈도우 프로그래밍에 필요한 보조 헤더 파일을 포함하고 있습니다.
tchar.h 파일은 앞 장에서 말한 대로 범용타입을 사용하기 위한 헤더입니다.
시작점
윈도우 프로그램에서의 엔트리 포인트 함수는 환경에 따라 다양한 키워드가 사용될 수 있습니다.
엔트리 포인트 함수 | 내용 |
WinMain | 유니코드가 아닌 환경 |
wWinMain | 유니코드 환경 |
_tWinMain | 매크로이며 범용적인 형태 |
각 환경에 맞는 엔트리 포인트 함수를 사용해야 하며 이것이 제대로 해결 되지 않을 시 아래와 같은 링크 에러가 발생합니다. (참조 위치 : __tmainCRTStartup 함수)에서 확인하지 못했습니다.
함수명 앞에 있는 WINAPI 지정자는 윈도우의 표준 호출 규약인 __stdcall을 사용한다는 의미입니다.
//minwindef.h
#define WINAPI __stdcall
리턴 타입과 인자
인자 | 의미 |
hInstance | 프로그램의 인스턴스 핸들 |
hPrev | 바로 앞에 실행된 현재 프로그램의 인스턴스 핸들, 없을 경우는 NULL이며 Win32에서는 항상 NULL 입니다. |
IpCmdLine | 명령행으로 입력된 프로그램 인자입니다. |
nShowCmd | 프로그램이 실행될 형태이며, 최소화, 보통, 최대화 모양 등이 전달됩니다. |
API 함수들 중 HINSTANCE 타입을 요구하는 경우가 있습니다. 우선 HINSTANCE란 프로그램 자체를 일컫는 정수값이며 응용 프로그램의 인스턴스핸들이라고 표현할 수 있습니다. 프로그램 내부에서 자기 자신을 가리키는 1인칭 대명사입니다. 실제 타입은 void* 형태로 되어 있으며 아래 함수를 통해 얻어 올 수 있습니다.
HINSTANCE hCurInst = GetModuleHandle(0);
MessageBox 함수
1번째 피라미터는 윈도우의 핸들, 2번째 피라미터는 메시지 출력 내용, 3번째 피라미터는 타이틀바 문자열, 4번째 피라미터는 버튼의 모양 및 ICON 모양을 나타내며 winapifamily.h 파일에 정의되어 있습니다.
#include <winapifamily.h>
#define MB_OK 0x00000000L
#define MB_OKCANCEL 0x00000001L
#define MB_ABORTRETRYIGNORE 0x00000002L
#define MB_YESNOCANCEL 0x00000003L
#define MB_YESNO 0x00000004L
#define MB_RETRYCANCEL 0x00000005L
#if(WINVER >= 0x0500)
#define MB_CANCELTRYCONTINUE 0x00000006L
#endif
#define MB_ICONHAND 0x00000010L
#define MB_ICONQUESTION 0x00000020L
#define MB_ICONEXCLAMATION 0x00000030L
#define MB_ICONASTERISK 0x00000040L
함수 호출 규약
일반적으로 하나의 함수를 어떻게 컴파일 되도록 하느냐에 따른 호출 규약이 있습니다. 몇가지만 살펴보면
호츌 규약 | 인자 전달 | 스택 제거 | 기타 |
__cdecl | Right -> Left | 호출자가 인자 제거 | C/C++ 함수의 기본 호출 규약 |
__stdcall | Right -> Left | 호출된 함수가 인자 제거 | 대부분의 System 함수가 사용 |
this | Right -> Left | 호출자가 인자 제거 | C++ 클래스의 맴버 함수가 사용 |
__stdcall은 윈도우 프로그램에서 사용하는 대부분의 API가 사용하는 방식입니다. __cdecl과의 차이점은 호출된 함수가 스택에서 인자를 제거한다는겁니다. 이러한 이유 때문에 __cdecl 방식보다 메모리 사용이 효율적입니다. Pascal 언어가 사용하던 방식이라서 Pascal 호출 규약이라고도 합니다.
대다수의 윈도우 프로그램에서 사용하는 함수는 __stdcall 방식을 사용합니다. WINAPI, CALLBACK, APIENTRY 등의 매크로는 __stdcall 방식의 매크로입니다.
exe 타입
비주얼 스튜디오를 사용하여 프로젝트를 만들 때 일반적으로 2가지 방식을 사용합니다. 1번째는 윈도우 프로그래밍을 위한 Win32 프로젝트이고 2번째는 콘솔 프로그래밍을 위한 Win32 콘솔 응용프로그램입니다. 생성된 프로젝트의 차이점은 어떠한 하위 시스템을 선택하느냐에 따른 부분이고 그 외 차이점은 없습니다. 비주얼 스튜디오에서 생성된 프로젝트의 하위 시스템을 변경할 수 있는데 .exe 파일을 실행하는 방법을 지시할 수 있습니다. 그리고 선택한 하위 시스템에 따라 링커가 선택하는 진입점 기호가 결정되게 됩니다.
CUI(Console User Interface) - Win32 콘솔 응용프로그램
- Entry Point 수행 전 Console 창이 실행됩니다.
- Entry Point 함수는 main() 또는 wmain() 입니다.
- Link Option 은 /SUBSYSTEM:CONSOLE 입니다.
GUI(Graphic User Interface) - Win32 프로젝트
- Entry Point 수행 전 Console 창이 생성되지 않습니다.
- Entry Point 함수는 WinMain(), wWinMain() 입니다.
- Link Option은 /SUBSYSTEM:WINDOWS 입니다.
따라서 프로젝트를 목적과 다르게 생성한 경우는 속성 페이지에서 하위 시스템을 변경해야 됩니다. 또 다른 방법으로는 아래와 같은 코드 상단에 전처리 구문을 사용하여 변경할 수 있습니다.
#pragma comment (linker, "/subsystem:windwos")
#pragma comment (linker, "/subsystem:console")
데이터 타입
API에서 사용되는 타입들은 아래와 같이 대부분 대문자로 구성되어 있습니다.
// windef.h
typedef struct tagPOINT
{
LONG x;
LONG y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
사용되는 특정 문자의 의미를 알면 타입을 구별하기 쉽습니다.
키워드 | 내용 |
P | Pointer를 나타냅니다. |
LP | Win32에서 L 키워드는 의미가 없습니다. PSTR 과 LPSTR 은 동일한 타입입니다. |
T, t | 범용 타입입니다. LPSTR(char*) 과 LPTSTR(TCHAR*) 는 다릅니다. |
W | Unicode Type입니다. |
C | const를 의미합니다. LPCTSTR |
STR | 문자열을 의미합니다. PSTR(char*) |
H | 객체의 핸들을 의미합니다. HWND, HPEN |
최근댓글