win32sdk学习 richedit实现的一个简单记事本

2023-05-16

记录的源文件,篇幅有点长

工具栏资源图片

bmp格式

notepad.h文件

// NOTEPAD_H_INCLUDED
/*
** Copyright (C)
    name:notepad
    author:suju
    日期:2012-10-04
*/
#ifndef NOTEPAD_H_INCLUDED
#define NOTEPAD_H_INCLUDED
/*定义工具栏图标坐标数据*/
#define BNEW                            2
#define BOPEN                           4
#define BSAVE                           0
#define BREVO                           1
#define BRECOVERY                       3
#define BSHEAR                          7
#define BCOPY                           8
#define BPASTE                          9
#define BFIND                           5
#define BREPLACE                        10
#define BCENTER                         11
#define BLEFT                           12
#define BRIGHT                          13
#define BBOLD                           14
#define BITALIC                         15
#define BUNDERLINE                      16
#define BFONTSTYLE                      6
//工具栏样式图标
#define BOLD    0
#define ITALIC  1
#define UNDERLINE   2
//文本编码
#define TXT_UNICODE   1
#define TXT_ASCII     0
//
#define IF_FALSE(bool,sta1,sta2) bool!=0?sta1:sta2
#endif
/*include*/
#include <windows.h>
#include <stdio.h>
#include <richedit.h>
#include <commctrl.h>
#include "resource.h"
/*声明函数*/
/******start function********/
void setStatus();                   /*设置状态栏*/
long getLength();                   /*获取文本长度*/
void textChange();                  /*文本改变处理函数*/
void findText();                    /*查找*/
void savetofile();                  /*保存文件*/
void checkFormat();                 //工具栏图标匹配选中文本格式
void close(HWND hwnd);              /*关闭退出程序*/
void newfile(HWND hwnd);            /*新建文件*/
void readfile(HWND hwnd);           /*读取文件*/
void openfile(HWND hwnd);           /*打开文件*/
void menuChange(HWND hwnd);         /*菜单和工具栏按钮初始化*/
void moveStatus(HWND hwnd);         /*移动状态栏*/
void setFont(HWND hwndrich);        /*设置字体样式*/
void initToolbar(HWND hwnd);        /*初始化工具栏*/
void createStatus(HWND hwnd);       /*创建状态栏*/
void setAlignment(int style);       //设置样式(加粗,斜体,下划线)

void setWindowSize(HWND hwnd);                    /*设置窗体大小*/
void quickSetFormat(int STYLE);                   //工具栏设置样式
int savefiledialog(HWND hwndrich);                /*保存文件处理函数*/
void clickfile(HWND hwnd,LPSTR name);             //桌面拖放打开文件
void savefile(HWND hwnd,int savemodel);           /*保存文件*/
HWND getFindDialog(HWND hwnd,int model);          /*打开/替换对话框*/
void notifyChange(HWND hwnd,LPARAM lParam);       /*notify消息处理*/

TCHAR* substring(TCHAR* ch,int pos,int length);                       //字符串截取
void selText(TCHAR* lpchar,int index,TCHAR* defext);                  /*文件后缀判断函数*/

void getCHARFORMAT(HWND hwndrich,CHARFORMAT* cformat,CHOOSEFONT* cf);               /*获取格式化结构变量*/

void initOpn(OPENFILENAME* opn,TCHAR* filename,LPCSTR Title,DWORD filterIndex);      /*初始化opn结构*/
DWORD CALLBACK StreamCallback(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG *pcb);      /*输入流回调函数*/
void initEidtStream(EDITSTREAM* stream,LPCSTR type,EDITSTREAMCALLBACK callback);     /*初始化读写流结构*/
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam);    /*主程序回调函数*/
DWORD CALLBACK SaveStreamCallback(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG *pcb);  /*输出流回调函数*/
BOOL CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);   /*对话框回调函数*/
/******end funciton********/
/*声明全局变量*/
/*******Statement Parameters*********/
HINSTANCE hInst;                            /*应用程序句柄*/
HWND hwndrich;                              /*richedit句柄*/
HWND hwndfind;                              /*查找对话框句柄*/
HWND hwndStatus;                            /*状态栏句柄*/
HWND hWndToolBar;                           /*工具栏句柄*/
UINT uFindReplaceMsg;  //FINDMSGSTRING消息  自定义查找消息
/*定义文件后缀*/
TCHAR filtername[MAX_PATH]=TEXT("rtf\0*.rtf\0txt\0*.txt\0all\0*.*\0");
TCHAR filename[MAX_PATH]="";                 /*初始文件名*/
TCHAR defext[MAX_PATH];                      /*初始文件后缀*/
TCHAR szFindWhat[80]="";                     /*初始查找文本*/
TCHAR szReplaceWhat[80]="";                  /*初始替换文本*/
FINDREPLACE fr;                             /*替换/查找对话框 结构变量*/
const int FIND=0;                           /*查找FIND常量*/
const int REPLACE=1;                        /*替换REPLACE常量*/
const int SAVE=0;                           /*保存SAVE常量*/
const int SAVEAS=1;                         /*另存为SAVES常量*/
const int F_OPEN=0;                         /*打开文件F_OPEN常量*/
const int F_CHANGE=1;                       /*改变文件内容F_CHANGE常量*/
TCHAR defaultname[]="未命名";                /*默认标题名*/
TCHAR SaveFileName[MAX_PATH]="";             /*默认保存文件名*/
TCHAR staformat[MAX_PATH]=TEXT("行%d 列%d");                   /*状态栏格式化文本*/
TCHAR sizeformat[MAX_PATH]=TEXT("字数 %ld");                   /*状态栏格式化文本*/
TCHAR status_line[MAX_PATH]="";                                /*状态栏行列数*/
TCHAR status_size[MAX_PATH]="";                                /*状态栏文本总长度*/
TCHAR szBuf[MAX_PATH];                                         /*提示消息字符缓冲*/
int isSave=TRUE;                                              /*修改状态*/
OPENFILENAME opfn;                                            /*OPENFILENAME打开文件结构*/
long size=0;                                                  /*文件大小*/
DWORD filterIndex=2;                                          //默认文件后缀索引
TCHAR szAppName[]=TEXT("DLG_MAIN");                            //窗口类名称
FILE* file=NULL;                                              //文件指针
CHARFORMAT cformat;                                           //格式化结构
PARAFORMAT paraformat;                                        //段落格式结构
int txtcode=TXT_ASCII;                                        //默认文件编码
int textmode;
/********Statement Parameters****************/




resource.h资源头文件

#ifndef IDC_STATIC
#define IDC_STATIC (-1)


#define DLG_MAIN                                101
#define IDR_MENU1                               102
#define IDD_DIALOG1                             103
#define ID_ACCE                                 106
#define IDI_ICON1                               107
#define IDB_BITMAP1                             108
#define IDC_RICHEDIT1                           1000
#define IDM_OPEN                                40000
#define IDM_EXIT                                40001
#define IDM_ABOUT                               40002
#define IDM_SAVE                                40003
#define IDM_STYLE                               40004
#define IDM_FIND                                40005
#define IDM_REPLACE                             40006
#define IDM_SAVEAS                              40007
#define IDM_NEW                                 40008
#define IDM_REVO                                40009
#define IDM_SHEAR                               40010
#define IDM_COPY                                40011
#define IDM_PASTE                               40012
#define IDM_RECOVERY                            40013
#define IDM_TAB                                 40014
#define IDR_TOOLBAR1                            40015
#define IDM_BOLD                                40016
#define IDM_ITALIC                              40017
#define IDM_UNDERLINE                           40018
#define IDM_CENTER                              40019
#define IDM_LEFT                                40020
#define IDM_RIGHT                               40021
#endif

