본문 바로가기

Application Programming Interface/Windows API

갈아 만든 Windows API - #3 Hello, World!

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

갈아 만든 Windows API

#3 Hello, World!

tapitolife(dkhighest@naver.com)

원본 소스 보기

#include <windows.h>
HINSTANCE g_hInstance;
TCHAR szClassName[] = TEXT("TAPITO WinAPI Example");
TCHAR szWindowName[] = TEXT("TAPITO Windows API Example #1");

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS WndClass;

    g_hInstance = 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 = szClassName;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClass(&WndClass);

    hWnd = CreateWindow(
        szClassName,
        szWindowName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        (HWND)NULL,
        (HMENU)NULL,
        hInstance,
        (LPVOID)NULL
        );

    ShowWindow(hWnd, nShowCmd);

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

    return (int)msg.wParam;
}

/* ↓ 조작해 볼 부분 ↓ */

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
    LRESULT ret;

    switch(uMessage)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        ret = 0;
        break;

    default:
        ret = DefWindowProc(hWnd, uMessage, wParam, lParam);
        break;
    }

    return ret;
}

 

Windows 프로그램은 실행 순서가 일정하지 않고 그때그때 들어오는 메시지에 따라 작업을 처리하기 때문에 Hello, World가 출력될 시점을 다르게 정할 수 있습니다. 또한 Windows에서는 화면이 여러 개의 창으로 관리되기 때문에 문자열이 출력될 창 또한 다르게 지정할 수 있습니다.

 

MessageBox를 통한 Hello, World 출력

#include <windows.h>
HINSTANCE g_hInstance;
TCHAR szClassName[] = TEXT("TAPITO WinAPI Example");
TCHAR szWindowName[] = TEXT("TAPITO Windows API Example #1");

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS WndClass;

    g_hInstance = 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 = szClassName;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClass(&WndClass);

    hWnd = CreateWindow(
        szClassName,
        szWindowName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        (HWND)NULL,
        (HMENU)NULL,
        hInstance,
        (LPVOID)NULL
        );

    ShowWindow(hWnd, nShowCmd);

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

    return (int)msg.wParam;
}

/* ↓ 조작해 볼 부분 ↓ */

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
    LRESULT ret;

    switch(uMessage)
    {
    case WM_CREATE:
        MessageBox(hWnd, TEXT("Hello, World!"), TEXT("Alert! WM_CREATE"), MB_OK | MB_ICONWARNING);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        ret = 0;
        break;

    default:
        ret = DefWindowProc(hWnd, uMessage, wParam, lParam);
        break;
    }

    return ret;
}

 

출력 결과

그림 1 Hello, World!

 

API 4. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);

창으로 메시지가 전달될 때마다 작업을 수행합니다. 반환 값은 대개 0L이거나 DefWindowProc이 반환하는 값입니다.

 

hWnd [IN]

메시지가 들어온 창 핸들입니다.

 

uMessage [IN]

창에 전달된 메시지입니다. 메시지의 종류는 매우 다양한데, 이번 화에서 다루는 기본적인 메시지는 다음과 같습니다.

 

표 1. 기본적인 WM_ 메시지

상수

의미

WM_CREATE

창 객체가 만들어질 때 발생합니다.

WM_DESTROY

창 객체가 소멸되려 할 때 발생합니다.

WM_PAINT

창을 새로 그려야 할 때 수시로 발생합니다.

 

wParam [IN]

메시지를 수식하는 WORD형 매개변수입니다. 대개 핸들/정수가 전달됩니다.

 

lParam [IN]

메시지를 수식하는 LONG형 매개변수입니다. 대개 포인터가 전달됩니다.

API 5. int WINAPI MessageBox(IN HWND hWnd, IN LPCTSTR lpText, IN LPCTSTR lpCaption, IN UINT uType);

메시지 박스를 출력합니다. 반환 값은 메시지 박스를 누른 버튼에 대한 고유 번호입니다.

 

표 2. MessageBox 반환 상수

상수명

설명

IDABORT 

'중단' 버튼이 눌렸습니다.

IDCANCEL 

'취소' 버튼이 눌렸습니다.

IDCONTINUE 

'계속' 버튼이 눌렸습니다.

IDIGNORE 

'무시' 버튼이 눌렸습니다.

IDNO 

'아니요' 버튼이 눌렸습니다.

IDOK 

'확인' 버튼이 눌렸습니다.

IDRETRY 

'다시 시도' 버튼이 눌렸습니다.

IDTRYAGAIN 

'재시도' 버튼이 눌렸습니다.

IDYES

'확인' 버튼이 눌렸습니다.

 

hWnd [IN]

메시지 상자를 소유하는 창의 핸들입니다. 소유자가 없다면 NULL을 지정합니다.

 

lpText [IN]

출력할 메시지입니다.

 

