Chinaunix首页 | 论坛 | 博客
  • 博客访问: 514860
  • 博文数量: 158
  • 博客积分: 4015
  • 博客等级: 上校
  • 技术积分: 1711
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-27 14:00
文章分类

全部博文(158)

文章存档

2010年(71)

2009年(87)

我的朋友

分类: C/C++

2010-01-21 19:34:02

上次我们仅仅实现了打开文件的功能, 今天我们要实现“文件”菜单中大部分的功能, 有些如“页面设置”,“打印"以后再说。

我们准备实现这些功能, 并且添加快捷键接口。我们的这个小记事本只支持ANSI字符集, UNICODE以后再说。
PodPad.c


#include <windows.h>
#include <commdlg.h>
#include "resource.h"
#define UNTITLED "untitled.txt"

    static TCHAR szAppName[] = TEXT("我的记事本");
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
                 HINSTANCE hPrevInstance,
                 PSTR szCmdLine,
                 int iCmdShow) {
    HACCEL hAccel;
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;
    
    if(!RegisterClass(&wndclass)) {
        MessageBox(NULL, TEXT("Register failure..."),
            szAppName, MB_ICONERROR);
        return 0;
    }
    
    hwnd = CreateWindow(szAppName,
        szAppName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);
    
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    // 增加快捷键接口

    hAccel = LoadAccelerators(hInstance, szAppName);
    
    while(GetMessage(&msg, NULL, 0, 0)) {
        if(!TranslateAccelerator(hwnd, hAccel, &msg)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        }
    }
    return msg.wParam;
}

// 这个函数用于当每次新的操作而需要保存文件

// 时弹出的对话框。

short AskAboutSave(HWND hwnd, TCHAR* szFileName) {
    TCHAR buffer[64 + MAX_PATH];
    int iReturn;
    // 当还没有文件名的时候,我们假定文件名就是untitled.txt

    wsprintf(buffer, "您没有保存%s文件,想要保存么?",
        szFileName[0] ? szFileName : UNTITLED);
    // yes to save file, no to not save file, cancel to cancel the save operation.

    iReturn = MessageBox(hwnd, buffer, szAppName, MB_YESNOCANCEL | MB_ICONQUESTION);
    if(iReturn == IDYES)
        SendMessage(hwnd, WM_COMMAND, IDM_FILE_SAVE, 0);
    return iReturn;
}

void DoCaption(HWND hwnd, TCHAR* szCaptionName) {
    TCHAR buffer[64 + MAX_PATH];
    wsprintf(buffer, "%s - %s", szAppName,
        szCaptionName[0] ? szCaptionName : UNTITLED);
    SetWindowText(hwnd, buffer);
}

void OkMessage(HWND hwnd, TCHAR* message, TCHAR* szFileName) {
    TCHAR buffer[64 + MAX_PATH];
    wsprintf(buffer, message, szFileName[0] ? szFileName : UNTITLED);
    MessageBox(NULL, buffer,
        szAppName, MB_OK | MB_ICONEXCLAMATION);
}

LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam) {
    static TCHAR fullPath[MAX_PATH], fileName[MAX_PATH];
    TCHAR* pText;
    static HWND hwndEdit;
    static BOOL bNeedSave = FALSE;
    
    switch(message) {
    case WM_CREATE:
        hwndEdit = CreateWindow(TEXT("edit"),
            NULL,
            WS_CHILD | WS_VISIBLE | ES_LEFT
            | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE |
            ES_AUTOVSCROLL,
            0, 0, 0, 0,
            hwnd,
            (HMENU)1,
            (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
            NULL);
        // 这一步是必须的,初始化OPENFILENAME

        popFileInit(hwnd);
        return 0;
    case WM_SIZE:
        MoveWindow(hwndEdit, 0, 0, LOWORD(lParam),
            HIWORD(lParam), TRUE);
        return 0;
        
    case WM_SETFOCUS:
        SetFocus(hwndEdit);
        return 0;
        
    case WM_COMMAND:
        // 学习一下它的处理方法

        if(lParam && LOWORD(wParam) == 1) {
            switch(HIWORD(wParam)) {
            case EN_UPDATE:
                bNeedSave = TRUE;
                return 0;
            case EN_ERRSPACE:
            case EN_MAXTEXT:
                MessageBox(NULL, TEXT("记事本已经超出了范围"),
                    szAppName, MB_OK | MB_ICONSTOP);
                return 0;
            }
            break;
        }
        switch(LOWORD(wParam)) {
        case IDM_FILE_NEW:
            // 当使用者按下了YES,文件将保存,下面的条件将为FALSE,执行NEW操作

            // 当按下了NO,下面的条件将会为FALSE,执行NEW操作

            // 当按下的CANCEL,下面的条件将会为真,不执行NEW操作

            if(bNeedSave && IDCANCEL == AskAboutSave(hwnd, fileName))
            return 0;
            SetWindowText(hwndEdit, "\0");
            fullPath[0] = '\0';
            fileName[0] = '\0';
            DoCaption(hwnd, fileName);
            bNeedSave = FALSE;
            return 0;

        case IDM_FILE_OPEN:
            if(bNeedSave && IDCANCEL == AskAboutSave(hwnd, fileName))
                return 0;
            // 我们不处理按下了CANCEL的情况

            if(openDlg(hwnd, fullPath, fileName))
                if(!openReadFile(hwndEdit, fileName)) {
                    OkMessage(hwnd, "无法打开文件%s!", fileName);
                    fullPath[0] = '\0';
             fileName[0] = '\0';
                }
                DoCaption(hwnd, fileName);
                bNeedSave = FALSE;
                return 0;

        case IDM_FILE_SAVE:
            // 以前保存过,如果是第一次保存,

            // 下面的条件为FALSE,转到下一个CASE

            if(fileName[0]) {
                if(saveWriteFile(hwndEdit, fileName)) {
                    bNeedSave = FALSE;
                    return 1;
                } else {
                    OkMessage(hwnd, "无法保存文件%s", fileName);
                    return 0;
                }
            }

        case IDM_FILE_SAVE_AS:
            if(saveDlg(hwnd, fullPath, fileName)) {
                if(saveWriteFile(hwndEdit, fileName)) {
                    bNeedSave = FALSE;
                    DoCaption(hwnd, fileName);
                    return 1;
                } else {
                    OkMessage(hwnd, "无法保存文件%s", fileName);
                    return 0;
                }
            }
            return 0;

        case IDM_FILE_EXIT:
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;
        }
        break;

        case WM_CLOSE:
            if(bNeedSave && IDCANCEL == AskAboutSave(hwnd, fileName))
                return 0;
            DestroyWindow(hwnd);
            return 0;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

PopFile.c

#include <windows.h>
#include <commdlg.h>

static OPENFILENAME ofn;
void popFileInit();
BOOL openDlg(HWND, TCHAR*, TCHAR*);
BOOL saveDlg(HWND, TCHAR*, TCHAR*);
BOOL openReadFile(HWND, TCHAR*);
BOOL saveWriteFile(HWND, TCHAR*);

void popFileInit(HWND hwnd) {
    static TCHAR szFilter[] = TEXT("Text Files(*.txt)\0*.txt\0") \
        TEXT("All Files(*.*)\0*.*\0\0");
    // 确定结构的大小

    ofn.lStructSize = sizeof(OPENFILENAME);
    // 指定它的父窗口

    ofn.hwndOwner = hwnd;
    // 一般为NULL,表示我们使用的是通用对话框

    // ,当然我们也可以自定义对话框,此时hInstance指示

    // 资源的handle。

    ofn.hInstance = NULL;
    // 指示打开或者保存文件时的过滤器,比如说:

    // static TCHAR szFilter[] = TEXT("Text Files(*.txt)\0*.txt\0") \

    //    TEXT("All Files(*.*)\0*.*\0\0");

    // 结构是这样的:描述\0过滤\0, 最后一项必须是两个\0,

    // 详情请参考MSDN。

    ofn.lpstrFilter = szFilter;
    // 一般为NULL

    ofn.lpstrCustomFilter = NULL;
    // 一般为0

    ofn.nMaxCustFilter = 0;
    // 指示默认过滤器为第几项

    ofn.nFilterIndex = 0;
    // 用于保存文件的完事路径及文件名

    ofn.lpstrFile = NULL;
    // 指示上面结构的大小

    ofn.nMaxFile = MAX_PATH;
    // 用于保存文件名,不包括路径

    ofn.lpstrFileTitle = NULL;
    // 指示上面结构的大小

    ofn.nMaxFileTitle = MAX_PATH;
    // 指示打开对话框的第一路径,

    // 我发现为NULL时,初始化路径总是

    // “我的文档”。

    ofn.lpstrInitialDir = NULL;
    // 指示对话框的caption, 我们一般为NULL,

    // 让系统指示, 当然也可以自己设置。

    ofn.lpstrTitle = NULL;
    // 这个东西在打开保存等有点不同,下面是为了打开而设置的

    // 我们以后会看到保存时此项的设置。

    ofn.Flags = 0;
    // 为0就可以了

    ofn.nFileOffset = 0;
    // 为0就可以了

    ofn.nFileExtension = 0;
    // 如果你保存的时候忘记加.txt时,

    // 它会自动给你加上。

    ofn.lpstrDefExt = TEXT("txt");
    // 为0就可以了

    ofn.lCustData = 0;
    // 为NULL就可以了

    ofn.lpfnHook = NULL;
    // 如果想定制对话框, 下面的就不能为NULL了

    // 但是我们一般为NULL。

    ofn.lpTemplateName = NULL;
}
BOOL openDlg(HWND hwnd, TCHAR* fullPath, TCHAR* fileName) {
    ofn.lpstrFile = fullPath;
    ofn.lpstrFileTitle = fileName;
    ofn.Flags = OFN_HIDEREADONLY;
    return GetOpenFileName(&ofn);
}

BOOL saveDlg(HWND hwnd, TCHAR* fullPath, TCHAR* fileName) {
    ofn.lpstrFile = fullPath;
    ofn.lpstrFileTitle = fileName;
    ofn.Flags = OFN_OVERWRITEPROMPT;
    return GetSaveFileName(&ofn);
}
BOOL openReadFile(HWND hwnd, TCHAR* fullPath) {
    HANDLE hFile;
    PBYTE pBuffer;
    int iFileLength;
    DWORD dwByteRead;
    
    if(INVALID_HANDLE_VALUE == (hFile = CreateFile(
        fullPath, GENERIC_READ, FILE_SHARE_READ, NULL,
        OPEN_EXISTING, 0, NULL)))
        return FALSE;
    
    iFileLength = GetFileSize(hFile, NULL);
    pBuffer = malloc(iFileLength + 2);
    ReadFile(hFile, pBuffer, iFileLength, &dwByteRead, NULL);
    CloseHandle(hFile);
    pBuffer[iFileLength] = pBuffer[iFileLength + 1] = '\0';
    SetWindowText(hwnd, pBuffer);
    free(pBuffer);
    return TRUE;
}

BOOL saveWriteFile(HWND hwnd, TCHAR* fullPath) {
    DWORD dwBytesWritten;
    HANDLE hFile;
    int size;
    PBYTE pBuffer;

    if(INVALID_HANDLE_VALUE == (hFile = CreateFile(fullPath,
        GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)))
        return FALSE;
    size = GetWindowTextLength(hwnd);
    pBuffer = (PSTR)malloc(size + 1);
    GetWindowText(hwnd, pBuffer, size + 1);
    WriteFile(hFile, pBuffer, size, &dwBytesWritten, NULL);
    if(dwBytesWritten != size) {
        free(pBuffer);
        CloseHandle(hFile);
        return FALSE;
    }
    free(pBuffer);
    CloseHandle(hFile);
    return TRUE;
}


阅读(8003) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~