resource.rc

//include 编译h文件
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
//
// Bitmap resources图片
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_BITMAP1        BITMAP         ".\\notepad.bmp"


LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDR_TOOLBAR1       BITMAP         "bitmap.bmp"



//
// Menu resources菜单
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDR_MENU1 MENU
{
    POPUP "文件(&F)"
    {
        MENUITEM "新建(&N) Ctrl+N", IDM_NEW
        MENUITEM "打开(&O) Ctrl+O", IDM_OPEN
        MENUITEM "保存(&S) Ctrl+S", IDM_SAVE
        MENUITEM "另存为(&A)", IDM_SAVEAS
        MENUITEM SEPARATOR
        MENUITEM "退出(&E)", IDM_EXIT
    }
    POPUP "编辑(&E)"
    {
        MENUITEM "查找(&F) Ctrl+F", IDM_FIND
        MENUITEM "替换(&R) Ctrl+H", IDM_REPLACE
        MENUITEM SEPARATOR
        MENUITEM "撤销(&U) Ctrl+Z", IDM_REVO
        MENUITEM "恢复(&Y)Ctrl+Y", IDM_RECOVERY
        MENUITEM SEPARATOR
        MENUITEM "剪切(&T) Ctrl+x", IDM_SHEAR
        MENUITEM "复制(&C) Ctrl+C", IDM_COPY
        MENUITEM "粘贴(&P) Ctrl+V", IDM_PASTE
    }
    POPUP "选项(&O)"
    {
        MENUITEM "样式(&S)", IDM_STYLE
    }
    POPUP "帮助(&H)"
    {
        MENUITEM "关于(&A)", IDM_ABOUT
    }
}



//
// Dialog resources主对话框窗口
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOGEX 6, 5, 265, 285
STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_GROUP | WS_MAXIMIZEBOX | WS_POPUP | WS_THICKFRAME | WS_SYSMENU | WS_TABSTOP
EXSTYLE WS_EX_WINDOWEDGE
CAPTION "Notepad"
MENU IDR_MENU1
CLASS "DLG_MAIN"
FONT 12, "Tahoma", 400, 0, 0
{
    //RICHEDIT_CLASS 2.0版本class name
    //L"RichEdit50W" CLASS 4.1版本class name
    CONTROL         "", IDC_RICHEDIT1,RICHEDIT_CLASS, WS_VSCROLL | NOT WS_BORDER | NOT WS_TABSTOP | ES_MULTILINE | ES_NOHIDESEL | ES_WANTRETURN, 0, 33, 265, 230, WS_EX_CLIENTEDGE
}


//关于对话框
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG1 DIALOG 0, 0, 174, 105
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU
CAPTION "关于"
FONT 8, "Ms Shell Dlg 2"
{
    DEFPUSHBUTTON   "确  定", IDOK, 136, 84, 25, 14
    LTEXT           "Notepad v1.0 demo\n\n制作:suju\n\nEmail:2567861663@qq.com", IDC_STATIC, 73, 26, 90, 40, SS_LEFT
    CONTROL         IDB_BITMAP1, IDC_STATIC, WC_STATIC, WS_GROUP | SS_BITMAP | SS_CENTERIMAGE | SS_NOTIFY | 0x00000840, 0, 19, 66, 56, WS_EX_TRANSPARENT
}



//
// String Table resources工具栏提示字符串资源
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
STRINGTABLE
{
    IDM_OPEN                      "打开"
    IDM_SAVE                      "保存"
    IDM_STYLE                     "样式"
    IDM_FIND                      "查找"
    IDM_REPLACE                   "替换"
    IDM_NEW                       "新建"
    IDM_REVO                      "撤销"
    IDM_SHEAR                     "剪切"
    IDM_COPY                      "复制"
    IDM_RECOVERY                  "恢复"
    IDM_PASTE                     "粘贴"
    IDM_BOLD                      "粗体"
    IDM_ITALIC                    "斜体"
    IDM_UNDERLINE                 "下划线"
    IDM_CENTER                    "居中显示"
    IDM_LEFT                      "靠左显示"
    IDM_RIGHT                     "靠右显示"
}



//
// Accelerator resources加速键
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
ID_ACCE ACCELERATORS
{
    "F",            IDM_FIND, VIRTKEY, CONTROL
    "O",            IDM_OPEN, VIRTKEY, CONTROL
    "H",            IDM_REPLACE, VIRTKEY, CONTROL
    "S",            IDM_SAVE, VIRTKEY, CONTROL
    VK_TAB,        IDM_TAB, VIRTKEY
}



//
// Icon resources图标资源
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDI_ICON1          ICON           ".\\notepad.ico"


notepad.c文件

//#define WIN32_LEAN_AND_MEAN

#include "notepad.h"
#define TBSTYLE_FLAT 2048       //工具栏样式

