. Dangeun.cpp

그러면 이제 호스트인 메인 모듈이 어떻게 작성되어 있나 보도록 하자. 처음 시작 파일치고는 그리 길지 않으며 아주 일반적인 MDI 프로젝트의 원형 그대로이다.

 

#include "stdafx.h"

 

LRESULT CALLBACK DGWndProc(HWND,UINT,WPARAM,LPARAM);

LRESULT CALLBACK DGChildProc(HWND,UINT,WPARAM,LPARAM);

int OnCreate(HWND hWnd,WPARAM wParam,LPARAM lParam);

void OnDestroy(HWND hWnd,WPARAM wParam,LPARAM lParam);

void OnTimer(HWND hWnd,WPARAM wParam,LPARAM lParam);

void OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam);

 

BOOL CALLBACK AboutProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam);

HWND New();

 

HINSTANCE g_hInst;

HWND g_hFrameWnd;

HWND g_hMDIClient;

int g_NewNo=0;

int g_ChildNum=0;

LPSTR lpszClass="Dangeun";

HMENU hMenu1,hMenu2;

 

struct SInfo

{

     CApiEdit Ae;

     TCHAR NowFile[MAX_PATH];

};

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance

            ,LPSTR lpszCmdParam,int nCmdShow)

{

     HWND hWnd;

     MSG Message;

     WNDCLASSEX WndClassEx;

     g_hInst=hInstance;

    

     hMenu1=LoadMenu(g_hInst,MAKEINTRESOURCE(IDR_MENU1));

     hMenu2=LoadMenu(g_hInst,MAKEINTRESOURCE(IDR_MENU2));

 

     WndClassEx.cbSize=sizeof(WNDCLASSEX);

     WndClassEx.cbClsExtra=0;

     WndClassEx.cbWndExtra=0;

     WndClassEx.hbrBackground=(HBRUSH)(COLOR_BTNFACE+1);

     WndClassEx.hCursor=LoadCursor(NULL,IDC_ARROW);

     WndClassEx.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_DANGEUN));

     WndClassEx.hIconSm=(HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_DANGEUN),

          IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),

          GetSystemMetrics(SM_CXSMICON),LR_DEFAULTCOLOR);

     WndClassEx.hInstance=hInstance;

     WndClassEx.lpfnWndProc=(WNDPROC)DGWndProc;

     WndClassEx.lpszClassName=lpszClass;

     WndClassEx.lpszMenuName=MAKEINTRESOURCE(IDR_MENU2);

     WndClassEx.style=0;

     RegisterClassEx(&WndClassEx);

 

     WndClassEx.lpszClassName="DGChild";

     WndClassEx.lpfnWndProc=(WNDPROC)DGChildProc;

     WndClassEx.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_CHILD));

     WndClassEx.hIconSm=(HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_CHILD),

          IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),

          GetSystemMetrics(SM_CXSMICON),LR_DEFAULTCOLOR);

     WndClassEx.lpszMenuName=NULL;

     WndClassEx.cbWndExtra=sizeof(DWORD);

     RegisterClassEx(&WndClassEx);

 

     hWnd=CreateWindow(lpszClass,"당근",WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,

          CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,

          NULL,(HMENU)NULL,hInstance,NULL);

     HACCEL hAccel;

 

     hAccel=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));

     while(GetMessage(&Message,0,0,0)) {

          if (!TranslateMDISysAccel(g_hMDIClient, &Message)) {

              if (!TranslateAccelerator(hWnd,hAccel,&Message)) {

                   TranslateMessage(&Message);

                   DispatchMessage(&Message);

              }

          }

     }

     return (int)Message.wParam;

}

 

LRESULT CALLBACK DGWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     switch(iMessage) {

          case WM_CREATE:return OnCreate(hWnd,wParam,lParam);

          case WM_DESTROY:OnDestroy(hWnd,wParam,lParam);return 0;

          case WM_COMMAND:OnCommand(hWnd,wParam,lParam);break;

          case WM_TIMER:OnTimer(hWnd,wParam,lParam);return 0;

     }

     return(DefFrameProc(hWnd,g_hMDIClient,iMessage,wParam,lParam));

}

 

int OnCreate(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     CLIENTCREATESTRUCT ccs;

     INITCOMMONCONTROLSEX icex;

 

     g_hFrameWnd=hWnd;

     icex.dwSize=sizeof(icex);

     icex.dwICC=ICC_WIN95_CLASSES;

     InitCommonControlsEx(&icex);

 

     ccs.hWindowMenu=GetSubMenu(GetMenu(hWnd),5);

     ccs.idFirstChild=IDM_WINDOWCHILD;

     g_hMDIClient=CreateWindowEx(WS_EX_CLIENTEDGE,"MDICLIENT", NULL,

          WS_CHILD | WS_CLIPCHILDREN |    WS_VISIBLE,

          0,0,0,0,hWnd,(HMENU)NULL, g_hInst, (LPSTR)&ccs);

     SetTimer(hWnd,100,1,NULL);

 

     return 0;

}

 

