cyphen156

Win32 API #1 본문

프로그래밍/Win32 API

Win32 API #1

cyphen156 2024. 7. 20. 20:12

취업전 코드 활용 재활 겸 다 까먹은 윈도우즈 32API 복습용 글쓰기

 

윈도우즈 32 API는 마이크로 소프트에서 Windows 운영체제를 위한 타겟플랫폼 개발을 지원하기 위해 만든 API이자 SDK이다.

프로젝트의 생성은 다음 스크린샷을 따라 생성하면 된다.

맨 처음 프로젝트를 생성하고 나면 확인해 볼 것은 딱 3개다. 

1. 프로그램의 메인 시작점인 Win32API.cpp

2. 프로젝트 내의 리소스들을 관리하는 Resource.h와 Resoruce.rc

3. 프로그램이 빌드되었을 때 표시될 아이콘인 Winc32API.ico와 small.ico

Win32API.cpp

프로젝트명.cpp파일로 프로그램의 메인 진입점이 된다. 

React에서의 app.js/index.js에 해당하는 파일이다.

처음 메인파일을 열어보면 뭔가 잔뜩 쓰여있는데 몇가지 신경써야할 핵심 요소가 있다. 

전처리기 매크로 #define MAX_LOADSTRING 100

#define MAX_LOADSTRING 100
// 프로그램 실행 시 표시되는 타이틀의 최대 글자수를 결정한다. 
// 0으로 지정하면 에러가 발생한다.

Main()함수에 해당하는 wWinMAIN

이 함수 안에서 모든 프로그램 동작이 수행된다. 보다보면 무한 반복문으로 메세지 루프가 존재하는데 사용자의 입력수신을 대기하는 이벤트 처리기라 생각하면 된다.

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,  // main(str argc, srargv)
                     _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_WIN32API, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 애플리케이션 초기화를 수행합니다:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32API));

    MSG msg;

    // 기본 메시지 루프입니다:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

 

 

메인파일은 이정도만 알고 있으면 된다.

이제 프로그램을 디버깅 해보면 다음과 같은 프로그램이 실행된다.

하얀 창 안에 있는 상자모양 아이콘과 프로젝트명,  파일과 도움말이라는 메뉴상자가 존재한다. 이것들은 어디있나 싶어서 찾아보면 리소스 파일이라는 곳에 존재한다. 

리소스 뷰를 통해 Resource.rc파일을 열어보면 여러가지 메뉴들이 보인다.

String Table

프로그램의 이름수정할 수 있는 곳이다. 캡션이라는 곳을 수정하면 된다.

코드를 통해 보면 다음과 같다.

STRINGTABLE
BEGIN
    IDS_APP_TITLE           "Win32API를 수정하면 되나?"
    IDC_WIN32API            "WIN32API"
END

그런데 저 109번에 해당하는 IDC_WIN32API에 해당하는 캡션은 수정해도 변경점을 찾을 수 없다. 아마 작업 관리자에 등록되는 프로세스 명이 아닐까 싶은데 정확하진 않으니 나중에 다시 확인하도록 하자.

++찾았다. Main함수 내부에서 사용되는 가속키 테이블에 대한 이름 지정이었다. 밑에서 후술할 Acclerator의 이름에 해당하는 것 같다.

Menu리소스를 리소스 뷰를 통해 보면 다음과 같이 생겼다.

여기에 입력을 통해 새 메뉴 탭을 생성하거나 코드에서 추가할 수 있다.

IDC_WIN32API MENU
BEGIN
    POPUP "파일(&F)"
    BEGIN
        MENUITEM "끝내기(&X)",                     IDM_EXIT
        MENUITEM "1",                           ID_32771
        MENUITEM "2",                           ID_32772
        MENUITEM "3",                           ID_32773
    END
    POPUP "도움말(&H)"
    BEGIN
        MENUITEM "정보(&A)...",                   IDM_ABOUT
    END
END

메뉴 바가 JSON객체와 비슷하게 생긴 것을 알 수 있다. 또한 이벤트 처리를 위해 ID값을 def하여 매크로로 처리하고 있는 것 같다.

Dialog라는 리소스가 있는데 이것은 사용자 상호작용을 하기 위한 대화 상자 창들을 관리하는 곳이다.  

메뉴탭-도움말-정보를 클릭하면 나오는 대화상자 창

IDD_ABOUTBOX DIALOGEX 0, 0, 163, 70	// 대화상자 크기정보 (0, 0) to (163, 70)
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "정보 Win32API"
FONT 9, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    ICON            IDI_WIN32API,IDC_STATIC,14,14,20,20
    LTEXT           "Win32API, 버전 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2024",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "확인",IDOK,106,49,50,14,WS_GROUP
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 156
        TOPMARGIN, 7
        BOTTOMMARGIN, 63
    END
END
#endif    // APSTUDIO_INVOKED

대화상자 창에 대한 이벤트 처리는 메인함수내에 존재하는 메세지 루프를 통해 처리되는데, 다음 코드를 통해 수행된다. 

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;
}

case IDM_ABOUT:

    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

WindProc에서는 메인 창의 메뉴탭에서 발생하는 이벤트들에 대한 처리를 수행하고 있고, About이라는 모달 대화 함수를 통해 이전에 생성한 IDD_ABOUTBOX라는 정보 모달창에 대한 이벤트를 전달하고 있다. 

모달 대화 함수는 사용자가 해당 창을 닫기 전까지 다른 창과의 상호작용을 막는 함수이고, 모달리스 대화상자는 다음 대화상자를 통해 이벤트를 처리할 수 있다.

HWND hDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
ShowWindow(hDlg, SW_SHOW);

실제로 메뉴 1을 누르면 모달리스 대화상자가 나오도록 이벤트를 만들어 본다면 다음과 같다. 

메뉴 1에 대한 정보는 다음과 같다.

case ID_32771:
{
    HWND hDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_32771), hWnd, About);
    if (hDlg != NULL)
    {
        ShowWindow(hDlg, SW_SHOW);
    }
    else
    {
        MessageBox(hWnd, L"CreateDialog 실패", L"오류", MB_OK | MB_ICONERROR);
    }
}
break;

위의 코드를 WindProc함수에 추가하면 다음과 같이 모달창이 발생한다

또한 Acclerator 라는 리소스는 프로그램에서 사용되는 단축키를 설정하는 곳이다. 

ICON은 대강 프로그램 아이콘을 의미하는 것이니 넘기겠다.

이로써 프로젝트 시작 구성에 대한 내용을 대강 파악하였다. 개인적으로 혼자 구글링해가면서 뒤적거리면서 공부하기 때문에 현업과는 매우 멀 수 있으니 그냥 참고용 정도로만 사용하면 감사드립니다.

'프로그래밍 > Win32 API' 카테고리의 다른 글

문자 집합(MBCS VS UniCode)  (0) 2024.08.22