본문 바로가기

프로그램언어/C++

MID 프로그래밍

MID 프로그래밍

 

CLIENTCREATESTRUCT 구조체

typedef struct {

    HANDLE        hWindowMenu;    // 응용 프로그램의 메인 메뉴 중 선택한 부메뉴에 대한 핸들 값

    UINT             idFirstChild;         // 생성할 자식 윈도우의 ID로 사용할 정수값,
                                               // 두 번째 자식 윈도우부터는 1씩 증가시킨 정수를 ID로 사용

} CLIENTCREATESTRUCT;

MDICREATESTRUCT 구조체

typedef struct tagMDICREATESTRUCT {
    LPCTSTR       szClass;        // MDI 작식 창의 클래스 이름

    LPCTSTR       szTitle;        // MDI 자식 창의 제목

    HANDLE      hOwner;       // MDI 클라이언트 창을 만드는 응용 프로그램의 인스턴스에 대한 핸들
    int              x;                   // MDI 자식 창의 초기 수평 위치 (클라이언트 좌표)입니다. 이 멤버가 
                                            // CW_USEDEFAULT 이면 MDI 자식 창에 기본 가로 위치가 할당됩니다. 

    int              y;                   // MDI 자식 창의 초기 수직 위치 (클라이언트 좌표)입니다. 이 멤버가
                                            // CW_USEDEFAULT 이면 MDI 자식 창에 기본 세로 위치가 할당됩니다.

    int              cx;                 // MDI 자식 창의 초기 너비 (장치 단위)입니다. 이 멤버가 CW_USEDEFAULT 이면
                                            // MDI 자식 창에 기본 너비가 할당됩니다.

    int              cy;                // MDI 자식 창의 초기 높이 (장치 단위)입니다. 이 멤버가 CW_USEDEFAULT 로 설정 되면
                                           // MDI 자식 창에 기본 높이가 할당됩니다.

    DWORD      style;           // MDI 자식 창의 스타일

    LPARAM     lParam;        // 애플리케이션 정의 값

} MDICREATESTRUCT

DWORD style : MDI 자식 창의 스타일입니다. MDI 클라이언트 창이 MDIS_ALLCHILDSTYLES 창 스타일 로 생성 된 경우이 멤버는 창 스타일 페이지에 나열된 창 스타일의 조합이 될 수 있습니다 . 그렇지 않으면이 멤버는 다음 값 중 하나 이상이 될 수 있습니다.

값의미

   
WS_MINIMIZE 처음에 최소화 된 MDI 자식 창을 만듭니다.
WS_MAXIMIZE 처음에 최대화 된 MDI 자식 창을 만듭니다.
WS_HSCROLL 가로 스크롤 막대가있는 MDI 자식 창을 만듭니다.
WS_VSCROLL 세로 스크롤 막대가있는 MDI 자식 창을 만듭니다.

 

 

MID 프로그램 만들기

#include <windows.h>

#include <TCHAR.H>

#include "resource.h"

LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

LRESULT CALLBACK ChildWndProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);

HINSTANCE hInst;

 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

    HWND hwnd;

    MSG msg;

    WNDCLASS WndClass;

    hInst = hInstance;

    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    WndClass.lpfnWndProc = FrameWndProc;

    WndClass.cbClsExtra = 0;

    WndClass.cbWndExtra = 0;

    WndClass.hInstance = hInstance;

    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    WndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);

    WndClass.lpszClassName = _T("Window Class Name");

    RegisterClass(&WndClass);

 

    WndClass.lpfnWndProc = ChildWndProc;

    WndClass.lpszMenuName = NULL;

     WndClass.lpszClassName = _T("Child Window Class Name");

     RegisterClass(&WndClass);

 

    hwnd = CreateWindow( _T("Window Class Name"), _T("Main Window Title"), WS_OVERLAPPEDWINDOW,

         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, nCmdShow);

 

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return (int)msg.wParam;

}

 

LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    static HWND hwndClient;

    CLIENTCREATESTRUCT clientcreate;

    MDICREATESTRUCT mdicreate;

    HWND hwndChild;

 

    switch (iMsg)

    {

    case WM_CREATE:

        clientcreate.hWindowMenu = GetSubMenu(GetMenu(hwnd), 0);

        clientcreate.idFirstChild = 100;

        hwndClient = CreateWindow(

            _T("MDICLIENT"), NULL,

           WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,

           0, 0, 0, 0,

           hwnd,

           NULL,

           hInst,

           (LPSTR)&clientcreate

        );

        ShowWindow(hwndClient, SW_SHOW);

        return 0;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case ID_FILENEW:

            mdicreate.szClass = _T("Child Window Class Name");

            mdicreate.szTitle = _T("Child Window Title Name");

            mdicreate.hOwner = hInst;

            mdicreate.x = CW_USEDEFAULT;

            mdicreate.y = CW_USEDEFAULT;

            mdicreate.cx = CW_USEDEFAULT;

            mdicreate.cy = CW_USEDEFAULT;

            mdicreate.style = 0;

            mdicreate.lParam = 0;

            hwndChild = (HWND)SendMessage(hwndClient, WM_MDICREATE, 0,
                                (LPARAM)(LPMDICREATESTRUCT)&mdicreate);

            return 0;

        }

        break;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefFrameProc(hwnd, hwndClient, iMsg, wParam, lParam);

}

 

LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT iMsg,WPARAM wParam, LPARAM lParam)

{

    switch (iMsg)

    {

    case WM_CREATE:

        break;

    case WM_DESTROY:

    return 0;

    }

    return DefMDIChildProc(hwnd, iMsg, wParam, lParam);

}

실행 결과]

 

 

자식 윈도우 창 정렬하기

    switch (LOWORD(wParam))

    {

   case ID_FILENEW:

        mdicreate.szClass = _T("Child Window Class Name");

        mdicreate.szTitle = _T("Child Window Title Name");

        mdicreate.hOwner = hInst;

        mdicreate.x = CW_USEDEFAULT;

        mdicreate.y = CW_USEDEFAULT;

        mdicreate.cx = CW_USEDEFAULT;

        mdicreate.cy = CW_USEDEFAULT;

        mdicreate.style = 0;

        mdicreate.lParam = 0;

        hwndChild = (HWND)SendMessage(hwndClient, WM_MDICREATE, 0, 
                            (LPARAM)(LPMDICREATESTRUCT)&mdicreate);

        return 0;

    case ID_WINDOW_CLOSE:

        hwndChild = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);

        if (SendMessage(hwndChild, WM_QUERYENDSESSION, 0, 0))

            SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM)hwndChild, 0);

        return 0;

    case ID_TILE:

        SendMessage(hwndClient, WM_MDITILE, 0, 0);

        return 0;

    case ID_CASCADE:

        SendMessage(hwndClient, WM_MDICASCADE, 0, 0);

        return 0;

    case ID_ARRANGE:

        SendMessage(hwndClient, WM_MDIICONARRANGE, 0, 0);
        return 0;

    }

실행 결과]

 

윈도우 분할하기

 

분할 윈도우도 메인 윈도우와 같은 방법으로 생성하고 CreateWindowEx()함수를 사용한다.

 

CreateWindowEx() 함수

HWND CreateWindowExA(

    DWORD         dwExStyle,           // 생성되는 확장 윈도우의 스타일

    LPCSTR          lpClassName,       // 등록된 윈도우 클래스

    LPCSTR          lpWindowName,   // 윈도우 타이틀 텍스트

    DWORD         dwStyle,              // 기본 윈도우 스타일

    int                 X,                     // 생성 윈도우 위치의 X 값

    int                 Y,                    // 생성 윈도우 위치의 Y 값

    int                 nWidth,            // 생성 윈도우의 너비

    int                 nHeight,           // 생성 윈도우의 높이

    HWND            hWndParent,     // 부모 윈도우 핸들

    HMENU           hMenu,           // 사용될 메뉴의 핸들

    HINSTANCE      hInstance,        // 응용 프로그램 인스턴스

    LPVOID            lpParam          // 창에 전달할 값을 가리키는 포인터

);

 

HWNDChildHwnd[2];

LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    static HWND hwndClient;

    CLIENTCREATESTRUCT clientcreate;

    MDICREATESTRUCT mdicreate;

HWND hwndChild;

 

    RECT rectView;

 

    switch (iMsg)

    {

    case WM_CREATE:

        GetClientRect(hwnd, &rectView);

        ChildHwnd[0] = CreateWindowEx(

            WS_EX_CLIENTEDGE,                     // 생성되는 확장 윈도우 스타일

            _T("Child Window Class Name"),     // 등록된 윈도우 클래스

            NULL,                                         // 윈도우 타이틀

            WS_CHILD | WS_VISIBLE,               // 기본 윈도우 스타일

            0,                                              // 윈도우 X좌표 

            0,                                              // 원도우  Y좌표

            rectView.right,                             // 윈도우 너비

            rectView.bottom / 2 - 1,                // 윈도우 높이

            hwnd,                                         // 부모 윈도우 핸들

            NULL,                                         // 사용될 메뉴의 핸들

            hInst,                                          // 응용 프로그램 인스턴스

            NULL                                          // 창에 전달될 정보

        );

 

        ChildHwnd[1] = CreateWindowEx(

            WS_EX_CLIENTEDGE,

            _T("Child Window Class Name"),

            NULL,

            WS_CHILD | WS_VISIBLE,

            0,

            rectView.bottom / 2 + 1,

            rectView.right,

            rectView.bottom / 2 - 1,

            hwnd,

            NULL,

            hInst,

            NULL

        );

        return 0;

    case WM_COMMAND:

실행 결과]

 

