Linguagem C - MDI File Editor


#include <windows.h>
#include <commctrl.h>

#include "resource.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK MDIChildWndProc(HWND, UINT, WPARAM, LPARAM);

char g_szAppName[] = "MyMDIWindow";
char g_szChild[]   = "MyMDIChild";
HINSTANCE g_hInst;
HWND g_hMDIClient, g_hSBar, g_hTBar;
HWND g_hMWindow;

BOOL LoadFile(HWND hEdit, LPSTR pszFName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;

    hFile = CreateFile(
        pszFName,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        0
    );

    if(hFile != INVALID_HANDLE_VALUE) {
        DWORD dwFSize;
        dwFSize = GetFileSize(hFile, NULL);
        if(dwFSize != 0xFFFFFFFF) {
            LPSTR pszFText;
            pszFText = LPSTR(GlobalAlloc(GPTR, dwFSize + 1));
            if(pszFText != NULL) {
                DWORD dwRead;
                if(ReadFile(hFile, pszFText, dwFSize, &dwRead, NULL)) {
                    pszFText[dwFSize] = 0; // Null terminator
                    if(SetWindowText(hEdit, pszFText)) {
                        bSuccess = TRUE;
                    }
                }
                GlobalFree(pszFText);
            }
        }
        CloseHandle(hFile);
    }
    return bSuccess;
}

BOOL SaveFile(HWND hEdit, LPSTR pszFileName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;

    hFile = CreateFile(
        pszFileName,
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        0
    );
    if(hFile != INVALID_HANDLE_VALUE) {
        DWORD dwTL;
        dwTL = GetWindowTextLength(hEdit);

        if(dwTL > 0) {
            LPSTR pszText;
            pszText = LPSTR(GlobalAlloc(GPTR, dwTL + 1));
            if(pszText != NULL) {
                if(GetWindowText(hEdit, pszText, dwTL + 1)) {
                    DWORD dwWritten;
                    if(WriteFile(hFile,pszText,dwTL,&dwWritten,NULL)) {
                        bSuccess = TRUE;
                    }
                }
                GlobalFree(pszText);
            }
        }
        CloseHandle(hFile);
    }
    return bSuccess;
}