/*主启动函数*/

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst = hInstance;                  //保存实例句柄
    LoadLibrary("RichEd20.dll");       //载入richedit动态库,这个控件是以单独dll形式保存的2.0版本
    //LoadLibrary("msftedit.dll");       //载入richedit动态库,这个控件是4.1的
    MSG msg;                            //队列消息变量
    HWND hwnd;                          //窗口句柄
    HICON icon;                         //图标
    HACCEL haccel;                      //加速键
    //自定义查找对话框消息
    uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);
    //载入窗口图标
    icon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
    //--start声明,注册一个窗口类,类名和默认对话框模板类型一样。
    WNDCLASSEX wndclass ;                                       //窗口类结构
    ZeroMemory(&wndclass,sizeof(wndclass));                     //初始化结构
    wndclass.cbSize = sizeof (WNDCLASSEX);                      //cbSize大小,window检测窗口类型的参数。
    wndclass.style= CS_HREDRAW | CS_VREDRAW;                    //样式
    wndclass.lpfnWndProc= WndProc;                              //指定窗口消息处理函数
    wndclass.cbClsExtra= 0 ;                                    //窗口类预留字节空间,这里为0字节
    wndclass.cbWndExtra = DLGWINDOWEXTRA ;                      //窗口结构预留字节
    wndclass.hInstance= hInstance ;                             //窗口类模块句柄
    wndclass.hIcon =icon;                                       //定义图标
    wndclass.hCursor= LoadCursor (NULL, IDC_ARROW) ;            //鼠标光标
    wndclass.hbrBackground= (HBRUSH) (COLOR_BTNFACE + 1) ;      //设置背景色
    wndclass.lpszMenuName= NULL;                                //窗口应用程序菜单 NULL
    wndclass.lpszClassName= szAppName ;                         //窗口类别名称,对话框窗口和模板类名称相同
    //注册窗口
    if(!RegisterClassEx(&wndclass))
    {
        //注册失败处理
        MessageBox(NULL,TEXT("窗口注册失败!"),TEXT("Notepad"),MB_ICONERROR);
        return 0;
    }
    /*--end 注册窗口*/

    //基于对话框模板方式创建一个非模态对话框窗口
    //MAKEINTRESOURCE宏用于把数字资源ID转为字符串指针。
    hwnd=CreateDialog(hInstance,MAKEINTRESOURCE(DLG_MAIN),NULL,0);
    /*初始化窗口标题栏,并显示窗口*/
    SetWindowText(hwnd,strcat(defaultname,"-Notepad"));
    ShowWindow(hwnd,nShowCmd);
    UpdateWindow(hwnd);

    /*设置richedit控件响应消息*/
    hwndrich=GetDlgItem(hwnd,IDC_RICHEDIT1);
    SendMessage(hwndrich,EM_SETEVENTMASK,0,ENM_SELCHANGE|ENM_MOUSEEVENTS|ENM_CHANGE|ENM_KEYEVENTS|ENM_SCROLL|ENM_DROPFILES);
    SendMessage(hwndrich,EM_EXLIMITTEXT,0,-1);
    //载入加速键资源表,保存加速键表句柄
    haccel=LoadAccelerators(hInstance,MAKEINTRESOURCE(ID_ACCE));
    //创建状态栏,并重置窗口位置
    createStatus(hwnd);
    setWindowSize(hwnd);
    /*命令行和拖放文件打开判断*/
    if (strcmp(lpCmdLine,TEXT(""))!=0){
       clickfile(hwnd,lpCmdLine);
    }
    //*主消息循环*//
    while (GetMessage(&msg,NULL,0,0))
    {
        //加速键捕获处理
        if (!TranslateAccelerator(hwnd,haccel,&msg))
        {
            //非模态对话框消息处理
            if (hwnd==NULL || !IsDialogMessage (hwnd,&msg))
            {
                //主消息循环体
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
    FreeLibrary(hInstance);     //释放模块句柄资源
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
    switch(message)
    {
        case WM_CREATE:
            initToolbar(hwnd);
            menuChange(hwnd);
            //初始化字符格式结构
            ZeroMemory(&cformat,sizeof(CHARFORMAT));
            cformat.cbSize=sizeof(CHARFORMAT);
            cformat.dwMask=CFM_SIZE|CFM_COLOR|CFM_FACE|CFM_ITALIC|CFM_BOLD|CFM_STRIKEOUT|CFM_UNDERLINE;
            //初始化段落格式结构
            ZeroMemory(¶format,sizeof(paraformat));
            paraformat.cbSize=sizeof(PARAFORMAT);
            return 0;
        case WM_SIZE:
            setWindowSize(hwnd);                //重置窗口
            return 0;
        case WM_CLOSE:
            close(hwnd);                        //响应close
            return 0;
        case WM_NOTIFY:
            notifyChange(hwnd,lParam);          //工具栏和richedit组件特定消息,键盘,鼠标控制
            return 0;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDM_TAB:
                    //tab加速键
                    SendMessage(hwndrich,EM_REPLACESEL,0,(LPARAM)TEXT("\t"));
                    textChange(F_CHANGE);
                    break;
                case IDM_NEW:
                    newfile(hwnd);
                    break;
                case IDM_OPEN:
                    openfile(hwnd);
                    break;
                case IDM_STYLE:
                    setFont(hwndrich);
                    break;
                case IDM_SAVEAS:
                    savefile(hwnd,SAVEAS);
                    break;
                case IDM_EXIT:
                    close(hwnd);
                    break;
                case IDM_SAVE:
                    savefile(hwnd,SAVE);
                    break;
                case IDM_REVO:
                    //撤销
                    SendMessage(hwndrich,EM_UNDO,0,0);
                    textChange(F_CHANGE);
                    break;
                case IDM_RECOVERY:
                    //恢复
                    SendMessage(hwndrich,EM_REDO,0,0);
                    textChange(F_CHANGE);
                    break;
                case IDM_COPY:
                    SendMessage(hwndrich,WM_COPY,0,0);
                    break;
                case IDM_SHEAR:
                    SendMessage(hwndrich,WM_CUT,0,0);
                    textChange(F_CHANGE);
                    break;
                case IDM_PASTE:
                    SendMessage(hwndrich,WM_PASTE,0,0);
                    textChange(F_CHANGE);
                    break;
                case IDM_REPLACE:
                    hwndfind=getFindDialog(hwnd,REPLACE);
                    break;
                case IDM_FIND:
                    hwndfind=getFindDialog(hwnd,FIND);
                    break;
                case IDM_BOLD:
                    quickSetFormat(BOLD);
                    break;
                case IDM_ITALIC:
                    quickSetFormat(ITALIC);
                    break;
                case IDM_UNDERLINE:
                    quickSetFormat(UNDERLINE);
                    break;
                case IDM_CENTER:
                    setAlignment(PFA_CENTER);
                    break;
                case IDM_LEFT:
                    setAlignment(PFA_LEFT);
                    break;
                case IDM_RIGHT:
                    setAlignment(PFA_RIGHT);
                    break;
                case IDM_ABOUT:
                    //about模态窗口
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hwnd,(DLGPROC)AboutDialogProc);
            }
            return 0;
        default:
            //查找替换对话框消息
            if (message==uFindReplaceMsg){
                findText();
                return 0;
            }
    }
    return DefWindowProc(hwnd, message, wParam, lParam) ;
}
//about模态对话框 回调函数
BOOL CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_CLOSE:
            EndDialog(hwndDlg, 0);
            return TRUE;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDOK:
                    EndDialog(hwndDlg, 0);
                    break;
            }
            return TRUE;
    }
    return FALSE;
}
//组件响应事件处理
void notifyChange(HWND hwnd,LPARAM lParam)
{
    LPTOOLTIPTEXT lpToolTipText;            //TOOLTIPTEXT结构指针
    MSGFILTER* msgfilter;                   //MSGFILTER结构指针

    //MSGFILTER,TOOLTIPTEXT结构第一个字段都是NMHDR结构
    LPNMHDR nmhdr=(LPNMHDR)lParam;          //从nmhdr结构获取code消息代码
    switch(nmhdr->code)
    {
        //richedit键盘鼠标事件响应
        case EN_MSGFILTER:
            msgfilter=(MSGFILTER*)lParam;
            //MSGFILTER结构中msg消息字段
            switch(msgfilter->msg)
            {
                case WM_MOUSEACTIVATE:
                    //鼠标单击
                    setStatus();
                    break;
                case WM_KEYUP:
                    //按键按起状态
                    textChange(F_CHANGE);
            }
            break;
        //工具栏提示文本响应
        case TTN_NEEDTEXT:
            lpToolTipText = (LPTOOLTIPTEXT)lParam;
            // 如果系统需要文本,则从资源中进行装载字符串
            LoadString (hInst,
                lpToolTipText->hdr.idFrom,    // 字符串ID == 命令ID
                szBuf,
                sizeof(szBuf));
            // 将结构lpszText字段指向字符串
            lpToolTipText->lpszText = szBuf;
            break;
        //选择文本改变响应
        case EN_SELCHANGE:
            menuChange(hwnd);
    }
}
//初始化工具栏
void initToolbar(HWND hwnd)
{
    //按钮结构数组
    TBBUTTON tbButtons[]={
          {BNEW, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BOPEN, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BSAVE, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
           {BREVO, IDM_REVO, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BRECOVERY, IDM_RECOVERY, TBSTATE_ENABLED, TBSTYLE_BUTTON},
            {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
           {BSHEAR, IDM_SHEAR, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BCOPY, IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BPASTE, IDM_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON},
            {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
           {BFIND, IDM_FIND, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BREPLACE, IDM_REPLACE, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
           {BFONTSTYLE, IDM_STYLE, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
           {BLEFT, IDM_LEFT, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BCENTER, IDM_CENTER, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BRIGHT, IDM_RIGHT, TBSTATE_ENABLED, TBSTYLE_BUTTON},
           {BBOLD, IDM_BOLD, TBSTATE_ENABLED, TBSTYLE_CHECK},
           {BITALIC, IDM_ITALIC, TBSTATE_ENABLED, TBSTYLE_CHECK},
           {BUNDERLINE, IDM_UNDERLINE, TBSTATE_ENABLED, TBSTYLE_CHECK},
           };
    //创建工具栏,返回工具栏句柄,IDR_TOOLBAR1工具栏图像id资源号
    hWndToolBar=CreateToolbarEx(hwnd,WS_VISIBLE|WS_CHILD|TBSTYLE_FLAT|TBSTYLE_TOOLTIPS,1,22,
                    hInst,IDR_TOOLBAR1,tbButtons,22,0,0,16,16,sizeof(TBBUTTON));

}
//
void createStatus(HWND hwnd)
{
    //创建一个状态栏
    hwndStatus=CreateWindow(STATUSCLASSNAME,"",SBS_SIZEGRIP|WS_CHILD | WS_VISIBLE,
                            0,0,0,0,hwnd,NULL,hInst,NULL);
    //移动初始化状态栏
    moveStatus(hwnd);
    //设置状态栏分栏文本,WPARAM指定栏目
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("就绪"));
    //使用格式化字符串来设置状态栏文本
    wsprintf(status_line,staformat,1,1);
    wsprintf(status_size,sizeformat,0);
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)1, (LPARAM)status_line);
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)2, (LPARAM)status_size);
}
void moveStatus(HWND hwnd)
{
    RECT rcClient;
    int width[3];                       //状态栏分割数组
    GetClientRect(hwnd, &rcClient);     //获取父窗口矩形
    int length=rcClient.right/3;        //根据父窗口宽度来分割指定大小
    width[0]=length;                    //状态栏第一栏宽度,为分割长度length
    width[1]=length*2;                  //状态栏往后栏目宽度,为length*栏目标号
    width[2]=length*3;

    //根据width数组来设置状态栏
    SendMessage(hwndStatus, SB_SETPARTS, 3, (LPARAM)(LPINT)width);
    MoveWindow(hwndStatus,0,0,0,0,TRUE);
}
//
void setStatus()
{
    int ln,col,lindex;
    //获取当前光标索引
    SendMessage(hwndrich,EM_GETSEL,(WPARAM)&lindex,0);
    //获取当前行
    ln=SendMessage(hwndrich,EM_LINEFROMCHAR,lindex,0);
    //返回当前行首字符所以
    col=SendMessage(hwndrich,EM_LINEINDEX,ln,0);
    //用lindex索引减col索引得到列号,更新消息
    wsprintf(status_line,staformat,ln+1,lindex-col+1);
    wsprintf(status_size,sizeformat,size);
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)1, (LPARAM)status_line);
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)2, (LPARAM)status_size);
}
///获取对话框
HWND getFindDialog(HWND hwnd,int model)
{
    //初始化FINDREPLACE结构
    ZeroMemory(&fr, sizeof(fr));
    fr.lStructSize = sizeof(FINDREPLACE);       //结构大小
    fr.hwndOwner = hwnd;                        //父窗口
    fr.lpstrFindWhat = szFindWhat;              //查找字符串
    fr.wFindWhatLen = sizeof(szFindWhat);       //查找字符串长度
    fr.Flags=FR_DOWN|FR_MATCHCASE|FR_HIDEWHOLEWORD;     //查找标记
    if (model){
        //替换对话框
        fr.lpstrReplaceWith=szReplaceWhat;              //替换字符串
        fr.wReplaceWithLen=sizeof(szReplaceWhat);       //字符串长度
        fr.Flags=FR_HIDEWHOLEWORD|FR_REPLACE|FR_REPLACEALL;     //替换标记
        return ReplaceText(&fr);
    }
    return FindText(&fr);
}
//查找,替换逻辑
void findText()
{
    //FR_DIALOGTERM消息就返回
    if (fr.Flags&FR_DIALOGTERM){return;}
    //定义查找结构,并获取当前光标位置
    FINDTEXTEX findtext;
    findtext.lpstrText=fr.lpstrFindWhat;
    SendMessage(hwndrich,EM_EXGETSEL,0,(LPARAM)&findtext.chrg);

    if (fr.Flags&FR_FINDNEXT||fr.Flags&FR_REPLACE||fr.Flags&FR_REPLACEALL)
    {
        //FR_REPLACE或FR_REPLACEALL消息时执行
        if (fr.Flags&FR_REPLACE||fr.Flags&FR_REPLACEALL){
            CHAR buffer[MAX_PATH];      //声明临时数组存储当前选中文本内容
            SendMessage(hwndrich,EM_GETSELTEXT,0,(LPARAM)buffer);
            if (strcmp(buffer,fr.lpstrFindWhat)==0){
                //当前选中内容和替换文本一致,进行替换并更新状态栏
                SendMessage(hwndrich,EM_REPLACESEL,0,(LPARAM)fr.lpstrReplaceWith);
                textChange(F_CHANGE);
            }
        }
        //FR_DOWN标志判断
        if (fr.Flags&FR_DOWN){
            //非FR_FINDNEXT消息,进行findtext结构查找范围更改
            if (!(fr.Flags&FR_FINDNEXT)&&findtext.chrg.cpMin!=findtext.chrg.cpMax){
                findtext.chrg.cpMin=findtext.chrg.cpMax+strlen(fr.lpstrReplaceWith);
            }else{findtext.chrg.cpMin=findtext.chrg.cpMax;}
            //findtext查找范围cpMax默认为当前文本内容长度
            findtext.chrg.cpMax=GetWindowTextLength(hwndrich);
        }else{ findtext.chrg.cpMax=-1;}                  //非FR_DOWN标志,进行向上查找,改变查找范围
        LRESULT pos;                                     //声明pos变量记录当前查找结果索引
        pos=SendMessage(hwndrich,EM_FINDTEXTEX,fr.Flags,(LPARAM)&findtext);
        if (pos==-1){
            if (fr.Flags&FR_REPLACEALL){
                //FR_REPLACEALL消息时提示信息
                MessageBox(hwndfind,TEXT("全部替换完毕!"),"Notepad",MB_ICONINFORMATION);
            }else{ MessageBox(hwndfind,TEXT("没有找到匹配字符!"),"Notepad",MB_ICONINFORMATION);}
            return;                     //FR_REPLACEALL消息,递归替换,函数返回点
        }else{
            //选中当前查找文本,高亮显示
            SendMessage(hwndrich,EM_EXSETSEL,0,(LPARAM)&(findtext.chrgText));
        }
        //FR_REPLACEALL 递归查找
        if (fr.Flags&FR_REPLACEALL){findText();};
    }
}
//richedit流回调函数
DWORD CALLBACK StreamCallback(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG *pcb)
{
    FILE* ofile=(FILE*)dwCookie;         //文件指针
    int get;
    LONG i=0;
    while ((get=fgetc(ofile))!=EOF && (i++)<cb){
        *(pbBuff++)=get;                //数据写入pbBuff缓冲区。cb写入最大值
    }
    *pcb=i;                             //实际写入大小
    return 0;
}