메인 윈도우의 크기 조정하기

 

MoveWindow() 함수

BOOL MoveWindow(

    HWND     hWnd,      // 윈도우 핸들

    int           X,            // 윈도우 새 위치의 x 좌표

    int           Y,            // 윈도우 새 위치의 y 좌표

    int           nWidth,     // 윈도우의 새 너비

    int           nHeight,    // 윈도우의 새 높이

    BOOL       bRepaint   // 재조정 후 재출력 여부

);

LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    ....

    RECT rectView;

    static BOOL split;

 

    switch (iMsg)

    {

    case WM_CREATE:

        split = FALSE;

        return 0;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case ID_SPLIT_2X1:

            if (split == TRUE) break;

            split = TRUE;

            GetClientRect(hwnd, &rectView);

            ChildHwnd[0] = CreateWindowEx(

                WS_EX_CLIENTEDGE,

                _T("Child Window Class Name"),

                NULL,

                WS_CHILD | WS_VISIBLE,

                0,

                0,

                rectView.right,

                rectView.bottom / 2 - 1,

                hwnd,

                NULL,

                hInst,

                NULL

            );

 

            ChildHwnd[1] = CreateWindowEx(

                WS_EX_CLIENTEDGE,

                _T("Child Window Class Name"),

                NULL,

                WS_CHILD | WS_VISIBLE,

                0,

                rectView.bottom / 2 + 1,

                rectView.right,

                rectView.bottom / 2 - 1,

                hwnd,

                NULL,

                hInst,

                NULL

            );

            return 0;

실행 결과]

 

자식 윈도우의 크기 조정하기

LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    ....

    static BOOL split;

    static HCURSOR hCursor;

    static int boundary = -1;

 

    switch (iMsg)

    {

    case WM_CREATE:

        split = FALSE;

        return 0;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case ID_SPLIT_2X1:

            ....

            return 0;
        }
        return 0;

    case WM_MOUSEMOVE:

        if (HIWORD(lParam) >= boundary - 2 && HIWORD(lParam) <= boundary + 2)
            SetCursor(hCursor);

        if (wParam == MK_LBUTTON && split == TRUE)

        {

            GetClientRect(hwnd, &rectView);
           // HIWORD(lParam) : 마우스 y좌표

            if (rectView.top + 5 < HIWORD(lParam) && HIWORD(lParam) < rectView.bottom - 5)
                boundary = HIWORD(lParam);

            MoveWindow(ChildHwnd[0], 0, 0, rectView.right, boundary - 1, TRUE);
            //MoveWindow(윈도우핸들, x좌표, y좌표, 너비, 높이, 재출력 여부); 

            MoveWindow(ChildHwnd[1], 0, boundary + 1, rectView.right, rectView.bottom - boundary + 1, TRUE);

        }

        return 0;

    case WM_LBUTTONDOWN:

        if (split == TRUE)

        {

            SetCursor(hCursor);

            SetCapture(hwnd);        // 마우스를 윈도우 내에 캡처하기
                                             // (마우스를 드래그 하는 동안 윈도우 밖으로 나가지 목하도록 하는 함수)

        }

        return 0;

    case WM_LBUTTONUP:

        if (split == TRUE)
            ReleaseCapture();         // 마우스 캡처 해제하기

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefFrameProc(hwnd, hwndClient, iMsg, wParam, lParam);

}

 

실행 결과]

 

자식 윈도우 메시지 처리하기(타이머을 이용하여 원형 출력하기)

LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT iMsg,WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    static int x[2] = { 20, 20 }, y[2] = { 20, 20 }, flag[2];

    int select;

 

    switch (iMsg)

    {

    case WM_CREATE:

        break;

    case WM_TIMER:

        x[wParam] = x[wParam] + 20;

        hdc = GetDC(hwnd);

            Ellipse(hdc, x[wParam] - 20, y[wParam] - 20, x[wParam] + 20, y[wParam] + 20);

        ReleaseDC(hwnd, hdc);

        break;

    case WM_LBUTTONDOWN:

        if (hwnd == ChildHwnd[0])

            select = 0;

        else

            select = 1;

        flag[select] = 1 - flag[select];

        if (flag[select])

            SetTimer(hwnd, select, 100, NULL);

        else

            KillTimer(hwnd, select);

        break;

    case WM_DESTROY:

        return 0;

    }

    return DefMDIChildProc(hwnd, iMsg, wParam, lParam);

}

실행 결과]

 

'프로그램언어 > C++' 카테고리의 다른 글

파일 입출력1  (0) 2021.01.05
컨트롤 윈도우 사용하기  (0) 2021.01.05
대화상자4  (0) 2020.12.31
대화상자3  (0) 2020.12.29
대화상자만들기2  (0) 2020.12.28