BOOL GetFileName(HWND hwnd, LPSTR pszFName, BOOL bSave) {
    OPENFILENAME ofn;

    ZeroMemory(&ofn, sizeof(ofn));
    pszFName[0] = 0;

    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner   = hwnd;
    ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0";
    ofn.lpstrFile   = pszFName;
    ofn.nMaxFile    = MAX_PATH;
    ofn.lpstrDefExt = "txt";

    if(bSave) {
        ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
        OFN_OVERWRITEPROMPT;
        if(!GetSaveFileName(&ofn)) {
            return FALSE;
        }
    }
    else {
        ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
        if(!GetOpenFileName(&ofn)) {
            return FALSE;
        }
    }
    return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPI,LPSTR szCL, int iCS) {
    MSG  Msg;
    WNDCLASSEX WndClassEx;

    g_hInst = hInstance;

    WndClassEx.cbSize          = sizeof(WNDCLASSEX);
    WndClassEx.style           = CS_HREDRAW | CS_VREDRAW;
    WndClassEx.lpfnWndProc     = WndProc;
    WndClassEx.cbClsExtra      = 0;
    WndClassEx.cbWndExtra      = 0;
    WndClassEx.hInstance       = hInstance;
    WndClassEx.hIcon           = LoadIcon(hInstance, IMAGE);
    WndClassEx.hIconSm         = LoadIcon(hInstance, IMAGE);
    WndClassEx.hCursor         = LoadCursor(NULL, IDC_ARROW);
    WndClassEx.hbrBackground   = (HBRUSH)(COLOR_3DSHADOW+1);
    WndClassEx.lpszMenuName    = "MAIN";
    WndClassEx.lpszClassName   = g_szAppName;

    if(!RegisterClassEx(&WndClassEx)) {
        MessageBox(
            0,
            "Could Not Register Window",
            "Oh Oh...",
            MB_ICONEXCLAMATION | MB_OK
        );
        return -1;
    }

    WndClassEx.lpfnWndProc     = MDIChildWndProc;
    WndClassEx.lpszMenuName    = NULL;
    WndClassEx.lpszClassName   = g_szChild;
    WndClassEx.hbrBackground   = (HBRUSH)(COLOR_3DFACE+1);

    if(!RegisterClassEx(&WndClassEx)) {
        MessageBox(
            0,
            "Could Not Register Child Window",
            "Oh Oh...",
            MB_ICONEXCLAMATION | MB_OK
        );
        return -1;
    }

    g_hMWindow = CreateWindowEx(
        WS_EX_APPWINDOW, g_szAppName, "MDI File Editor",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
        CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
        0, 0, hInstance, NULL
    );

    if (g_hMWindow == NULL){
        MessageBox(
            0,
            "No Window",
            "Oh Oh...",
            MB_ICONEXCLAMATION | MB_OK
        );
        return -1;
    }

    ShowWindow(g_hMWindow, iCS);
    UpdateWindow(g_hMWindow);

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

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) {
    switch(msg) {
        case WM_CREATE: {
            CLIENTCREATESTRUCT ccs;
            int iSWidths[] = {200, 300, -1};
            TBADDBITMAP tbab;
            TBBUTTON tbb[9];

            ccs.hWindowMenu  = GetSubMenu(GetMenu(hwnd), 2);
            ccs.idFirstChild = ID_MDI_FIRSTCHILD;

            g_hMDIClient = CreateWindowEx(
                WS_EX_CLIENTEDGE, "mdiclient", NULL,
                WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                hwnd, (HMENU)ID_MDI_CLIENT, g_hInst, (LPVOID)&ccs
            );

            ShowWindow(g_hMDIClient, SW_SHOW);

            g_hSBar = CreateWindowEx(
                0, STATUSCLASSNAME, NULL,
                WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
                0, 0, 0, 0,
                hwnd, (HMENU)ID_STATUSBAR, g_hInst, NULL
            );
            SendMessage(g_hSBar, SB_SETPARTS, 3, (LPARAM)iSWidths);
            SendMessage(
                g_hSBar,
                SB_SETTEXT,
                2,
                (LPARAM) "Toolbar & Statusbar Example"
            );

            g_hTBar = CreateWindowEx(
                0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE,
                0, 0, 0, 0,
                hwnd, (HMENU) ID_TOOLBAR, g_hInst, NULL
            );

            SendMessage(
                g_hTBar,
                TB_BUTTONSTRUCTSIZE,
                (WPARAM) sizeof(TBBUTTON),
                0
            );

            tbab.hInst = HINST_COMMCTRL;
            tbab.nID = IDB_STD_SMALL_COLOR;
            SendMessage(g_hTBar, TB_ADDBITMAP, 0, (LPARAM)&tbab);

            ZeroMemory(tbb, sizeof(tbb));

            tbb[0].iBitmap = STD_FILENEW;
            tbb[0].fsState = TBSTATE_ENABLED;
            tbb[0].fsStyle = TBSTYLE_BUTTON;
            tbb[0].idCommand = CM_NOVO;

            tbb[1].iBitmap = STD_FILEOPEN;
            tbb[1].fsState = TBSTATE_ENABLED;
            tbb[1].fsStyle = TBSTYLE_BUTTON;
            tbb[1].idCommand = CM_FILE_OPEN;

            tbb[2].iBitmap   = STD_FILESAVE;
            tbb[2].fsStyle   = TBSTYLE_BUTTON;
            tbb[2].idCommand = CM_FILE_SAVE;

            tbb[3].fsStyle = TBSTYLE_SEP;

            tbb[4].iBitmap   = STD_CUT;
            tbb[4].fsStyle   = TBSTYLE_BUTTON;
            tbb[4].idCommand = CM_EDIT_CUT;

            tbb[5].iBitmap   = STD_COPY;
            tbb[5].fsStyle   = TBSTYLE_BUTTON;
            tbb[5].idCommand = CM_EDIT_COPY;

            tbb[6].iBitmap   = STD_PASTE;
            tbb[6].fsStyle   = TBSTYLE_BUTTON;
            tbb[6].idCommand = CM_EDIT_PASTE;

            tbb[7].fsStyle = TBSTYLE_SEP;

            tbb[8].iBitmap   = STD_UNDO;
            tbb[8].fsStyle   = TBSTYLE_BUTTON;
            tbb[8].idCommand = CM_EDIT_UNDO;

            SendMessage(g_hTBar, TB_ADDBUTTONS, 9, (LPARAM)&tbb);
            return 0;
        }
        case WM_COMMAND: {
            switch(LOWORD(wP)) {
                case CM_SAIR:
                    PostMessage(hwnd, WM_CLOSE, 0, 0);
                    break;
                case CM_NOVO: {
                    MDICREATESTRUCT mcs;
                    HWND hChild;

                    mcs.szTitle = "[Untitled]";
                    mcs.szClass = g_szChild;
                    mcs.hOwner  = g_hInst;
                    mcs.x = mcs.cx = CW_USEDEFAULT;
                    mcs.y = mcs.cy = CW_USEDEFAULT;
                    mcs.style = MDIS_ALLCHILDSTYLES;

                    hChild = (HWND)SendMessage(
                        g_hMDIClient,
                        WM_MDICREATE,
                        0,
                        (LPARAM)&mcs
                    );

                    if(!hChild) {
                        MessageBox(
                            hwnd,
                            "MDI Child creation failed.",
                            "Oh Oh...",
                            MB_ICONEXCLAMATION | MB_OK
                        );
                    }
                    break;
                }
                case CM_FILE_OPEN: {
                    MDICREATESTRUCT mcs;
                    HWND hChild;
                    char szFileName[MAX_PATH];

                    if(!GetFileName(hwnd, szFileName, FALSE))
                        break;

                    mcs.szTitle = szFileName;
                    mcs.szClass = g_szChild;
                    mcs.hOwner  = g_hInst;
                    mcs.x = mcs.cx = CW_USEDEFAULT;
                    mcs.y = mcs.cy = CW_USEDEFAULT;
                    mcs.style = MDIS_ALLCHILDSTYLES;

                    hChild = (HWND)SendMessage(
                        g_hMDIClient,
                        WM_MDICREATE,
                        0,
                        (LPARAM)&mcs
                    );

                    if(!hChild) {
                        MessageBox(
                            hwnd,
                            "MDI Child creation failed.",
                            "Oh Oh...",
                            MB_ICONEXCLAMATION | MB_OK
                        );
                    }
                    break;
                }
                case CM_WINDOW_TILEHORZ:
                    PostMessage(g_hMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
                    break;
                case CM_WINDOW_TILEVERT:
                    PostMessage(g_hMDIClient, WM_MDITILE, MDITILE_VERTICAL, 0);
                    break;
                case CM_WINDOW_CASCADE:
                    PostMessage(g_hMDIClient, WM_MDICASCADE, 0, 0);
                    break;
                case CM_WINDOW_ARRANGE:
                    PostMessage(g_hMDIClient, WM_MDIICONARRANGE, 0, 0);
                    break;
                default: {
                    if(LOWORD(wP) >= ID_MDI_FIRSTCHILD) {
                        DefFrameProc(hwnd, g_hMDIClient, msg, wP, lP);
                    }
                    else {
                        HWND hChild;
                        hChild = (HWND)SendMessage(
                            g_hMDIClient,
                            WM_MDIGETACTIVE,
                            0,
                            0
                        );
                        if(hChild) {
                            SendMessage(hChild, WM_COMMAND, wP, lP);
                        }
                    }
                }
            }
            break;
        }
        case WM_SIZE: {
            RECT rectClient, rectStatus, rectTool;
            UINT uToolHeight, uStatusHeight, uClientAlreaHeight;

            SendMessage(g_hTBar, TB_AUTOSIZE, 0, 0);
            SendMessage(g_hSBar, WM_SIZE, 0, 0);

            GetClientRect(hwnd, &rectClient);
            GetWindowRect(g_hSBar, &rectStatus);
            GetWindowRect(g_hTBar, &rectTool);

            uToolHeight = rectTool.bottom - rectTool.top;
            uStatusHeight = rectStatus.bottom - rectStatus.top;
            uClientAlreaHeight = rectClient.bottom;

            MoveWindow(
                g_hMDIClient,
                0,
                uToolHeight,
                rectClient.right,
                uClientAlreaHeight - uStatusHeight - uToolHeight,
                TRUE
            );
            break;
        }
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefFrameProc(hwnd, g_hMDIClient, msg, wP, lP);
    }
    return 0;
}

LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) {
    switch(msg) {
        case WM_CREATE: {
            char szFileName[MAX_PATH];
            HWND hEdit;

            hEdit = CreateWindowEx(
                WS_EX_CLIENTEDGE, "EDIT", " ",
                WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|ES_MULTILINE|ES_WANTRETURN,
                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                hwnd, (HMENU) IDC_CHILD_EDIT, g_hInst, NULL
            );

            SendMessage(
                hEdit,
                WM_SETFONT,
                (WPARAM) GetStockObject(DEFAULT_GUI_FONT),
                MAKELPARAM(TRUE, 0)
            );

            GetWindowText(hwnd, szFileName, MAX_PATH);
            if(*szFileName != '[') {
                if(!LoadFile(hEdit, szFileName)) {
                    MessageBox(
                        hwnd,
                        "Couldn't Load File.",
                        "Error.",
                        MB_OK | MB_ICONEXCLAMATION
                    );
                    return -1;
                }
            }
            break;
        }
        case WM_SIZE:
            if(wP != SIZE_MINIMIZED)
                MoveWindow(
                    GetDlgItem(hwnd,IDC_CHILD_EDIT),
                    0,
                    0,
                    LOWORD(lP),
                    HIWORD(lP),
                    TRUE
                );
            break;
        case WM_MDIACTIVATE: {
            HMENU hMenu, hFileMenu;
            BOOL EnableFlag;
            char szFileName[MAX_PATH];

            hMenu = GetMenu(g_hMWindow);
            if(hwnd == (HWND)lP) {
                EnableFlag = TRUE;
            }
            else {
                EnableFlag = FALSE;
            }
            EnableMenuItem(
                hMenu,
                1,
                MF_BYPOSITION | (EnableFlag ? MF_ENABLED : MF_GRAYED)
            );
            EnableMenuItem(
                hMenu,
                2,
                MF_BYPOSITION | (EnableFlag ? MF_ENABLED : MF_GRAYED)
            );

            hFileMenu = GetSubMenu(hMenu, 0);
            EnableMenuItem(
                hFileMenu,
                CM_FILE_SAVE,
                MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED)
            );
            EnableMenuItem(
                hFileMenu,
                CM_FILE_SAVEAS,
                MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED)
            );

            DrawMenuBar(g_hMWindow);

            SendMessage(g_hTBar, TB_ENABLEBUTTON, CM_FILE_SAVE, MAKELONG(EnableFlag, 0));
            SendMessage(g_hTBar, TB_ENABLEBUTTON, CM_EDIT_UNDO, MAKELONG(EnableFlag, 0));
            SendMessage(g_hTBar, TB_ENABLEBUTTON, CM_EDIT_CUT, MAKELONG(EnableFlag, 0));
            SendMessage(g_hTBar, TB_ENABLEBUTTON, CM_EDIT_COPY, MAKELONG(EnableFlag, 0));
            SendMessage(g_hTBar, TB_ENABLEBUTTON, CM_EDIT_PASTE, MAKELONG(EnableFlag, 0));

            GetWindowText(hwnd, szFileName, MAX_PATH);
            SendMessage(g_hSBar, SB_SETTEXT, 0, (LPARAM)(EnableFlag ? szFileName : ""));
            break;
        }
        case WM_SETFOCUS:
            SetFocus(GetDlgItem(hwnd, IDC_CHILD_EDIT));
            break;
        case WM_COMMAND: {
            switch(LOWORD(wP)) {
                case CM_FILE_SAVE: {
                    char szFName[MAX_PATH];

                    GetWindowText(hwnd, szFName, MAX_PATH);

                    if(*szFName != '[') {
                        if(!SaveFile(GetDlgItem(hwnd, IDC_CHILD_EDIT), szFName)) {
                            MessageBox(
                                hwnd,
                                "Couldn't Save File.",
                                "Error.",
                                MB_OK | MB_ICONEXCLAMATION
                            );
                            return 0;
                        }
                    }
                    else {
                        PostMessage(hwnd, WM_COMMAND,MAKEWPARAM(CM_FILE_SAVEAS, 0), 0);
                    }
                    return 0;
                }
                case CM_FILE_SAVEAS: {
                    char szFileName[MAX_PATH];

                    if(GetFileName(hwnd, szFileName, TRUE)) {
                        if(!SaveFile(GetDlgItem(hwnd, IDC_CHILD_EDIT), szFileName)) {
                            MessageBox(
                                hwnd,
                                "Couldn't Save File.",
                                "Error.",
                                MB_OK | MB_ICONEXCLAMATION
                            );
                            return 0;
                        }
                        else {
                            SetWindowText(hwnd, szFileName);
                        }
                    }
                    return 0;
                }
                case CM_EDIT_UNDO:
                    SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, EM_UNDO, 0, 0);
                    break;
                case CM_EDIT_CUT:
                    SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_CUT, 0, 0);
                    break;
                case CM_EDIT_COPY:
                    SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_COPY, 0, 0);
                    break;
                case CM_EDIT_PASTE:
                    SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_PASTE, 0, 0);
                    break;
            }
            return 0;
        }
    }
    return DefMDIChildProc(hwnd, msg, wP, lP);
}


