본문 바로가기

Windows/Windows API

MDI

#include <windows.h>
#include "resource.h"

// 프레임 윈도우와 차일드의 윈도우 프로시저
LRESULT CALLBACK MDIWndProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK MDIDrawProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK MDIEditProc(HWND,UINT,WPARAM,LPARAM);

// 전역 변수들
LPSTR lpszClass="MultiMDI";
HINSTANCE g_hInst;
HWND g_hFrameWnd;
HWND g_hMDIClient;
HMENU hMenu1, hMenu2, hMenu3;
HMENU hMenu1W,hMenu2W,hMenu3W;
int EditNum=1;
int DrawNum=1;

// 텍스트 에디터 차일드의 개별 정보 구조체
struct tagEditData {
    int Num;
    HWND hEdit;
};

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
         ,LPSTR lpszCmdParam,int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst=hInstance;

    // 메인 윈도우(프레임 윈도우) 클래스 등록
    WndClass.cbClsExtra=0;
    WndClass.cbWndExtra=0;
    WndClass.hbrBackground=(HBRUSH)COLOR_APPWORKSPACE+1;
    WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    WndClass.hInstance=hInstance;
    WndClass.lpfnWndProc=(WNDPROC)MDIWndProc;
    WndClass.lpszClassName=lpszClass;
    WndClass.lpszMenuName=NULL;
    WndClass.style=0;
    RegisterClass(&WndClass);

    // 프레임 윈도우 만듬
    hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
        NULL,(HMENU)NULL,hInstance,NULL);
    ShowWindow(hWnd,nCmdShow);
    g_hFrameWnd=hWnd;

    // 텍스트 에디터 차일드 윈도우 클래스 등록
    WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.lpszClassName="MDIExamEdit";
    WndClass.lpfnWndProc=(WNDPROC)MDIEditProc;
    WndClass.hIcon=LoadIcon(NULL,IDI_WINLOGO);
    WndClass.lpszMenuName=NULL;
    WndClass.cbWndExtra=sizeof(DWORD);
    RegisterClass(&WndClass);

    // 그래픽 에디터 차일드 윈도우 클래스 등록
    WndClass.lpszClassName="MDIExamDraw";
    WndClass.lpfnWndProc=(WNDPROC)MDIDrawProc;
    WndClass.hIcon=LoadIcon(NULL,IDI_WINLOGO);
    WndClass.lpszMenuName=NULL;
    WndClass.cbWndExtra=sizeof(DWORD);
    WndClass.style=CS_DBLCLKS;
    RegisterClass(&WndClass);

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

