C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[105] [KTS의 C++빌더] 최소 크기 Win32 실행파일 크기로 어플제작의 실제.
김태선 [cppbuilder] 18990 읽음    2006-06-10 20:23
//---------------------------------------------------------------------------
// 김태성의 C++빌더 강좌 : 최소 실행파일크기 Win32 실제 어플 만들기.
//---------------------------------------------------------------------------

며칠전에는 C++빌더로 최소크기의 win32 어플리케이션을 제작하는 것을 어떻게 하는지 살펴보았다.
그때는 방법 소개만을 목적으로 하였으므로, 어플리케이션에 대한 인스턴스 핸들인 HInstance 가 없어
윈도 창을 만들 수 없었다.
이번에는 실제로 윈도 창이 있는 정상적인 진짜 어플을 제작해 보자.

방법은 WinMain으로 넘기는 파라메터중에 HInstance와 nCmdShow 값만 제대로 세팅해주면 된다.
물론 커맨드라인 인자를 받는 어플을 만드는 경우는 그것도 처리해야겠지만,
윈도 환경이 되면서 거의 쓰이지 않으므로 여기서는 생략한다.

아래는 메인의 소스이다.

//---------------------------------------------------------------------------
// 최소 크기 win32 어플리케이션 만들기. 2번째 버전.
//         HINSTANCE 를 받을 수 있게 했다.
//         윈도를 만들려면 있어야 하기 때문이다.
//
// Written by 김태성
//---------------------------------------------------------------------------

#define _fmode         xxx_fmode
#define _fileinfo     xxx_fileinfo
#include <windows.h>
#pragma hdrstop
#undef _fmode
#undef _fileinfo

//---------------------------------------------------------------------------
#pragma link "c0w32.obj"
#pragma link "cw32.lib"

//WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
// cw32.lib에 들어 있는 것을 여기서 다시 구현한다.
extern "C"
{

void    _startup()
{
    WinMain(GetModuleHandle(NULL), NULL, NULL, SW_RESTORE);    // 원래는 파라메터를 해석해서 보내줘야 함.
    exit(0);    // 정상종료를 위해 강제종료루틴을 부른다.
}

void    __CRTL_VCL_Init(void) { }
void _RTLENTRY __declspec(naked) __CRTL_VCLLIB_Linkage (void)
{
    __emit__(0xC3); /* asm ret */
}

void    __CRTL_MEM_UseBorMM() { }
void    _ExceptInit() { }

void    __CRTL_TLS_Alloc() { }
void    __CRTL_TLS_Free() { }
void    __CRTL_TLS_GetValue() { }
void    __CRTL_TLS_SetValue() { }
void    __CRTL_TLS_InitThread() { }
void    __CRTL_TLS_ExitThread() { }
void    _matherr() { }
void    _matherrl() { }
void    _GetExceptDLLinfoInternal() { }
void    _wargv_expand_ptr() { }
void    _argv_expand_ptr() { }
void    _handle_setargv() { }
void    _handle_exitargv() { }
void    _handle_wsetargv() { }
void    _handle_wexitargv() { }
void    _turboFloat() { }
void    _setargv__() { }
void    _setenvp__() { }
void    _fmode() { }
void    _fileinfo() { }

}
//---------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
char  *szClass = "CBuilderSample";

#pragma argsused
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd;
    MSG  Message;
    WNDCLASS WndClass;
    g_hInst = 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)WndProc;
    WndClass.lpszClassName= szClass;
    WndClass.lpszMenuName=NULL;
    WndClass.style=CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&WndClass);

    hWnd=CreateWindow(szClass,szClass,WS_OVERLAPPEDWINDOW | WS_VSCROLL,
          CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
          NULL, (HMENU)NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);

    while(GetMessage(&Message,0,0,0))
    {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    return Message.wParam;
}