/**** resource.h ****/

#define CM_WINDOW_TILEVERT  9080
#define CM_WINDOW_TILEHORZ  9082
#define CM_WINDOW_ARRANGE   9081
#define CM_WINDOW_TILE      9080
#define CM_WINDOW_CASCADE   9076
#define CM_EDIT_PASTE   9079
#define CM_EDIT_COPY    9078
#define CM_EDIT_CUT     9077
#define CM_EDIT_REDO    9076
#define CM_EDIT_UNDO    9075
#define CM_FILE_SAVEAS  9074
#define CM_FILE_SAVE    9073
#define CM_FILE_OPEN    9072
#define CM_HELP_ABOUT   9072
#define CM_SAIR         9071
#define CM_NOVO         9070

#define ID_STATUSBAR       4997
#define ID_TOOLBAR         4998

#define ID_MDI_CLIENT      4999
#define ID_MDI_FIRSTCHILD  50000

#define IDC_CHILD_EDIT     2000

#define IMAGE              " "


/**** resource.rc ****/

#include "resource.h"
#include "afxres.h"

IMAGE ICON "icon1.ico"

MAIN MENU {
    POPUP "&Arquivo" {
        MENUITEM "&New",        CM_NOVO
        MENUITEM "&Open...",    CM_FILE_OPEN
        MENUITEM "&Save",       CM_FILE_SAVE, GRAYED
        MENUITEM "Save &As...", CM_FILE_SAVEAS, GRAYED
        MENUITEM SEPARATOR
        MENUITEM "E&xit",       CM_SAIR
    }

    POPUP "&Editar", GRAYED {
        MENUITEM "&Undo\tCtrl+Z",  CM_EDIT_UNDO
        MENUITEM SEPARATOR
        MENUITEM "Cu&t\tCtrl+X",   CM_EDIT_CUT
        MENUITEM "&Copy\tCtrl+C",  CM_EDIT_COPY
        MENUITEM "&Paste\tCtrl+V", CM_EDIT_PASTE
    }

    POPUP "&Janela", GRAYED {
        MENUITEM "&Cascade",         CM_WINDOW_CASCADE
        MENUITEM "Tile &Horizontal", CM_WINDOW_TILEHORZ
        MENUITEM "Tile &Vertical",   CM_WINDOW_TILEVERT
        MENUITEM "Arrange &Icons",   CM_WINDOW_ARRANGE
    }
}

Comentários