LRESULT CALLBACK MDIWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    CLIENTCREATESTRUCT ccs;
    MDICREATESTRUCT mcs;
    switch(iMessage) {
    case WM_CREATE:
        // 각 차일드의 메뉴 핸들과 윈도우 메뉴를 미리 구해 놓는다.
        hMenu1=LoadMenu(g_hInst,MAKEINTRESOURCE(IDR_MENU1));
        hMenu2=LoadMenu(g_hInst,MAKEINTRESOURCE(IDR_MENU2));
        hMenu3=LoadMenu(g_hInst,MAKEINTRESOURCE(IDR_MENU3));
        hMenu1W=GetSubMenu(hMenu1,0);
        hMenu2W=GetSubMenu(hMenu2,1);
        hMenu3W=GetSubMenu(hMenu3,1);

        // 차일드가 없을 때는 hMenu1을 사용한다.
        SetMenu(hWnd,hMenu1);
        
        // 프레임 윈도우 만듬
        ccs.hWindowMenu=hMenu1W;
        ccs.idFirstChild=IDM_WINDOWCHILD;
        g_hMDIClient=CreateWindow("MDICLIENT", NULL, WS_CHILD | WS_VSCROLL |
            WS_HSCROLL | WS_CLIPCHILDREN,
            0,0,0,0,hWnd,(HMENU)NULL, g_hInst, (LPSTR)&ccs);
        ShowWindow(g_hMDIClient, SW_SHOW);
        return 0;
    case WM_COMMAND:
        switch(LOWORD(wParam)) {
        case ID_FILE_NEWEDIT:
            mcs.szClass="MDIExamEdit";
            mcs.szTitle="Edit";
            mcs.hOwner=g_hInst;
            mcs.x=mcs.y=CW_USEDEFAULT;
            mcs.cx=mcs.cy=CW_USEDEFAULT;
            mcs.style=MDIS_ALLCHILDSTYLES;
            SendMessage(g_hMDIClient, WM_MDICREATE, 0,
                (LPARAM)(LPMDICREATESTRUCT)&mcs);
            break;
        case ID_FILE_NEWDRAW:
            mcs.szClass="MDIExamDraw";
            mcs.szTitle="Draw";
            mcs.hOwner=g_hInst;
            mcs.x=mcs.y=CW_USEDEFAULT;
            mcs.cx=mcs.cy=CW_USEDEFAULT;
            mcs.style=MDIS_ALLCHILDSTYLES;
            SendMessage(g_hMDIClient, WM_MDICREATE, 0,
                (LPARAM)(LPMDICREATESTRUCT)&mcs);
            break;
        case ID_WIN_TILE:
            SendMessage(g_hMDIClient, WM_MDITILE,
                (WPARAM)MDITILE_HORIZONTAL, 0);
            break;
        case ID_WIN_CASCADE:
            SendMessage(g_hMDIClient, WM_MDICASCADE,
                (WPARAM)MDITILE_SKIPDISABLED, 0);
            break;
        case ID_WIN_ARRANGE:
            SendMessage(g_hMDIClient, WM_MDIICONARRANGE, 0, 0);
            break;
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return(DefFrameProc(hWnd,g_hMDIClient,iMessage,wParam,lParam));
}

// 텍스트 에디터의 윈도우 프로시저
LRESULT CALLBACK MDIEditProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    char str[128];
    HWND hEdit;
    tagEditData *pED;
    switch(iMessage) {
    case WM_CREATE:
        // 캡션에 차일드 번호를 출력한다.
        wsprintf(str, "Edit %d", EditNum);
        SetWindowLong(hWnd, 0, EditNum);
        SetWindowText(hWnd, str);

        // 클라이언트 영역에 에디트 컨트롤을 배치한다.
        hEdit=CreateWindow("edit",NULL,WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
            | ES_MULTILINE | ES_AUTOVSCROLL | WS_HSCROLL | WS_VSCROLL,
            0,0,0,0,hWnd,(HMENU)100,g_hInst,NULL);

        // 에디트 컨트롤의 핸들과 차일드 번호를 구조체에 작성한 후
        // 여분 메모리에 이 포인터를 저장한다.
        pED=(tagEditData *)malloc(sizeof(tagEditData));
        pED->hEdit=hEdit;
        pED->Num=EditNum;
        SetWindowLong(hWnd,0,(LONG)pED);
        EditNum++;
        return 0;
    case WM_MDIACTIVATE:
        // 활성화될 때 자신의 메뉴를 프레임에 부착시킨다.
        if (lParam==(LPARAM)hWnd)
            SendMessage(g_hMDIClient,WM_MDISETMENU,
            (WPARAM)hMenu3,(LPARAM)hMenu3W);
        else
            SendMessage(g_hMDIClient,WM_MDISETMENU,
            (WPARAM)hMenu1,(LPARAM)hMenu1W);
        DrawMenuBar(g_hFrameWnd);
        return 0;
    case WM_SIZE:
        pED=(tagEditData *)GetWindowLong(hWnd,0);
        MoveWindow(pED->hEdit, 0, 0, LOWORD(lParam), HIWORD(lParam),TRUE);
        return 0;
    case WM_SETFOCUS:
        pED=(tagEditData *)GetWindowLong(hWnd,0);
        SetFocus(pED->hEdit);
        return 0;
    case WM_DESTROY:
        pED=(tagEditData *)GetWindowLong(hWnd,0);
        free(pED);
        break;
    }
    return(DefMDIChildProc(hWnd,iMessage,wParam,lParam));
}

// 드로우의 윈도우 프로시저
LRESULT CALLBACK MDIDrawProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    char str[128];
    static int x;
    static int y;
    static BOOL bnowDraw=FALSE;
    switch(iMessage) {
    case WM_CREATE:
        wsprintf(str, "Draw %d", DrawNum);
        SetWindowLong(hWnd, 0, DrawNum);
        DrawNum++;
        SetWindowText(hWnd, str);
        return 0;
    case WM_MDIACTIVATE:
        if (lParam==(LPARAM)hWnd)
            SendMessage(g_hMDIClient,WM_MDISETMENU,
            (WPARAM)hMenu2,(LPARAM)hMenu2W);
        else
            SendMessage(g_hMDIClient,WM_MDISETMENU,
            (WPARAM)hMenu1,(LPARAM)hMenu1W);
        DrawMenuBar(g_hFrameWnd);
        return 0;
    case WM_LBUTTONDOWN:
        x=LOWORD(lParam);
        y=HIWORD(lParam);
        bnowDraw=TRUE;
        return 0;
    case WM_MOUSEMOVE:
        if (bnowDraw==TRUE) {
            hdc=GetDC(hWnd);
            MoveToEx(hdc,x,y,NULL);
            x=LOWORD(lParam);
            y=HIWORD(lParam);
            LineTo(hdc,x,y);
            ReleaseDC(hWnd,hdc);
        }
        return 0;
    case WM_LBUTTONUP:
        bnowDraw=FALSE;
        return 0;
    case WM_LBUTTONDBLCLK:
        InvalidateRect(hWnd, NULL, TRUE);
        return 0;
    }
    return(DefMDIChildProc(hWnd,iMessage,wParam,lParam));
}

'Windows > Windows API' 카테고리의 다른 글

그림 인쇄(print)  (0) 2013.10.01
텍스트 인쇄 (print)  (0) 2013.10.01
클립보드 텍스트 복사 (Clipboard)  (0) 2013.10.01
클립보드 에디트 복사 (Clipboard)  (0) 2013.10.01
클립보드 그림 복사 (Clipboard)  (0) 2013.10.01