lpCaption [IN]

메시지 상자의 제목입니다.

 

uType [IN]

메시지 상자의 출력 옵션입니다.

 

버튼 속성

상수명

의미

MB_ABORTRETRYIGNORE 

'건너뛰기', '다시 시도', '무시' 버튼을 보입니다.

MB_CANCELTRYCONTINUE 

'취소', '재시도', '계속하기' 버튼을 보입니다..

MB_HELP 

버튼 끝에 '도움말' 버튼을 추가합니다. 단독으로 쓰일 경우 '확인'과 '도움말'이 표시됩니다. 이 버튼을 누르거나 F1을 누르면 소유주 창에 WM_HELP가 전달됩니다.

MB_OK 

'확인' 버튼을 보입니다.

MB_OKCANCEL 

'확인', '취소' 버튼을 보입니다.

MB_RETRYCANCEL 

'재시도', '취소' 버튼을 보입니다.

MB_YESNO 

'예', '아니오' 버튼을 보입니다.

MB_YESNOCANCEL 

'예', '아니오', '취소' 버튼을 보입니다.

아이콘

상수명

의미

MB_ICONEXCLAMATION 

Exclamation 아이콘을 보입니다.

MB_ICONWARNING 

Warning 아이콘을 보입니다.

MB_ICONINFORMATION 

Information 아이콘을 보입니다.

MB_ICONASTERISK 

Asterisk 아이콘을 보입니다.

MB_ICONQUESTION 

Question 아이콘을 보입니다.

다만 MSDN에 의한다면, 이 아이콘을 더 이상 쓰지 말 것을 권장하고 있습니다. 왜냐하면 사용자들은 단순히 아이콘만 가지고 메시지의 종류를 판별할 수 없기 때문입니다. 메시지 박스를 띄우는 것 자체가 사용자에게 뭘 물어보려는 의도이기 때문에 단순히 물음표 아이콘만 보여준다면 사용자로서는 이 메시지가 경고 메시지인지, 오류 메시지인지를 알 수 없다는 것입니다. 따라서 이 값은 하위 호환성을 위해서 남겨주었을 뿐, 메시지 박스를 띄워야 할 상황이라면 메시지의 목적에 맞는 구체적인 아이콘을 사용할 것을 권장합니다.

MB_ICONSTOP

Stop 아이콘입니다.

MB_ICONERROR 

Error 아이콘입니다.

MB_ICONHAND 

Hand 아이콘입니다.

기본 버튼

상수명

의미

MB_DEFBUTTON1 

1번째 버튼이 기본 버튼입니다.

MB_DEFBUTTON2 

2번째 버튼이 기본 버튼입니다.

MB_DEFBUTTON3 

3번째 버튼이 기본 버튼입니다.

MB_DEFBUTTON4 

4번째 버튼이 기본 버튼입니다.

모달 속성

Value 

Meaning 

MB_APPLMODAL

메시지 박스가 떠 있는 동안 소유주 창에 포커스를 둘 수 없습니다. 소유주 창이 활성화 되려면 이 메시지 박스에 반드시 응답해야 합니다. MB_SYSMODAL이나 MB_TASKMODAL을 지정한다면 이 속성을 기본으로 딸려옵니다.

MB_SYSTEMMODAL

메모리 부족과 같이 응용 프로그램 실행에 있어 치명적인 오류가 났을 때 사용자로부터 빨리 주목을 받기 위해서는 이 속성을 씁니다. 이 속성을 주면 현재 떠 있는 모든 윈도우보다 가장 위에 뜹니다.

MB_TASKMODAL

DLL처럼 hWnd로 지정할 만한 별도의 창이 없이 실행되고 있을 경우 이 속성을 지정하면 현재 스레드에서 실행중인 모든 창보다 위에 뜹니다.

기타 속성

상수명

의미

MB_DEFAULT_DESKTOP_ONLY

사용자가 로그인 했고 기본 데스크탑이 실행된 경우에만 띄웁니다. 즉, Windows XP의 '새로운 시작' 같은 화면이 뜬 상태에서는 메시지 띄우지 말라는 의미입니다.

MB_RIGHT

텍스트가 오른쪽 정렬됩니다.

MB_RTLREADING

아랍어나 히브리어처럼 오른쪽에서 왼쪽으로 읽는 언어로 된 메시지라면 이 속성을 줍니다.

MB_SETFOREGROUND

Foreground 윈도우로 띄웁니다.

MB_TOPMOST

항상 위 옵션(WS_EX_TOPMOST)으로 메시지 창을 엽니다.

MB_SERVICE_NOTIFICATION

0x00200000L

로그인한 사용자가 없더라도 화면에 창을 띄웁니다. 이때 hWnd는 NULL이어야 합니다. MB_DEFAULT_DESKTOP_ONLY와 반대의 개념입니다.