//流回调写入函数
DWORD CALLBACK SaveStreamCallback(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG *pcb)
{
    FILE* sfile=(FILE*)dwCookie;        //文件指针
    LONG i=0;
    while ((i++)<cb){
        putc(*(pbBuff++),sfile);        //pbBuff缓存区写入文件
    }
    *pcb=i;
    return 0;
}
//初始化OPENFILENAME结构
void initOpn(OPENFILENAME* opfn,char* filename,LPCSTR Title,DWORD filterIndex)
{
    ZeroMemory(opfn,sizeof(OPENFILENAME));
    opfn->lStructSize=sizeof(OPENFILENAME);         //结构大小
    opfn->lpstrFile=filename;                       //文件名保存字符数组
    opfn->lpstrTitle=Title;                         //标题
    opfn->lpstrFilter=filtername;                   //文件过滤器
    opfn->nMaxFile=MAX_PATH;                        //lpstrFile数组大小
    opfn->lpstrDefExt="";                           //默认文件后缀
    //定义打开模式标记
    opfn->Flags=OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
    opfn->nFilterIndex=filterIndex;                 //文件过滤器索引
}
//初始化编辑流结构
void initEidtStream(EDITSTREAM* stream,LPCSTR type,EDITSTREAMCALLBACK callback)
{
    ZeroMemory(stream,sizeof(EDITSTREAM));
    file=fopen(filename,type);              //根据模式打开文件
    stream->dwCookie=(DWORD_PTR)file;       //定义编辑流结构字段
    stream->dwError=0;
    stream->pfnCallback=callback;           //回调函数
    if (strcmp(type,TEXT("rb"))==0){
        TCHAR buff[3];                          //字符缓存
        //16进制格式化输入字符缓冲区,FFFE为unicode文件头,这里逆序存入字符数组,为FEFF
        sprintf(buff,"%X%X",fgetc(file),fgetc(file));
        if (strcmp(buff,TEXT("FEFF"))==0){
            txtcode=TXT_UNICODE;
        }else{
            txtcode=TXT_ASCII;
            fseek(file,0,0);        //从定位文件到开头
        }
    }else{
        IF_FALSE(txtcode,fprintf(file,TEXT("%c%c"),255,254),0);//255->0xFF,254->0xFE
    }
}
//保存文件
void savefile(HWND hwnd,int savemodel)
{
    //判断保存模式
    if(savemodel || strcmp(SaveFileName,TEXT(""))==0)
    {
        if (savefiledialog(hwndrich)){
            //保存成功。更新标题名
            strcpy(SaveFileName,filename);
            SetWindowText(hwnd,strcat(SaveFileName,TEXT("-Notepad")));
        }
    }else{
        savetofile();
    }
}
//保存文件对话框
int savefiledialog(HWND hwndrich)
{
    //初始化OPENFILENAME结构-保存
    initOpn(&opfn,filename,"保存",filterIndex);
    if(GetSaveFileName(&opfn)){
        savetofile();
        return 1;
    }
    return 0;
}
//保存文件
void savetofile()
{
    EDITSTREAM stream;
    //写入模式初始化编辑流
    initEidtStream(&stream,"wb",SaveStreamCallback);
    //判断文件后缀,其实OPENFILENAME结构有保存选择后缀字段,使用字段会简化点
    selText(filtername,opfn.nFilterIndex,defext);
    TCHAR* charpos=strstr(defext,"rtf");
    if (charpos==NULL){
        //非rtf后缀,都使用text格式保存
        IF_FALSE(txtcode,SendMessage(hwndrich,EM_STREAMOUT,SF_TEXT|SF_UNICODE,(LPARAM)&stream),
            SendMessage(hwndrich,EM_STREAMOUT,SF_TEXT,(LPARAM)&stream));
    }else{ SendMessage(hwndrich,EM_STREAMOUT,SF_RTF,(LPARAM)&stream);}
    //更新状态栏,并修改编辑状态。
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("已保存"));
    isSave=TRUE;
    fclose(file);       //关闭文件句柄
}
//字符格式结构
void getCHARFORMAT(HWND hwndrich,CHARFORMAT* cformat,CHOOSEFONT* cf)
{
    LOGFONT* lf=cf->lpLogFont;
    //获取当前选择字符样式结构,CHARFORMAT
    SendMessage(hwndrich,EM_GETCHARFORMAT,SCF_SELECTION,(LPARAM)cformat);
    //与~CFE_AUTOCOLOR字段,总是使dwEffects的CFE_AUTOCOLOR位无效
    cformat->dwEffects&=~CFE_AUTOCOLOR;
    cf->rgbColors=cformat->crTextColor;
    strcpy(lf->lfFaceName,cformat->szFaceName);
    //根据CHARFORMAT结构字段初始化LOGFONT
    lf->lfStrikeOut=cformat->dwEffects&CFM_STRIKEOUT;       //删除线
    lf->lfUnderline=cformat->dwEffects&CFM_UNDERLINE;       //下划线
    lf->lfItalic=cformat->dwEffects&CFE_ITALIC;             //斜体
    cformat->dwEffects&CFE_BOLD?lf->lfWeight=FW_BOLD:0;     //粗体
    lf->lfHeight=-cformat->yHeight/15;                      //字体大小
}
//工具栏快速设置
void quickSetFormat(int STYLE)
{
    //获取选中文本字符格式结构
    SendMessage(hwndrich,EM_GETCHARFORMAT,SCF_SELECTION,(LPARAM)&cformat);
    switch(STYLE)
    {
        case BOLD:
            if (SendMessage(hWndToolBar,TB_ISBUTTONCHECKED,IDM_BOLD,0)){
                cformat.dwEffects|=CFM_BOLD;  //|=,添加CFM_BOLD属性。&=~CFM_BOLD清除属性
            }else{cformat.dwEffects&=~CFM_BOLD;}
            break;
        case ITALIC:
            if (SendMessage(hWndToolBar,TB_ISBUTTONCHECKED,IDM_ITALIC,0)){
                cformat.dwEffects|=CFM_ITALIC;  //斜体
            }else{cformat.dwEffects&=~CFM_ITALIC;}
            break;
        case UNDERLINE:
            if (SendMessage(hWndToolBar,TB_ISBUTTONCHECKED,IDM_UNDERLINE,0)){
                cformat.dwEffects|=CFM_UNDERLINE;   //下划线
            }else{cformat.dwEffects&=~CFM_UNDERLINE;}
    }
    //设置格式,状态栏
    SendMessage(hwndrich,EM_SETCHARFORMAT,SCF_SELECTION,(LPARAM)&cformat);
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("已修改"));
    isSave=FALSE;
}
//选取文本动态改变工具栏图标状态
void checkFormat()
{
    SendMessage(hwndrich,EM_GETCHARFORMAT,SCF_SELECTION,(LPARAM)&cformat);
    /*?三元运算符,根据选中文本格式,改变对应工具栏图标状态*/
    //下划线
    cformat.dwEffects&CFM_UNDERLINE?SendMessage(hWndToolBar,TB_CHECKBUTTON,IDM_UNDERLINE,TRUE):
                                     SendMessage(hWndToolBar,TB_CHECKBUTTON,IDM_UNDERLINE,FALSE);
    //斜体
    cformat.dwEffects&CFE_ITALIC?SendMessage(hWndToolBar,TB_CHECKBUTTON,IDM_ITALIC,TRUE):
                                    SendMessage(hWndToolBar,TB_CHECKBUTTON,IDM_ITALIC,FALSE);
    //粗体
    cformat.dwEffects&CFE_BOLD?SendMessage(hWndToolBar,TB_CHECKBUTTON,IDM_BOLD,TRUE):
                                    SendMessage(hWndToolBar,TB_CHECKBUTTON,IDM_BOLD,FALSE);
}
//设置样式
void setFont(HWND hwndrich)
{
    CHOOSEFONT cf;                      //字体设置对话框结构
    LOGFONT lf;                         //字体属性结构
    ZeroMemory(&cf,sizeof(CHOOSEFONT));
    cf.lStructSize=sizeof(CHOOSEFONT);
    cf.lpLogFont= &lf;
    cf.Flags= CF_SCREENFONTS|CF_EFFECTS|CF_INITTOLOGFONTSTRUCT;     //对话框默认显示样式标记
    getCHARFORMAT(hwndrich,&cformat,&cf);                      //获取当前样式来设置字体对话框

    if(ChooseFont(&cf)){
        //依据LOGFONT字段来设置CHARFORMAT结构字段量
        lf.lfItalic?(cformat.dwEffects|=CFE_ITALIC):(cformat.dwEffects&=~CFE_ITALIC);
        lf.lfStrikeOut?(cformat.dwEffects|=CFM_STRIKEOUT):(cformat.dwEffects&=~CFM_STRIKEOUT);
        lf.lfUnderline?(cformat.dwEffects|=CFM_UNDERLINE):(cformat.dwEffects&=~CFM_UNDERLINE);
        lf.lfWeight>=FW_BOLD?(cformat.dwEffects|=CFM_BOLD):(cformat.dwEffects&=~CFM_BOLD);

        cformat.crTextColor=cf.rgbColors;       //颜色
        cformat.yHeight=-lf.lfHeight*15;        //size大小
        strcpy(cformat.szFaceName,lf.lfFaceName);           //字体名称
        SendMessage(hwndrich,EM_SETCHARFORMAT,SCF_SELECTION,(LPARAM)&cformat);
        SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("已修改"));
        isSave=FALSE;
    }
}
//文件后缀判断,//可以直接使用OPENFILENAME结构字段保存选择的后缀
void selText(TCHAR* lpchar,int index,TCHAR* defext)
{
    int i;
    //根据选择索引值获取索引对应后缀字符串
    for(i=0;i<((index-1)*2+1);++i){
        while(*(lpchar++)!='\0'){
        }
    }
    strcpy(defext,lpchar);
}
//打开文件
void openfile(HWND hwnd)
{
    if (isSave){
        readfile(hwnd);
    }else{
        int result=MessageBox(hwnd,TEXT("文件已经改动!需要保存吗?"),TEXT("提示"),MB_YESNOCANCEL|MB_ICONINFORMATION);
        switch(result)
        {
            case IDYES:
                //另存为
                savefile(hwnd,SAVEAS);
                readfile(hwnd);
                break;
            case IDNO:
                readfile(hwnd);
                break;
            case IDCANCEL:
                break;
        }
    }
}
//拖放文件打开
void clickfile(HWND hwnd,LPSTR name)
{
    //获取命令行字符串,截取两端的“
    name=substring(name,1,strlen(name)-2);
    strcpy(filename,name);
    //初始化编辑流,并打开文件
    EDITSTREAM stream;
    initEidtStream(&stream,"rb",StreamCallback);
    //从文件检查后缀
    TCHAR* charpos=strstr(filename,".rtf");
    if (charpos==NULL){
        //非rtf文件打开模式
        filterIndex=2;      //改变后缀索引
        //根据文本编码打开文件
        if (txtcode){
            SendMessage(hwndrich,EM_STREAMIN,SF_TEXT|SF_UNICODE,(LPARAM)&stream);
            txtcode=TXT_UNICODE;
        }else{
            //ASCII码
            SendMessage(hwndrich,EM_STREAMIN,SF_TEXT,(LPARAM)&stream);
        }
    }else{
        filterIndex=1;
        SendMessage(hwndrich,EM_STREAMIN,SF_RTF,(LPARAM)&stream);
    }
    //初始化OPENFILENAME结构
    initOpn(&opfn,filename,"打开",filterIndex);
    strcpy(SaveFileName,filename);              //设置标题栏
    SetWindowText(hwnd,strcat(SaveFileName,TEXT("-Notepad")));
    //更改状态栏信息
    textChange(F_OPEN);
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("就绪"));
    isSave=TRUE;
    fclose(file);
}
//读取文件
void readfile(HWND hwnd)
{
    //打开模式初始化结构
    initOpn(&opfn,filename,TEXT("打开"),filterIndex);
    if(GetOpenFileName(&opfn)){
        EDITSTREAM stream;          //读取模式初始化编辑流
        initEidtStream(&stream,"rb",StreamCallback);
        filterIndex=opfn.nFilterIndex;
        selText(filtername,opfn.nFilterIndex,defext);
        TCHAR* charpos=strstr(defext,"rtf");        //检索文件后缀
        if (charpos==NULL){
            SetWindowText(hwndrich,TEXT(""));       //清空当前内容
            //根据文本编码打开文件
            IF_FALSE(txtcode,SendMessage(hwndrich,EM_STREAMIN,SF_TEXT|SF_UNICODE,(LPARAM)&stream),
                     SendMessage(hwndrich,EM_STREAMIN,SF_TEXT,(LPARAM)&stream));
        }else{ SendMessage(hwndrich,EM_STREAMIN,SF_RTF,(LPARAM)&stream);}
        //更改标题栏文件名
        strcpy(SaveFileName,filename);
        SetWindowText(hwnd,strcat(SaveFileName,TEXT("-Notepad")));

        textChange(F_OPEN);
        SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("就绪"));
        isSave=TRUE;
        fclose(file);
    }
}
//获取内容长度
long getLength()
{
    //GETTEXTLENGTHEX结构 用来保存当前内容长度字段
    GETTEXTLENGTHEX lengthstrust={GTL_NUMCHARS,1200};
    return SendMessage(hwndrich,EM_GETTEXTLENGTHEX,(WPARAM)&lengthstrust,(LPARAM)0);
}
//窗口布局改变
void setWindowSize(HWND hwnd)
{
    RECT mainrect,recttemp;
    //width,richedit宽度,height,richedit高度
    long width,height;
    //获取主窗口布局矩形
    GetClientRect(hwnd,&mainrect);
    //获取width
    width=mainrect.right-mainrect.left;
    //移动状态栏
    moveStatus(hwnd);
    //获取状态栏窗口矩形
    GetWindowRect(hwndStatus,&recttemp);
    height=recttemp.top;
    //获取工具栏窗口矩形
    GetWindowRect(hWndToolBar,&recttemp);
    //得到richedit窗口top
    long top=recttemp.bottom-recttemp.top;
    height-=recttemp.bottom;
    SendMessage(hWndToolBar,TB_AUTOSIZE,0,0);
    //改变richedit窗口位置大小
    MoveWindow(hwndrich,mainrect.left,top,
               width,height,TRUE);
}
//设置状态栏
void textChange(int model)
{
    //当前文本长度
    long sizetemp=getLength();
    //文本内容长度改变,model为open,或isSave为TRUE
    if (model && isSave && size!=sizetemp){
        isSave=FALSE;
        SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("已修改"));
    }
    //更新文本长度
    size=sizetemp;
    setStatus();
}
//菜单工具栏状态
void menuChange(HWND hwnd)
{
    CHARRANGE chrg;
    //获取文本选择区域
    SendMessage(hwndrich,EM_EXGETSEL,0,(LPARAM)&chrg);
    if (chrg.cpMin==chrg.cpMax){
        EnableMenuItem(GetMenu(hwnd),IDM_COPY,MF_BYCOMMAND|MF_GRAYED);
        EnableMenuItem(GetMenu(hwnd),IDM_SHEAR,MF_BYCOMMAND|MF_GRAYED);
        EnableMenuItem(GetMenu(hwnd),IDM_STYLE,MF_BYCOMMAND|MF_GRAYED);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_COPY,FALSE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_SHEAR,FALSE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_STYLE,FALSE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_BOLD,FALSE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_ITALIC,FALSE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_UNDERLINE,FALSE);
    }else{
        EnableMenuItem(GetMenu(hwnd),IDM_COPY,MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(GetMenu(hwnd),IDM_SHEAR,MF_BYCOMMAND|MF_ENABLED);
        EnableMenuItem(GetMenu(hwnd),IDM_STYLE,MF_BYCOMMAND|MF_ENABLED);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_COPY,TRUE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_SHEAR,TRUE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_STYLE,TRUE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_BOLD,TRUE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_ITALIC,TRUE);
        SendMessage(hWndToolBar,TB_ENABLEBUTTON,IDM_UNDERLINE,TRUE);
        //更新格式化工具栏状态
        checkFormat();
    }
}
//新建文件
void newfile(HWND hwnd)
{
    if (isSave){
        SetWindowText(hwndrich,TEXT(""));
        SetWindowText(hwnd,defaultname);
    }else{
        int result=MessageBox(hwnd,TEXT("文件已经改动!需要保存吗?"),TEXT("提示"),MB_YESNOCANCEL|MB_ICONINFORMATION);
        switch(result)
        {
            case IDYES:
                savefile(hwnd,SAVEAS);
                break;
            case IDNO:
                //清空窗口内容,设置标题栏
                SetWindowText(hwndrich,TEXT(""));
                SetWindowText(hwnd,defaultname);
                SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("就绪"));
                isSave=TRUE;
                break;
            case IDCANCEL:
                break;
        }
    }
    txtcode=TXT_ASCII; //改变默认编码
}
//退出
void close(HWND hwnd)
{
    //检查文件保存状态
    if (isSave){
        PostQuitMessage(0);
    }else{
        int result=MessageBox(hwnd,TEXT("文件已经改动!需要保存吗?"),TEXT("提示"),
                              MB_YESNOCANCEL|MB_ICONINFORMATION);
        switch(result)
        {
            case IDYES:
                //保存文件再退出
                savefile(hwnd,SAVE);
                PostQuitMessage(0);
                break;
            case IDNO:
                PostQuitMessage(0);
                break;
            case IDCANCEL:
                break;
        }
    }
}
//设置段落格式
void setAlignment(int style)
{
    //获取当前段落格式  style格式参数
    SendMessage(hwndrich,EM_GETPARAFORMAT,0,(LPARAM)¶format);
    //设置文本居中,靠左,靠右属性有效字段PFM_ALIGNMENT
    paraformat.dwMask|=PFM_ALIGNMENT;
    paraformat.wAlignment=style;
    SendMessage(hwndrich,EM_SETPARAFORMAT,0,(LPARAM)¶format);
    //更改保存状态
    isSave=FALSE;
    SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("已修改"));
}
//字符串截取
TCHAR* substring(TCHAR* ch,int pos,int length)
{
    char* pch=ch;
    //定义一个字符指针,指向传递进来的ch地址。
    TCHAR* subch=calloc(sizeof(TCHAR),length+1);
    //通过calloc来分配一个length长度的字符数组,返回的是字符指针。
    int i;
    pch=pch+pos;
    //是pch指针指向pos位置。
    for(i=0;i<length;i++)
    {
        subch[i]=*(pch++);
    }
    subch[length]='\0';//加上字符串结束符。
    return subch;		//返回分配的字符数组地址。
}



 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