void OnDestroy(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     PostQuitMessage(0);

}

 

void OnTimer(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     switch (wParam) {

     case 100:

          KillTimer(hWnd,100);

          New();

          break;

     }

}

 

void OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     switch(LOWORD(wParam)) {

     case IDM_FILE_NEW:

          New();

          break;

     case IDM_FILE_EXIT:

          SendMessage(hWnd,WM_CLOSE,0,0);

          break;

     case IDM_WIN_VERT:

          SendMessage(g_hMDIClient, WM_MDITILE,

              (WPARAM)MDITILE_VERTICAL, 0);

          break;

     case IDM_WIN_HORZ:

          SendMessage(g_hMDIClient, WM_MDITILE,

              (WPARAM)MDITILE_HORIZONTAL, 0);

          break;

     case IDM_WIN_CASCADE:

          SendMessage(g_hMDIClient, WM_MDICASCADE,

              (WPARAM)MDITILE_SKIPDISABLED, 0);

          break;

     case IDM_WIN_ARRANGE:

          SendMessage(g_hMDIClient, WM_MDIICONARRANGE, 0, 0);

          break;

     case IDM_HELP_ABOUT:

          DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc);

          break;

     }

}

 

LRESULT CALLBACK DGChildProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     SInfo *pSi;

 

     switch(iMessage) {

     case WM_CREATE:

          g_ChildNum++;

          if (g_ChildNum == 1) {

              SendMessage(g_hMDIClient,WM_MDISETMENU,(WPARAM)hMenu1,

                   (LPARAM)GetSubMenu(hMenu1,5));

              DrawMenuBar(g_hFrameWnd);

          }

          pSi=new SInfo;

          SetWindowLong(hWnd,0,(LONG)pSi);

          pSi->Ae.Create(0,0,0,0,WS_CHILD | WS_VISIBLE,1,hWnd);

          wsprintf(pSi->NowFile,"이름없음 %d",g_NewNo);

          SetWindowText(hWnd,pSi->NowFile);

          return 0;

     case WM_SIZE:

          pSi=(SInfo *)GetWindowLong(hWnd,0);

          MoveWindow(pSi->Ae.hWnd,0,0,LOWORD(lParam),HIWORD(lParam),TRUE);

          break;

     case WM_SETFOCUS:

          pSi=(SInfo *)GetWindowLong(hWnd,0);

          SetFocus(pSi->Ae.hWnd);

          return 0;

     case WM_DESTROY:

          pSi=(SInfo *)GetWindowLong(hWnd,0);

          delete pSi;

          g_ChildNum--;

          if (g_ChildNum==0) {

              SendMessage(g_hMDIClient,WM_MDISETMENU,(WPARAM)hMenu2,NULL);

              DrawMenuBar(g_hFrameWnd);

          }

          return 0;

     }

     return(DefMDIChildProc(hWnd,iMessage,wParam,lParam));

}

 

BOOL CALLBACK AboutProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     switch(iMessage) {

     case WM_INITDIALOG:

          return TRUE;

     case WM_COMMAND:

          switch (LOWORD(wParam))

          {

          case IDOK:

              EndDialog(hDlg,IDOK);

              return TRUE;

          case IDCANCEL:

              EndDialog(hDlg,IDCANCEL);

              return TRUE;

          }

          return FALSE;

     }

     return FALSE;

}

 

HWND New()

{

     MDICREATESTRUCT mcs;

     HWND hActive;

     BOOL bMax;

 

     hActive=(HWND)SendMessage(g_hMDIClient, WM_MDIGETACTIVE,0,(LPARAM)&bMax);

 

     g_NewNo++;

     mcs.szClass="DGChild";

     mcs.szTitle="";

     mcs.hOwner=g_hInst;

     mcs.x=mcs.y=CW_USEDEFAULT;

     mcs.cx=mcs.cy=CW_USEDEFAULT;

     mcs.style=MDIS_ALLCHILDSTYLES | WS_CLIPCHILDREN;

     if (hActive == NULL || bMax == TRUE) {

           mcs.style |= WS_MAXIMIZE;

     }

     return (HWND)SendMessage(g_hMDIClient, WM_MDICREATE, 0,

          (LPARAM)(LPMDICREATESTRUCT)&mcs);

}

 

PCH 기능을 사용하기 위해 stdafx.h 하나만 인클루드하고 있다. 이 소스는 다음 절에서 자세하게 분석해 볼 것이다. 이제 컴파일한 후 실행해보자.

처음 실행되면 차일드 하나가 최대화되어 나타나는데 파일/새 파일 명령으로 언제든지 새 문서창을 만들 수 있다. 창 메뉴에는 열린 차일드의 목록이 나타나며 계단식, 수평, 수직으로 자식창을 정렬하는 기능도 제공된다. 메뉴에는 많은 항목들이 등록되어 있지만 아직 기능을 만들지 않았기 때문에 거의 대부분은 동작하지 않는 상태이다. 앞으로 실습을 통해 이 기능들을 하나 둘씩 만들어 나갈 것이다.