LRESULT CALLBACK PASCAL WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    char  *s;
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        case WM_LBUTTONDOWN:
            MessageBox(hWnd,
                "붉은악마의 상징 도깨비 문양은 바로 배달국 14대 환웅이신 치우천황을 뜻합니다.\n\n"
                "중국인의 시조인 헌원과의 73차례에 걸친 전쟁에서 모두 승리했던 분입니다.\n\n"
                "그 중에서도 탁록의 전투가 유명하며, 치우천황은 최초로 철로 무기를 만들어 쓰셨던 분입니다.\n\n"
                "중국인은 치우천황 소리만 들어도 벌벌 떨었고, 이후 치우천황은 전쟁에 나가는\n\n"
                "모든 장수들이 반드시 천제를 지내는 숭배의 대상이 되었습니다.\n\n"
                "중국역사에서 큰 전쟁을 치루는 왕들은 모두 치우천황에서 제사를 올리고 출정했습니다\n\n"
                "단순한 도깨비 문양이 아니며 대륙을 호령했던 우리 조상의 혼입니다\n\n",
                "위대한 우리의 조상",MB_OK);
            return 0;
        case WM_PAINT:
            hdc=BeginPaint(hWnd,&ps);
            SetTextAlign(hdc, TA_CENTER);
            s = "C++ 개발툴의 중심 C++Builder";
            TextOut(hdc,300,60, s, strlen(s));
            s = "클릭해 보세요";
            TextOut(hdc,300,100, s, strlen(s));
            EndPaint(hWnd,&ps);
            return 0;
    }
    return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
//---------------------------------------------------------------------------

WinMain 함수 안은 그냥 정상적인 어플일 뿐이다. 달리 설명할 것은 아무것도 없다.
다만 WinMain을 호출하는 startup 함수에서
어떻게 해서 WinMain을 호출하는가만 살펴보면 된다.

WinMain(GetModuleHandle(NULL), NULL, NULL, SW_RESTORE);

이것은 커맨드라인 인자를 제외하고는 정상적으로 WinMain을 호출하는 방식과 같다.
그러므로 정상적인 어플의 동작을 가능케 한다.

컴파일해보면 배포가능한 실행화일이 만들어 지는데, 정확하게 8KB가 된다.
필자가 중간에 메시지를 많이 넣어 크기가 이전보다 약간 증가했는데 이 크기 역시,
VC++이나 델파이로 순수 win32 어플을 만들때 보다 작은,
C++ 컴파일러로 만들 수 있는 가장 작은 크기이다.

중간에
#pragma link "cw32.lib"
로 라이브러리를 링크하는데 이미 프로그램에서 구현한 것이 링크 규약상
우선 링크되어 cw32.lib는 무시되므로 문장이 있어도 상관 없다.

이 프로젝트는 C++Builder6에서 테스트되었으나,
C++Builder5나 그 이하 버전에도 그대로 적용될 수 있다.
뿐만 아니라 최신의 BDS 2006에서도 비슷한 방법을 사용할 수 있으리라 생각된다.
BDS2006이 설치되어 있지 않아 실험은 하지 못했으나, 동작 원리가 대동소이 하기 때문이다.


실제 제작한 파일을 첨부해서 올린다.



//---------------------------------------------------------------------------
// 김태성 cppbuilder@naver.com
// 이 강좌는 아무 곳에나 비상업적인 용도에 한해 내용 변경 없이 원래의 출처를 명시하여
// 배포할 수 있습니다. 단, 필자의 이메일로 게제 사실을 통보해야 합니다.
//---------------------------------------------------------------------------
김호광 [testcode]   2006-06-12 18:53 X
잘 봤네요 옛날에 어셈으로 윈도우 만들기 소스가 생각나네요 4kb 정도로 기억나네요
Lloyd von Reuenthal [tinydew4]   2006-09-01 09:25 X
앗 호광님 여기서 보네요 ㅋㅋ
요즘 전역 후 사회 적응차 둘러보는 중...-_-;

+ -

관련 글 리스트
105 [KTS의 C++빌더] 최소 크기 Win32 실행파일 크기로 어플제작의 실제. 김태선 18990 2006/06/10
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.