win32sdk学习 richedit实现的一个简单记事本 的相关文章

  • [LaTeX|翻译]What are .cls and .sty files? How are they different?

    什么是 cls和 sty文件 xff1f 它们的区别是什么 xff1f What are cls and sty files How are they different 通常来讲 xff0c cls和 sty文件是用于增强LaTeX功能的
  • [Pyplot] 绘制3D曲面+自定义面片颜色

    一 背景 使用python 43 matplotlib实现绘制3D曲面 xff08 由多个小面片组成 xff09 xff0c 支持自定义面片颜色 xff1b 实现效果如图 a b 所示 xff1a a 使用面片法向作为面片颜色 b 使用默认
  • [STL]使用vector::erase对vector遍历删除

    在对vector中的元素进行遍历删除时遇到了一点问题 xff0c 查博客发现博客上并不靠谱 在此记录 xff0c 共同进步 vector循环遍历正确代码 span class token keyword for span span clas
  • 判断一个数是不是质数(素数),3种方式介绍

    本文参考博文判断一个数是不是质数 素数 xff0c 3种方式介绍 xff0c 原文章解释的已经很详细 xff0c 本问增加部分博主自己的理解 一 概念介绍 质数 xff1a 质数是指在大于1的自然数中 xff0c 除了1和它本身以外不再有其
  • Ubuntu/Arm安装Mysql报错:mysql-server 依赖于 mysql-server-5.7;然而:软件包 mysql-server-5.7 尚未配置。

    报错内容如下 xff1a dpkg 依赖关系问题使得 mysql server 的配置工作不能继续 xff1a mysql server 依赖于 mysql server 5 7 xff1b 然而 xff1a 软件包 mysql serve
  • E90-DTU系列无线数传电台网关与节点4gDTU通信教程

    以E90 DTU 400SL22 ETH 与E90 DTU 400SL22 为例实现网关与节点进行数据交换 xff0c 其它频段或功率的网关 节点 xff0c 其操作方式与该视频教程一致 第一步 安装网关 为网关安装天线电源模块 第二步 调
  • STM32实现将printf重定向到串口的3种方法

    STM32实现将printf重定向到串口的3种方法 目录 STM32实现将printf重定向到串口的3种方法一 使用MicroLib重定向printf二 不使用MicroLib重定向printf三 使用标准库自定义printf 函数到串口1
  • 时钟传感器—DS3231

    时钟传感器 DS3231 DS3231概述DS3231引脚DS3231寄存器DS3231 操作 DS3231概述 DS3231是一款高精度I2C实时时钟器件内部带温度补偿 闰年补偿提供两个可编程日历闹钟提供秒 分 时 星期 日期 月 年等信
  • C语言进阶

    C语言进阶 数据操作1 数据修饰 auto static register const volatile2 大端模式 小端模式 内存操作1 动态内存管理 xff08 堆区 heap xff09 malloc calloc realloc f
  • 虚拟机VMware:由于找不到vcruntime140_1.dll,无法继续执行代码

    最近换了台新电脑 xff0c 就开始安装虚拟机VMware xff0c 就发现虚拟机开机的时候 xff0c 弹出了一个错误 xff0c 下图 于是 xff0c 百度了一下缺少vcruntime140 1 dll xff0c 如何解决 解决方
  • Linux 基础

    Linux 基础 进程1 进程查看命令 ps pstree job2 进程的状态3 进程间的关系3 1 父进程与子进程 xff0c frok vfrok 3 2 进程组3 3 会话 4 进程间通信 IPC4 1 管道 pipe4 2 信号
  • STC8A 应用知识归纳

    STC8A 应用知识归纳 串口通信串口寄存器介绍功能 定时器 计数器定时器寄存器介绍 看门狗 xff1a 复位看门狗寄存器操作 外部中断ADCADC寄存器介绍 串口通信 每个串行口有两个数据缓冲器 xff08 SBUF xff09 一个移位
  • LoRa是什么

    LoRa是什么 LoRa是什么LoRa调制LoRa调制参数LoRa WAN 网络LoRa技术框图LoRa WAN网络组成LoRa终端设备划分成A B C三类 LoRa是什么 LoRa 是LPWAN通信技术中的一种 LoRa 是美国Semte
  • LoRa模块(内置MCU),亿百特E22-400T30S,广播监听、定点传输、中继组网

    LoRa模块 xff08 内置MCU xff09 xff0c 亿百特E22 400T30S xff0c 广播监听 定点传输 中继组网 配置说明广播监听 定点传输中继组网 配置说明 工作模式 模式M1 M0模式介绍模式0 传输模式0 0串口打
  • 定位——GNSS

    GNSS GNSS 即全球导航卫星系统 xff08 Global Navigation Satellite System xff09 是所有导航定位卫星的总称 xff0c 凡是可以通过捕获跟踪其卫星信号实现定位的系统 xff0c 均可纳入G
  • 惠普zbook15g2拆机换硅脂

    前几天电脑cpu温度居高不下 xff0c 就寻思着拆机清灰 43 替换硅脂 xff0c 结果网上到处找不到惠普zbook15的完整拆机指导 xff0c 唯一可用的某论坛关于zbook17的拆机分享看着很不舒服 xff0c 于是决定自己成功后
  • Camera-LIDAR 联合标定方法总结

    项目需要融合雷达和相机 xff0c 所以要做联合标定 xff0c 记录下收集的标定方法 一 总体标定步骤 标定就是找到雷达到相机的空间转换关系 xff0c 在不同的坐标系之间转换需要旋转矩阵 R 和平移矩阵 T xff0c 为后续的雷达和相
  • 52条SQL语句性能优化策略

    1 对查询进行优化 xff0c 应尽量避免全表扫描 xff0c 首先应考虑在 WHERE 及 ORDER BY 涉及的列上建立索引 2 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断 xff0c 创建表时 NULL 是默认值
  • TCP/IP四层模型及各层协议首部详述

    1 OSI七层和TCP IP四层的关系 1 1 OSI引入了服务 接口 协议 分层的概念 xff0c TCP IP借鉴了OSI的这些概念建立TCP IP模型 1 2 OSI先有模型 xff0c 后有协议 xff0c 先有标准 xff0c 后
  • 位域的定义和使用

    位域 xff1a 有些信息在存储时 xff0c 并不需要占用一个完整的字节 xff0c 而只需占几个或一个二进制位 例如在存放一个开关量时 xff0c 只有0和1 两种状态 xff0c 用一位二进位即可 为了节省存储空间 xff0c 并使处

随机推荐

  • Makefile 的运行(六)

    一般来说 xff0c 最简单的就是直接在命令行下输入make命令 xff0c make命令会找当前目录的makefile来执行 xff0c 一切都是自动的 但也有时你也许只想让make重编译某些文件 xff0c 而不是整个工程 xff0c
  • FreeRTOS 任务优先级说明

    freeRTOS任务优先级与Unix进程优先级不同 FreeRTOS 任务优先 xff1a 任务优先级数值越小 xff0c 任务优先级越低 Unix 任务优先 xff1a 进程优先级数值越小 xff0c 进程优先级越高 下面对 FreeRT
  • QT子线程读取串口数据并传到主线程

    转载 读取串口部分借鉴于Quartz010的文章 如何在QT中读取串口数据 http blog csdn net zz709196484 article details 66474917 这是博客网址 大致思路就是子线程去读取串口数据并传送
  • 最常用的Java库一览

    一个典型的Java项目依赖于第三方库 本文总结的Java库适用于各种应用 xff0c 比较流行并且广泛使用 其中一些还提供简单的示例 xff08 来自ProgramCreek xff09 Java SDK 肯定是使用最广的库 xff0c 所
  • C#Socket编程详解(一)TCP与UDP简介

    一 TCP与UDP 1 TCP 1 1 定义 TCP xff08 TransmissionControl Protocol xff09 传输控制协议 是一种可靠的 面向连接的协议 xff08 eg 打电话 xff09 传输效率低全双工通信
  • AD19导出bom表的方法(按照元件不同数值分类,重点信息突出)

    我画电路图用的是AD19的软件 xff0c 最后板子画好了要进行元器件采购要生成bom表 xff0c 查了一下相关的资料 xff0c 总结整理一下 xff1a 1 在报告 xff08 report xff09 打开Bill of Mater
  • 为什么c++要“在头文件中声明,在源文件中定义”?

    gt gt gt 搬运一个知乎问答 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 下面是回答 61 61 61 61 61 61 61 61 61 61 61 61 61
  • HTTP header 参数丢失情况分析以及解决防范

    HTTP header 参数丢失情况分析以及解决防范 1 问题 当项目有Nginx做了代理的时候 xff0c 请求头中传参 34 user ip 34 xff0c 接口接收不到 2 问题分析 默认nginx是不能转发带 的header信息的
  • Keil 调试局部变量查看显示not in scope

    调整优化级别 不同的优化级别允许您在编译代码中可用的调试信息级别与代码性能之间进行权衡 可以使用以下优化级别 xff1a o O0应用最小优化 大多数优化都被关闭 xff0c 生成的代码具有最佳的调试视图 o O1应用受限优化 例如 xff
  • 【32单片机学习】(6)STM32串口+DMA收发不定长数据

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 目录 前言 1 DMA介绍 2 串口接收数据 3 实验现象 1 实验电路图 2 串口收发不定长数据视频演示 3 OLED 显示接收数据 4
  • www-authenticate认证过程浅析

    文档 xff1a www authenticate认证过程简单研究 创建 xff1a http hi baidu com netee 日期 xff1a 2009 10 07 版权 xff1a 原创内容 xff0c 转载请注明出处 xff0c
  • STM32F407ZG 串口通信+固定帧头帧尾传输数据帧

    STM32F407ZG开发板学习 xff08 4 xff09 串口简介通信接口USART接线电平标准数据帧 实验 xff1a 固定帧头帧尾数据传输需求最终思路以及思考过程思路中断函数程序段长度的问题缓冲区数据结构的决定 初始化配置中断服务函
  • 基于杰理RTOS平台的433射频无线数传通信

    在杰理的AC7916N实现了433射频的数据发送 xff0c 在杰理的AD15系列实现433射频接收 xff0c 本代码用于门铃项目收发 xff0c 下面请看代码 首先是AC7916N的433数据发送代码 xff0c 发送部分的程序放在一个
  • boost简介

    我认为做为一名c 43 43 编程人员 xff0c 对boost库必须要有一定的了解与使用 这对于代码的整洁和效率有很大的帮助 借着这个机会整理一下使用boost库的经验 xff0c 顺便再学习一下 首先 xff0c 什么是boost库 b
  • Android上增加对M3U8文件下载的功能

    最近给一个客户提了一个需求 xff0c 想对他们网站的视频做一个下载的功能 xff0c 希望他的App能够缓存视频功能 xff0c 然后用户可以在下次快速播放视频 一开始接到这个需求 xff0c 自然是去搜罗一遍 xff0c 有没有可靠稳定
  • VLC自定义m3u8协议片段加密方式

    hls xff08 m3u8 xff09 本身有一套自己的加密方式 xff0c 可以保证片段是安全的 但是本身在传输的过程中加密key请求容易被截获 xff0c 这样存在一点片段key被截取的风险 xff0c 截取者就可以根据片段和key重
  • Fragment里使用CordovaWebView

    因为CordovaWebView 默认的初始化里判断了Content是不是继承CordovaInterface xff0c 如果直接使用Fragment继承CordovaInterface xff0c CordovaInterface有个抽
  • CMake教程(二)- 添加静态库文件和动态库文件

    CMake教程 xff08 二 xff09 添加静态库文件和动态库文件 什么是库文件静态链接库动态链接库静态库和动态库的区别 如何在CMake中添加库文件CMake 中 target link libraries 的 PRIVATE xff
  • jtextpane的使用方法

    jtextpane是java swing中的一个组件 xff0c 是一个可以编辑和显示html xff0c rtf和普通文本的富文本组件 xff0c jtextpane是根据使用EditorKit来显示内容的 xff0c 目前jtextpa
  • win32sdk学习 richedit实现的一个简单记事本

    记录的源文件 xff0c 篇幅有点长 工具栏资源图片 bmp格式 notepad h文件 NOTEPAD H INCLUDED Copyright C name xff1a notepad author xff1a suju 日期 xff1