《Windows API每日一练》10.3 公用对话框

Windows最初发行时的主要目标之一就是提倡一种标准化的用户界面。对于公用菜单 项来说,这一目标实现得很快。几乎所有的软件制造商都采用了Alt-File-Open组合来打开 文件。但是,真正用来打开文件的对话框却经常很不一样。

从Windows 3.1开始,这一问题的解决方案开始出现。这一方案被称作“公用对话框库”(common dialogue box library)。这个库包括了一些函数,可以用来激活打开和存储文件、 查找和替换、选择颜色、选择字体以及打印(将在第十三章中演示)的对话框。

在使用这些函数时,基本上要初始化一个结构的一些字段并将该结构的指针传递给公用对话框库的某个函数。该函数会创建并显示相应对话框。当用户关闭对话框时,函数将控制权返还给程序,然后程序可以从此前传递给函数的结构中获取信息。

需要在所有用到公用对话框库的C源文件中包括COMMDLG.H头文件。

本节必须掌握的知识点:

        公用对话框

        第68练:完善的POPPAD

        第69练:颜色对话框模板

10.3.1 公用对话框

打开文件公用对话框

       要打开文件的公用对话框,可以使用 Windows API 中的 GetOpenFileName 函数。该函数允许用户选择一个文件,并返回所选文件的路径。

以下是 GetOpenFileName 函数的函数原型:

BOOL GetOpenFileName(

    LPOPENFILENAME lpofn

);

参数说明:

lpofn:指向 OPENFILENAME 结构体的指针,它包含了打开文件对话框的各种参数和选项。

返回值:

如果用户选择了文件并点击了打开按钮,函数返回非零值 (TRUE)。

如果用户取消了对话框或者发生了错误,函数返回零值 (FALSE)。

OPENFILENAME 是一个结构体,用于配置和传递给 GetOpenFileName 和 GetSaveFileName 函数的参数和选项。它定义了打开文件对话框和保存文件对话框的行为。

以下是 OPENFILENAME 结构体的定义:

typedef struct tagOFN {

    DWORD        lStructSize;// 结构体的大小,必须设置为 sizeof(OPENFILENAME)

    HWND         hwndOwner;          // 父窗口的句柄

    HINSTANCE    hInstance;                // 应用程序实例句柄

    LPCTSTR      lpstrFilter;                  // 文件过滤器

    LPTSTR       lpstrCustomFilter;       // 自定义过滤器

    DWORD        nMaxCustFilter;      // 自定义过滤器的最大长度

    DWORD        nFilterIndex;           // 初始选择的过滤器索引

    LPTSTR       lpstrFile;                     // 接收选择的文件路径的缓冲区

    DWORD        nMaxFile;               // lpstrFile 缓冲区的大小

    LPTSTR       lpstrFileTitle;               // 接收选择的文件名的缓冲区

    DWORD        nMaxFileTitle;         // lpstrFileTitle 缓冲区的大小

    LPCTSTR      lpstrInitialDir;       // 初始目录

    LPCTSTR      lpstrTitle;                   // 对话框标题

    DWORD        Flags;                     // 选项标志

    WORD         nFileOffset;             // 文件名在 lpstrFile 中的偏移量

    WORD         nFileExtension;        // 文件扩展名在 lpstrFile 中的偏移量

    LPCTSTR      lpstrDefExt;                // 默认文件扩展名

    LPARAM       lCustData;                // 自定义数据

    LPOFNHOOKPROC lpfnHook;           // 钩子函数

    LPCTSTR      lpTemplateName;      // 自定义模板的资源名称

#if (_WIN32_WINNT >= 0x0500)

    void *        pvReserved;               // 保留,不要使用

    DWORD        dwReserved;          // 保留,不要使用

    DWORD        FlagsEx;                  // 扩展选项标志

#endif // (_WIN32_WINNT >= 0x0500)

} OPENFILENAME, *LPOPENFILENAME;

OPENFILENAME 结构体的注释详细说明了每个成员的作用和用法,您可以根据需要设置相应的成员来配置打开文件对话框的行为和选项。

●使用 GetOpenFileName 函数的一般步骤如下:

1.初始化 OPENFILENAME 结构体,设置各种参数和选项。

2.调用 GetOpenFileName 函数,并传递指向初始化的 OPENFILENAME 结构体的指针。

3.检查 GetOpenFileName 的返回值,判断用户是否选择了文件并点击了打开按钮。

4.如果返回值为非零,通过 OPENFILENAME 结构体的 lpstrFile 成员获取所选文件的路径。

●以下是一个简单的示例代码,演示如何使用 GetOpenFileName 函数:

#include <windows.h>

#include <commdlg.h>

int main()

{

    OPENFILENAME ofn = { 0 };

    TCHAR szFile[MAX_PATH] = { 0 };

    ofn.lStructSize = sizeof(OPENFILENAME);

    ofn.hwndOwner = NULL;  // 父窗口句柄,可设置为 NULL

    ofn.lpstrFilter = _T("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");  // 文件过滤器

    ofn.lpstrFile = szFile;  // 存储用户选择的文件路径

    ofn.nMaxFile = MAX_PATH;  // szFile 缓冲区大小

    ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;  // 选项

    if (GetOpenFileName(&ofn))

    {

        // 用户选择了文件并点击了打开按钮

        MessageBox(NULL, ofn.lpstrFile, _T("Selected File"), MB_OK);

    }

    return 0;

}

以上示例代码使用 GetOpenFileName 函数打开一个包含文件过滤器的打开文件对话框。用户可以选择一个文本文件 (.txt) 或任何文件 (所有文件选项)。如果用户选择了文件并点击了打开按钮,则通过 MessageBox 函数显示所选文件的路径。

【注意】示例代码中使用了 _T 宏,它根据编译选项确定是使用 ANSI 字符集还是 Unicode 字符集。在 Unicode 编译模式下,TCHAR 被定义为 wchar_t,在 ANSI 编译模式下,TCHAR 被定义为 char。因此,字符串参数和结构体成员使用 _T 宏进行宽字符/窄字符兼容处理。

存储文件公用对话框

       要使用公共文件对话框来存储文件,您可以使用 GetSaveFileName 函数和 OPENFILENAME 结构体。以下是一个简单的示例代码,展示如何配置和使用公共文件对话框来存储文件:

#include <windows.h>

#include <commdlg.h>

int main()

{

    // 初始化 OPENFILENAME 结构体

    OPENFILENAME ofn = {0};

    TCHAR szFile[MAX_PATH] = {0};

    ofn.lStructSize = sizeof(OPENFILENAME);

    ofn.hwndOwner = NULL;          // 父窗口的句柄,这里设置为 NULL

    ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");  // 文件过滤器

    ofn.lpstrFile = szFile;                 // 用于接收文件路径的缓冲区

    ofn.nMaxFile = MAX_PATH;      // 缓冲区大小

    ofn.lpstrDefExt = TEXT("txt");     // 默认文件扩展名

    ofn.Flags = OFN_OVERWRITEPROMPT;  // 显示覆盖提示对话框

    // 显示存储文件对话框

    if (GetSaveFileName(&ofn))

    {

        // 用户点击了保存按钮,可以使用 ofn.lpstrFile 获取选择的文件路径

        MessageBox(NULL, ofn.lpstrFile, TEXT("Selected File"), MB_OK);

    }

    return 0;

}

以上代码首先初始化了 OPENFILENAME 结构体,并设置了相关的成员,如文件过滤器、文件路径缓冲区、默认文件扩展名等。然后,使用 GetSaveFileName 函数来显示存储文件对话框。如果用户点击了保存按钮并选择了文件路径,您可以通过 ofn.lpstrFile 获取选择的文件路径,并进行相应的处理。

查找和替换公用对话框

要使用公共文件对话框来进行查找和替换操作,您可以使用 FindText 和 ReplaceText 函数以及相应的结构体。以下是一个简单的示例代码,演示如何配置和使用公共文件对话框来进行查找和替换:

#include <windows.h>

#include <commdlg.h>

int main()

{

    // 初始化 FINDREPLACE 结构体

    FINDREPLACE fr = {0};

    TCHAR szFind[MAX_PATH] = {0};

    TCHAR szReplace[MAX_PATH] = {0};

    fr.lStructSize = sizeof(FINDREPLACE);

    fr.hwndOwner = NULL;  // 父窗口的句柄,这里设置为 NULL

    fr.lpstrFindWhat = szFind;  // 用于接收查找文本的缓冲区

    fr.wFindWhatLen = MAX_PATH;  // 缓冲区大小

    fr.lpstrReplaceWith = szReplace;  // 用于接收替换文本的缓冲区

    fr.wReplaceWithLen = MAX_PATH;  // 缓冲区大小

    fr.Flags = FR_DOWN;  // 查找方向为向下

    // 显示查找和替换对话框

    if (FindText(&fr))

    {

        // 用户点击了查找或替换按钮,可以使用 fr.lpstrFindWhat

//和 fr.lpstrReplaceWith 获取查找和替换文本

        MessageBox(NULL, fr.lpstrFindWhat, TEXT("Find Text"), MB_OK);

        MessageBox(NULL, fr.lpstrReplaceWith, TEXT("Replace Text"), MB_OK);

    }

    return 0;

}

以上代码首先初始化了 FINDREPLACE 结构体,并设置了相关的成员,如查找文本缓冲区、替换文本缓冲区等。然后,使用 FindText 函数来显示查找和替换对话框。如果用户点击了查找或替换按钮,您可以通过 fr.lpstrFindWhat 和 fr.lpstrReplaceWith 获取查找和替换文本,并进行相应的处理。

●以下是 FINDREPLACE 结构体的定义,每个成员都有相应的注释说明其作用和用法:

typedef struct tagFINDREPLACE {

    DWORD lStructSize;         // 结构体的大小,必须设置为 sizeof(FINDREPLACE)

    HWND   hwndOwner;                // 父窗口的句柄

    HINSTANCE   hInstance;             // 应用程序实例句柄

    DWORD Flags;                           // 选项标志

    LPCTSTR lpstrFindWhat;             // 查找文本的缓冲区

    LPCTSTR lpstrReplaceWith;         // 替换文本的缓冲区

    WORD    wFindWhatLen;            // 查找文本的缓冲区大小

    WORD    wReplaceWithLen;        // 替换文本的缓冲区大小

    LPARAM lCustData;           // 自定义数据

    LPFRHOOKPROC lpfnHook;       // 钩子函数

    LPCTSTR lpTemplateName;         // 自定义模板的资源名称

} FINDREPLACE, *LPFINDREPLACE;

选择字体公用对话框

要使用公共字体对话框来选择字体,您可以使用 ChooseFont 函数和 CHOOSEFONT 结构体。以下是一个简单的示例代码,展示如何配置和使用公共字体对话框来选择字体:

#include <windows.h>

#include <commdlg.h>

int main()

{

    // 初始化 CHOOSEFONT 结构体

    CHOOSEFONT cf = {0};

    LOGFONT lf = {0};

    cf.lStructSize = sizeof(CHOOSEFONT);

    cf.hwndOwner = NULL; // 父窗口的句柄,这里设置为 NULL

    cf.lpLogFont = &lf;      // 用于接收选择的字体信息的 LOGFONT 结构体指针

    cf.Flags = CF_SCREENFONTS | CF_EFFECTS;  // 显示屏幕字体和效果选项

    // 显示选择字体对话框

    if (ChooseFont(&cf))

    {

        // 用户点击了确定按钮,可以使用 lf 字段获取选择的字体信息

        MessageBox(NULL, lf.lfFaceName, TEXT("Selected Font"), MB_OK);

    }

    return 0;

}

以下是 CHOOSEFONT 结构体的定义,其中包含了选择字体对话框的相关配置信息:

typedef struct tagCHOOSEFONT {

    DWORD lStructSize;            // 结构体的大小,必须设置为 sizeof(CHOOSEFONT)

    HWND   hwndOwner;         // 父窗口的句柄

    HDC       hDC;                     // 设备上下文句柄

    LPLOGFONT  lpLogFont;     // 用于接收选择的字体信息的 LOGFONT 结构体指针

    INT         iPointSize;             // 字体大小(以 1/10 点为单位)

    DWORD Flags;                    // 选项标志

    COLORREF    rgbColors;     // 初始文本颜色和背景颜色

    LPARAM        lCustData       // 自定义数据

    LPCFHOOKPROC lpfnHook; // 钩子函数

    LPCTSTR lpTemplateName;  // 自定义模板的资源名称

    HINSTANCE    hInstance;  // 应用程序实例句柄

    LPTSTR   lpszStyle;               // 预定义样式列表

    WORD    nFontType;           // 字体类型标志

    WORD    ___MISSING_ALIGNMENT__; // 未使用

    INT          nSizeMin;     // 最小可选择的字体大小

    INT          nSizeMax;     // 最大可选择的字体大小

} CHOOSEFONT, *LPCHOOSEFONT;

选择颜色公用对话框

要使用公共颜色对话框来选择颜色,您可以使用 ChooseColor 函数和 CHOOSECOLOR 结构体。以下是一个简单的示例代码,展示如何配置和使用公共颜色对话框来选择颜色:

#include <windows.h>

#include <commdlg.h>

int main()

{

    // 初始化 CHOOSECOLOR 结构体

    CHOOSECOLOR cc = {0};

    COLORREF acrCustColors[16] = {0};

    cc.lStructSize = sizeof(CHOOSECOLOR);

    cc.hwndOwner = NULL;                   // 父窗口的句柄,这里设置为 NULL

    cc.lpCustColors = acrCustColors;      // 自定义颜色数组

    cc.Flags = CC_FULLOPEN | CC_RGBINIT;  // 全部颜色打开和初始颜色设置

    // 显示选择颜色对话框

    if (ChooseColor(&cc))

    {

        // 用户点击了确定按钮,可以使用 cc.rgbResult 获取选择的颜色

        COLORREF selectedColor = cc.rgbResult;

        MessageBox(NULL, TEXT("Selected Color"), TEXT("Selected Color"), MB_OK);

    }

    return 0;

}

以上代码首先初始化了 CHOOSECOLOR 结构体,并设置了相关的成员,如父窗口句柄、自定义颜色数组、显示选项等。然后,使用 ChooseColor 函数来显示选择颜色对话框。如果用户点击了确定按钮并选择了颜色,您可以通过 cc.rgbResult 获取选择的颜色,并进行相应的处理。

以下是 CHOOSECOLOR 结构体的定义,其中包含了选择颜色对话框的相关配置信息:

typedef struct tagCHOOSECOLOR {

    DWORD lStructSize;        // 结构体的大小,必须设置为 sizeof(CHOOSECOLOR)

    HWND   hwndOwner;         // 父窗口的句柄

    HWND   hInstance;             // 应用程序实例句柄

    COLORREF    rgbResult;      // 选择的颜色

    COLORREF*   lpCustColors; // 自定义颜色数组

    DWORD Flags;                    // 选项标志

    LPARAM        lCustData;      // 自定义数据

    LPCCHOOKPROC lpfnHook; // 钩子函数

    LPCTSTR lpTemplateName;  // 自定义模板的资源名称

} CHOOSECOLOR, *LPCHOOSECOLOR;

10.3.2 第68练:完善的POPPAD

■POPPAD.C

/*------------------------------------------------------------------------

 068 WIN32 API 每日一练

     第68个例子POPPAD.C:公用对话框-文本编辑器

     POPPAD.C  //主程序

     POPFILE.C //文件菜单处理

     POPFIND.C //SEARCH菜单处理

     POPFONT.C //FONT菜单处理

     POPPRINTO.C  //打印处理(第十三章讲述) 

 (c) www.bcdaren.com 编程达人

-----------------------------------------------------------------------*/

#include <windows.h>

#include <commdlg.h> //公用对话框库

#include "resource.h"

#define EDITID 1    //顶级菜单ID:FILE 0 ,EDIT 1,SEARCH 2,FORMAT 3,HELP 4

#define UNTITLED TEXT ("(untitled)")

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

BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;

 // Functions in POPFILE.C

void PopFileInitialize (HWND) ; //初始化File对话框

BOOL PopFileOpenDlg (HWND, PTSTR, PTSTR) ; //创建“打开”文件对话框

BOOL PopFileSaveDlg (HWND, PTSTR, PTSTR) ; //创建“保存”文件对话框

BOOL PopFileRead (HWND, PTSTR) ; //读文件

BOOL PopFileWrite (HWND, PTSTR) ; //写文件

 // Functions in POPFIND.C

HWND PopFindFindDlg (HWND) ;       //初始化Find对话框

HWND PopFindReplaceDlg (HWND) ;    //初始化FindReplace对话框

BOOL PopFindFindText (HWND, int *, LPFINDREPLACE) ; //查找字符串

BOOL PopFindReplaceText (HWND, int *, LPFINDREPLACE) ; //替换字符串

BOOL PopFindNextText (HWND, int *) ; //查找下一处

BOOL PopFindValidFind (void) ; //无效查找

 // Functions in POPFONT.C

void PopFontInitialize (HWND) ; //初始化对话框字体

BOOL PopFontChooseFont (HWND) ; //选择字体

void PopFontSetFont (HWND) ;       //设置字体

void PopFontDeinitialize (void) ;  //删除字体

 // Functions in POPPRNT.C

BOOL PopPrntPrintFile (HINSTANCE, HWND, HWND, PTSTR) ; //打印文件

 // Global 变量

static HWND hDlgModeless ; //通用对话框句柄

static TCHAR szAppName[] = TEXT ("PopPad") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{

     MSG msg;

     HWND hwnd;

     HACCEL hAccel;

     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 = (HBRUSH)GetStockObject(WHITE_BRUSH);

     wndclass.lpszMenuName = szAppName;

     wndclass.lpszClassName = szAppName;

     if (!RegisterClass(&wndclass))

     {

          MessageBox(NULL, TEXT("This program requires Windows NT!"),

               szAppName, MB_ICONERROR);

          return 0;

     }

     hwnd = CreateWindow(szAppName, NULL,

          WS_OVERLAPPEDWINDOW,

          CW_USEDEFAULT, CW_USEDEFAULT,

          CW_USEDEFAULT, CW_USEDEFAULT,

          NULL, NULL, hInstance, szCmdLine);

     ShowWindow(hwnd, iCmdShow);

     UpdateWindow(hwnd);

     hAccel = LoadAccelerators(hInstance, szAppName);

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

     {//对话框为空或不是对话框消息时

          if (hDlgModeless == NULL || !IsDialogMessage(hDlgModeless, &msg))

          {//如果加速键消息未被翻译过TranslateAccelerator函数返回值为0

               if (!TranslateAccelerator(hwnd, hAccel, &msg))

               {

                    TranslateMessage(&msg);

                    DispatchMessage(&msg);

               }

          }

     }

     return msg.wParam;

}

//设置标题

void DoCaption (HWND hwnd, TCHAR * szTitleName)

{

     TCHAR szCaption[64 + MAX_PATH];

     wsprintf(szCaption, TEXT("%s - %s"), szAppName,

          szTitleName[0] ? szTitleName : UNTITLED);

     SetWindowText(hwnd, szCaption);

}

//向用户显示消息框提示信息

void OkMessage (HWND hwnd, TCHAR * szMessage, TCHAR * szTitleName)

{

     TCHAR szBuffer[64 + MAX_PATH];

     wsprintf(szBuffer, szMessage, szTitleName[0] ? szTitleName : UNTITLED);

     MessageBox(hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION);

}

// 是否保存文件

short AskAboutSave (HWND hwnd, TCHAR * szTitleName)

{

     TCHAR szBuffer[64 + MAX_PATH];

     int iReturn;

     wsprintf(szBuffer, TEXT("Save current changes in %s?"),

          szTitleName[0] ? szTitleName : UNTITLED);

     iReturn = MessageBox(hwnd, szBuffer, szAppName,

          MB_YESNOCANCEL | MB_ICONQUESTION);

     if (iReturn == IDYES)

          if (!SendMessage(hwnd, WM_COMMAND, IDM_FILE_SAVE, 0))//IDM_FILE_SAVE返回0为失败,1成功

               iReturn = IDCANCEL;//YES但保存失败

     return iReturn;

}

//主窗口过程

LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, WPARAM wParam,LPARAM

lParam)

{

      static BOOL bNeedSave = FALSE ;

      static HINSTANCE hInst ;

      static HWND hwndEdit ;

      static int iOffset ;

//完全路径文件名缓冲区和文件名缓冲区

      static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH] ;

      static UINT messageFindReplace ;

      int iSelBeg, iSelEnd, iEnable ;

      LPFINDREPLACE pfr ;

      switch (message)

      {

      case WM_CREATE:

           hInst = ((LPCREATESTRUCT) lParam) -> hInstance ;

           // 创建编辑控件子窗口

           hwndEdit = CreateWindow (TEXT ("edit"), NULL,

                WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |

                WS_BORDER | ES_LEFT | ES_MULTILINE |

//ES_NOHIDESEL反转所选文本

                ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,

                0, 0, 0, 0,

                hwnd, (HMENU) EDITID, hInst, NULL) ;

          //设置文本编辑控件的最大字符数,0L为long类型常量0

           SendMessage (hwndEdit, EM_LIMITTEXT, 32000, 0L) ;

           // 初始化公用对话框

           PopFileInitialize (hwnd) ;//初始化文件公用对话框

           PopFontInitialize (hwndEdit) ;  //创建字体

/*定义一个新的窗口消息,仅当多个应用程序必须处理同一条消息时才使用RegisterWindowMessage。“查找或替换”对话框会将 FINDMSGSTRING 注册的消息发送到其所有者窗口的窗口过程。*/

           messageFindReplace = RegisterWindowMessage (FINDMSGSTRING) ;

           DoCaption (hwnd, szTitleName) ; //窗口标题栏显示文件名

           return 0 ;

      case WM_SETFOCUS:

           SetFocus(hwndEdit);//设置焦点

           return 0;

     case WM_SIZE:

          MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam),TRUE);

          return 0;

     //当下拉菜单或子菜单即将变为活动状态时发送

      case WM_INITMENUPOPUP:

      switch (lParam)

      {

      case 1: // Edit 菜单

           // 如果有撤销操作,启用“Undo”菜单

            //启用,禁用或显示指定的菜单项

           EnableMenuItem ((HMENU) wParam, IDM_EDIT_UNDO,

           SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?

           MF_ENABLED : MF_GRAYED) ;

           // 如果文本在剪贴板中,则启用粘贴

           EnableMenuItem ((HMENU) wParam, IDM_EDIT_PASTE,

           IsClipboardFormatAvailable (CF_TEXT) ? //剪贴板是否有内容

           MF_ENABLED : MF_GRAYED) ;

           //如果有选中文本字符串,启用剪切、复制和删除选中的文本

//获取选定文本的位置信息

           SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iSelBeg,

           (LPARAM) &iSelEnd) ;

          //如果开始位置等于结束位置,禁用菜单

           iEnable = iSelBeg != iSelEnd ? MF_ENABLED : MF_GRAYED ;

           EnableMenuItem ((HMENU) wParam, IDM_EDIT_CUT,iEnable) ;

           EnableMenuItem ((HMENU) wParam, IDM_EDIT_COPY,iEnable) ;

           EnableMenuItem ((HMENU) wParam, IDM_EDIT_CLEAR,iEnable) ;

           break ;

      case 2: // Search 菜单 

           //如果非模态对话框==NULL时,激活菜单

           iEnable = hDlgModeless == NULL ? MF_ENABLED : MF_GRAYED ;

           EnableMenuItem ((HMENU) wParam, IDM_SEARCH_FIND,iEnable) ;

           EnableMenuItem ((HMENU) wParam, IDM_SEARCH_NEXT, iEnable) ;

           EnableMenuItem ((HMENU) wParam, IDM_SEARCH_REPLACE, iEnable) ;

           break ;

           }

           return 0 ;

      case WM_COMMAND:

           // 处理"EDIT"控件消息

           if (lParam && LOWORD (wParam) == EDITID)

           {

           switch (HIWORD (wParam)) //控件通知码

           { //当编辑控件即将重绘时发送。

//在控件格式化文本之后但在显示文本之前发送此通知代码。

           case EN_UPDATE :

                bNeedSave = TRUE ;

                return 0 ;

           case EN_ERRSPACE : //空间不足

           case EN_MAXTEXT :

                MessageBox(hwnd, TEXT("Edit control out of space."),

                     szAppName, MB_OK | MB_ICONSTOP);

                return 0;

           }

           break ;

           }

          switch (LOWORD (wParam)) //加速键ID或菜单ID,这里两个ID相等

           {

           //处理"FILE"菜单消息

           case IDM_FILE_NEW:

            //保存旧文件,如果保存时失败,则什么都不做,直接返回。

                if (bNeedSave && IDCANCEL == AskAboutSave

                (hwnd, szTitleName))

                     return 0;

               //清除编辑框内容

                SetWindowText(hwndEdit, TEXT("\0"));//设置标题栏缓冲区为空

                szFileName[0] = '\0';//设置文件名缓冲区为空

                szTitleName[0] = '\0';//设置标题缓冲区为空

                DoCaption(hwnd, szTitleName);//显示标题栏

                bNeedSave = FALSE;

                return 0;

           case IDM_FILE_OPEN:

               //保存旧文件,如果保存时失败,则什么都不做,直接返回。

                if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, szTitleName))

                     return 0;

                if (PopFileOpenDlg(hwnd, szFileName, szTitleName))

                {

                     if (!PopFileRead(hwndEdit, szFileName))

                     {

                          OkMessage(hwnd, TEXT("Could not read file %s!"),

                               szTitleName);

                          szFileName[0] = '\0';

                          szTitleName[0] = '\0';

                     }

                }

                DoCaption(hwnd, szTitleName);

                bNeedSave = FALSE;

                return 0;

          case IDM_FILE_SAVE:

               if (szFileName[0])

               {

                    if (PopFileWrite(hwndEdit, szFileName))

                    {

                         bNeedSave = FALSE;

                         return 1;

                    }

                    else

                    {

                         OkMessage(hwnd, TEXT("Could not write file %s"),

                              szTitleName);

                         return 0;

                    }

               }

           //继续往下执行

           case IDM_FILE_SAVE_AS:

                if (PopFileSaveDlg(hwnd, szFileName, szTitleName))

                {

                     DoCaption(hwnd, szTitleName);

                     if (PopFileWrite(hwndEdit, szFileName))

                     {

                          bNeedSave = FALSE;

                          return 1;

                     }

                     else

                     {

                          OkMessage(hwnd, TEXT("Could not write file %s"),

                               szTitleName);

                          return 0;

                     }

                }

                return 0;

          case IDM_FILE_PRINT:

               if (!PopPrntPrintFile(hInst, hwnd, hwndEdit,

                    szTitleName))

                    OkMessage(hwnd, TEXT("Could not print file %s"),

                         szTitleName);

               return 0;

           case IDM_APP_EXIT:

                SendMessage(hwnd, WM_CLOSE, 0, 0);

                return 0;

           // Edit 菜单消息 

           case IDM_EDIT_UNDO:

                SendMessage (hwndEdit, WM_UNDO, 0, 0) ;

                return 0 ;

           case IDM_EDIT_CUT:

                SendMessage (hwndEdit, WM_CUT, 0, 0) ;

                return 0 ;

           case IDM_EDIT_COPY:

                SendMessage(hwndEdit, WM_COPY, 0, 0);

                return 0;

           case IDM_EDIT_PASTE:

                SendMessage (hwndEdit, WM_PASTE, 0, 0) ;

                return 0 ;

           case IDM_EDIT_CLEAR:

                SendMessage(hwndEdit, WM_CLEAR, 0, 0);

                return 0;

           case IDM_EDIT_SELECT_ALL:

                SendMessage(hwndEdit, EM_SETSEL, 0, -1);

                return 0;

           // Search 菜单消息

          case IDM_SEARCH_FIND:

            //查找将从iOffset位置开始(首获取选中文本后面的位置iOffset)

               SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);

               hDlgModeless = PopFindFindDlg(hwnd);

               return 0;

           case IDM_SEARCH_NEXT:

                SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);

                if (PopFindValidFind())

                     PopFindNextText(hwndEdit, &iOffset);

                else

                     hDlgModeless = PopFindFindDlg(hwnd);

                return 0;

           case IDM_SEARCH_REPLACE:

                SendMessage (hwndEdit, EM_GETSEL, 0, (LPARAM) &iOffset) ;

                hDlgModeless = PopFindReplaceDlg (hwnd) ;

                return 0 ;

           case IDM_FORMAT_FONT:

                if (PopFontChooseFont(hwnd))

                     PopFontSetFont(hwndEdit);

           return 0 ;

           // Help菜单消息

           case IDM_HELP:

                OkMessage(hwnd, TEXT("Help not yet implemented!"),

                     TEXT("\0"));

                return 0;

           case IDM_APP_ABOUT:

                DialogBox(hInst, TEXT("AboutBox"), hwnd, AboutDlgProc);

                return 0 ;

          }

           break ;

      case WM_CLOSE:

           if (!bNeedSave || IDCANCEL != AskAboutSave (hwnd, szTitleName))

               DestroyWindow (hwnd) ;

           return 0 ;

     //结束会话或者系统关机发送的消息

      case WM_QUERYENDSESSION :

           if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, szTitleName))

                return 1;//结束

           return 0;//不结束

      case WM_DESTROY:

           PopFontDeinitialize();

           PostQuitMessage(0);

           return 0;

      default:

           //处理“查找”、“替换”发送的特殊消息

           if (message == messageFindReplace)

           {

                pfr = (LPFINDREPLACE)lParam;

               //用户点击了“取消”按钮

                if (pfr->Flags & FR_DIALOGTERM)

                     hDlgModeless = NULL;

               //用户点击了“查找下一个”按钮

                if (pfr->Flags & FR_FINDNEXT)

                     if (!PopFindFindText(hwndEdit, &iOffset, pfr))

                          OkMessage(hwnd, TEXT("Text not found!"), TEXT("\0"));

               //用户点击了“替换”或“替换全部”

                if (pfr->Flags & FR_REPLACE || pfr->Flags & FR_REPLACEALL)

                     if (!PopFindReplaceText(hwndEdit, &iOffset, pfr))

                          OkMessage(hwnd, TEXT("Text not found!"), TEXT("\0"));

                if (pfr->Flags & FR_REPLACEALL)

                     while (PopFindReplaceText(hwndEdit, &iOffset, pfr));

                return 0;

           }

           break ;

          }

     return DefWindowProc (hwnd, message, wParam, lParam) ;

}

//About模态对话框窗口过程

BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam)

{

     switch (message)

     {

     case WM_INITDIALOG:

          return TRUE;

     case WM_COMMAND:

          switch (LOWORD(wParam))

          {

          case IDOK:

               EndDialog(hDlg, 0);

               return TRUE;

          }

          break;

     }

     return FALSE;

}

■POPFILE.C

/*--------------------------------------------------------------------------

 POPFILE.C -- Popup Editor File Functions

 ------------------------------------------------------------------------*/

#include <windows.h>

#include <commdlg.h>

static OPENFILENAME ofn ;

//初始化对话框

void PopFileInitialize (HWND hwnd)

{

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

           TEXT("ASCII Files (*.ASC)\0*.asc\0") \

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

      ofn.lStructSize = sizeof (OPENFILENAME) ; //结构体的大小

      ofn.hwndOwner = hwnd ; //所属窗口,可以为NULL

      ofn.hInstance = NULL ; //对话框模板或模块句柄,ofn.Flags字段相关

      ofn.lpstrFilter = szFilter ; //文件筛选字符串

      ofn.lpstrCustomFilter = NULL ; //缓冲区,保留用户选择的过滤样式

      ofn.nMaxCustFilter = 0 ; //以TCHAR为单位的缓冲大小

      ofn.nFilterIndex = 0 ; //当前选择的过滤器的索引

      ofn.lpstrFile = NULL ; // 在打开和关闭函数中设置,全路径文件名缓冲区

      ofn.nMaxFile = MAX_PATH ;

// 在打开和关闭函数中设置,接收不含路径的文件名的缓冲区

      ofn.lpstrFileTitle = NULL ;

      ofn.nMaxFileTitle = MAX_PATH ;

      ofn.lpstrInitialDir = NULL ; //在这个字符串中指定初始目录

      ofn.lpstrTitle = NULL ; //对话框标题,默认为“打开”或“保存”

      //  在打开和关闭函数中设置,,对话框不同行为的标志,只读,多选,覆盖等

ofn.Flags = 0;

      ofn.nFileOffset = 0 ; //返回文件名字符串中,文件名的起始位置

      ofn.nFileExtension = 0 ; //扩展名在字符串中的起始位置

      ofn.lpstrDefExt = TEXT ("txt") ; //指定默认的扩展名

//系统传递给由lpfnHook成员标识的hook过程的应用程序定义的数据

      ofn.lCustData = 0L ;

      ofn.lpfnHook = NULL ; //指向一个钩子程序

      ofn.lpTemplateName = NULL ; //是对话框模板资源

}

//创建一个“打开”文件对话框

BOOL PopFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)

{

     ofn.hwndOwner = hwnd;

     ofn.lpstrFile = pstrFileName;//全路径文件名

     ofn.lpstrFileTitle = pstrTitleName;//文件名(含扩展名)

//隐藏只读复选框,如果文件不存在,则创建文件

     ofn.Flags = OFN_HIDEREADONLY | OFN_CREATEPROMPT;

//创建一个“打开”文件对话框,该对话框允许用户指定驱动器,

//目录以及要打开的文件或文件集的名称。

     return GetOpenFileName(&ofn);

}

//创建一个“保存”文件对话框

BOOL PopFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)

{

     ofn.hwndOwner = hwnd;

     ofn.lpstrFile = pstrFileName;

     ofn.lpstrFileTitle = pstrTitleName;

//如果所选文件已存在,则使 “另存为”对话框生成一个消息框。

//用户必须确认是否覆盖文件。

     ofn.Flags = OFN_OVERWRITEPROMPT;

//创建一个“保存”对话框,该对话框允许用户指定要保存的文件的驱动器,目录和名称。

     return GetSaveFileName(&ofn);

}

//读取文件

BOOL PopFileRead (HWND hwndEdit, PTSTR pstrFileName)

{

      BYTE bySwap ;

      DWORD dwBytesRead ;

      HANDLE hFile ;

      int i, iFileLength, iUniTest ;

      PBYTE pBuffer, pText, pConv ;

      // 打开文件

      if (INVALID_HANDLE_VALUE ==

           (hFile = CreateFile(pstrFileName, GENERIC_READ,

                FILE_SHARE_READ,

                NULL, OPEN_EXISTING, 0, NULL)))

           return FALSE;

      // 获取文件大小,以字节为单位,并为读取分配内存。

      iFileLength = GetFileSize (hFile, NULL) ;

      pBuffer = malloc (iFileLength + 2) ; //多出两个字节存放两个'\0'

      //读文件到缓冲区,并在文件末尾放\0结束符

      ReadFile (hFile, pBuffer, iFileLength, &dwBytesRead, NULL) ;

      CloseHandle (hFile) ;

      pBuffer[iFileLength] = '\0' ;

      pBuffer[iFileLength + 1] = '\0' ;

      //测试文本是否是Unicode编码,前两个字节为0xFEFF或0xFFFE

      //IS_TEXT_UNICODE_SIGNATURE——0xFEFF(小端:高高低低)

      //IS_TEXT_UNICODE_REVERSE_SIGNATURE——0xFFFE(大端)

     iUniTest = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE ;

     if (IsTextUnicode (pBuffer, iFileLength, &iUniTest))

     {

          pText = pBuffer + 2;//跳过前两个字节,指向正文部分

          iFileLength -= 2;

//如果大端存储,调换字节顺序

          if (iUniTest & IS_TEXT_UNICODE_REVERSE_SIGNATURE)

          {

               for (i = 0; i < iFileLength / 2; i++)

               {

                    bySwap = ((BYTE *)pText)[2 * i];

                    ((BYTE *)pText)[2 * i] = ((BYTE *)pText)[2 * i + 1];

                    ((BYTE *)pText)[2 * i + 1] = bySwap;

               }

      }

      //为可能的字符串转换分配内存

      pConv = malloc (iFileLength + 2) ;

      //Edit控件使用Unicode,则显示之前将Unicode文本转化为多字节文本

     #ifndef UNICODE

      WideCharToMultiByte (CP_ACP, 0, (PWSTR) pText, -1, pConv,

           iFileLength + 2, NULL, NULL) ; //共iFileLength+2字节,含2个\0

      //Edit控件是非Unicode,则直接拷贝文本

     #else

      lstrcpy ((PTSTR) pConv, (PTSTR) pText) ;

     #endif

      }

      else //非Unicode文件

      {

           pText = pBuffer ;

           //ASCII转Unicode,需2倍的空间。额外加两个\0。

           pConv = malloc (2 * iFileLength + 2) ;

           // 如果编辑控件是Unicode,则转换ASCII文本。

          #ifdef UNICODE

           MultiByteToWideChar (CP_ACP, 0, pText, -1, (PTSTR) pConv,

           iFileLength + 1) ;

           // 如果不是,则直接拷贝

          #else

           lstrcpy ((PTSTR) pConv, (PTSTR) pText) ;

          #endif

      }

      SetWindowText (hwndEdit, (PTSTR) pConv) ; //将内容写入到编辑框

      free (pBuffer) ;

      free (pConv) ;

      return TRUE ;

}

//写文件

BOOL PopFileWrite (HWND hwndEdit, PTSTR pstrFileName)

{

      DWORD dwBytesWritten ;

      HANDLE hFile ;

      int iLength ;

      PTSTR pstrBuffer ;

//小端模式时,前两个字节被写入FF FE。大端时被写入FE FF

      WORD wByteOrderMark = 0xFEFF ;

      //打开文件,必要时可创建文件 

      if (INVALID_HANDLE_VALUE ==

           (hFile = CreateFile(pstrFileName, GENERIC_WRITE, 0,

                NULL, CREATE_ALWAYS, 0, NULL)))

           return FALSE;

      //获取编辑框中的字符个数,并分配内存

      iLength = GetWindowTextLength (hwndEdit) ;

      pstrBuffer = (PTSTR) malloc ((iLength + 1) * sizeof (TCHAR)) ;

      if (!pstrBuffer)

      {

           CloseHandle(hFile);

           return FALSE;

      }

      // 如果编辑框使用Unicode编码,则写入Unicode字节序

     #ifdef UNICODE

      WriteFile (hFile, &wByteOrderMark, 2, &dwBytesWritten, NULL) ;

     #endif

      //获取编辑框中的文本,并输出到文件

      GetWindowText (hwndEdit, pstrBuffer, iLength + 1) ;

      WriteFile (hFile, pstrBuffer, iLength * sizeof (TCHAR),

      &dwBytesWritten, NULL) ;

      if ((iLength * sizeof (TCHAR)) != (int) dwBytesWritten)

      {

           CloseHandle(hFile);

           free(pstrBuffer);

           return FALSE;

      } 

      CloseHandle (hFile) ;

      free (pstrBuffer) ;

      return TRUE ;

}

■POPFIND.C

/*--------------------------------------------------------------------------

 POPFIND.C -- Popup Editor Search and Replace Functions

 ------------------------------------------------------------------------*/

#include <windows.h>

#include <commdlg.h>

#include <tchar.h> // for _tcsstr (strstr for Unicode & non-Unicode)

#define MAX_STRING_LEN 256

static TCHAR szFindText [MAX_STRING_LEN] ;

static TCHAR szReplText [MAX_STRING_LEN] ;

//初始化Find对话框

HWND PopFindFindDlg (HWND hwnd)

{

      static FINDREPLACE fr ; // 非模态对话框必须是静态的!!

      fr.lStructSize = sizeof (FINDREPLACE) ; //结构的长度(以字节为单位)。

      fr.hwndOwner = hwnd ;   //拥有对话框的窗口的句柄。

      fr.hInstance = NULL ;

//隐藏搜索方向单选按钮,隐藏“区分大小写”复选框,

      fr.Flags = FR_HIDEUPDOWN | FR_HIDEMATCHCASE |

                    FR_HIDEWHOLEWORD ; //隐藏“仅匹配整个单词”复选框

      fr.lpstrFindWhat = szFindText ; //键入的搜索字符串缓冲区的长度

      fr.lpstrReplaceWith = NULL; //键入的替换字符串缓冲区的长度,

               //如果FINDMSGSTRING消息指定FR_REPLACE或FR_REPLACEALL标志,

               //则lpstrReplaceWith包含替换字符串,该FINDTEXT函数忽略这个成员。

      //lpstrFindWhat成员指向的缓冲区的长度(以字节为单位)。

fr.wFindWhatLen = MAX_STRING_LEN ;

 //lpstrReplaceWith成员指向的缓冲区的长度(以字节为单位)。

      fr.wReplaceWithLen = 0 ;

      fr.lCustData = 0 ; //Hook过程的应用程序定义的数据

//指向FRHookProc Hook过程的指针,该过程可以处理用于对话框的消息。

      fr.lpfnHook = NULL ;

     fr.lpTemplateName = NULL;//hInstance成员标识的模块中对话框模板资源的名称。

      return FindText (&fr) ; //创建查找对话框并返回其句柄

}

//初始化FindReplace对话框

HWND PopFindReplaceDlg (HWND hwnd)

{

      static FINDREPLACE fr ; // 非模态对话框必须是静态的!!

      fr.lStructSize = sizeof (FINDREPLACE) ;

      fr.hwndOwner = hwnd ;

      fr.hInstance = NULL ;

      fr.Flags = FR_HIDEUPDOWN | FR_HIDEMATCHCASE |

               FR_HIDEWHOLEWORD ;

      fr.lpstrFindWhat = szFindText ;

      fr.lpstrReplaceWith = szReplText ;

      fr.wFindWhatLen = MAX_STRING_LEN ;

      fr.wReplaceWithLen = MAX_STRING_LEN ;

      fr.lCustData = 0 ;

      fr.lpfnHook = NULL ;

      fr.lpTemplateName = NULL ;

      return ReplaceText (&fr) ;

}

//查找字符串

BOOL PopFindFindText (HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)

{

      int iLength, iPos ;

      PTSTR pstrDoc, pstrPos ; //文件指针和当前位置指针

      //读取编辑框内容

      iLength = GetWindowTextLength (hwndEdit) ;

      if (NULL == (pstrDoc = (PTSTR) malloc ((iLength + 1) * sizeof (TCHAR))))

          return FALSE ;

      GetWindowText (hwndEdit, pstrDoc, iLength + 1) ;

      // 在文档中搜索查找字符串

      pstrPos = _tcsstr (pstrDoc + * piSearchOffset, pfr->lpstrFindWhat) ;

      free (pstrDoc) ;

      //如果找不到,返回FALSE 

      if (pstrPos == NULL)

          return FALSE ;

      //找到字符串,将偏移设置到新的位置 

      iPos = pstrPos - pstrDoc ;

//偏移设到找到的字符串的后面。

      * piSearchOffset = iPos + lstrlen (pfr->lpstrFindWhat) ;

      //选中找到的文本

      SendMessage (hwndEdit, EM_SETSEL, iPos, * piSearchOffset) ;

//可视窗口滚动到插入符号的位置,以便可见找到的文本。

      SendMessage (hwndEdit, EM_SCROLLCARET, 0, 0) ;

      return TRUE ;

}

//查找下一处

BOOL PopFindNextText (HWND hwndEdit, int * piSearchOffset)

{

     FINDREPLACE fr;

     fr.lpstrFindWhat = szFindText;

     return PopFindFindText(hwndEdit, piSearchOffset, &fr);

}

//替换文本字符串

BOOL PopFindReplaceText (HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)

{

      //查找文本

      if (!PopFindFindText (hwndEdit, piSearchOffset, pfr))

          return FALSE ;

      // 替换

      SendMessage ( hwndEdit, EM_REPLACESEL, 0, (LPARAM) pfr->

     lpstrReplaceWith) ;

          return TRUE ;

}

//无效查找

BOOL PopFindValidFind (void)

{

      return * szFindText != '\0' ; //没输入查找文本时,是无效的查找。

}

■POPFONT.C

/*----------------------------------------------------

 POPFONT.C -- Popup Editor Font Functions

------------------------------------------------------*/

#include <windows.h>

#include <commdlg.h>

static LOGFONT logfont ; //字体的属性结构变量

static HFONT hFont ;

//选择字体

BOOL PopFontChooseFont (HWND hwnd)

{

      CHOOSEFONT cf ; //包含ChooseFont函数用来初始化“字体”对话框的信息。用户

//关闭对话框后,系统将在此结构中返回有关用户选择的信息。

      cf.lStructSize = sizeof (CHOOSEFONT) ; //结构的长度,以字节为单位。

      cf.hwndOwner = hwnd ; //拥有对话框的窗口的句柄。

      cf.hDC = NULL ;       //忽略

      cf.lpLogFont = &logfont ; //指向LOGFONT结构的指针 。

      cf.iPointSize = 0 ; //选择的字体的大小,单位是1/10磅

//用logfont初始化对话框,屏幕字体、效果复选框

      cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS |

               CF_EFFECTS ;

      cf.rgbColors = 0 ; //文本颜色

      cf.lCustData = 0 ;

      cf.lpfnHook = NULL ;

      cf.lpTemplateName = NULL ;

      cf.hInstance = NULL ;

      cf.lpszStyle = NULL ; //字体样式

      cf.nFontType = 0 ; // 所选的字体

      cf.nSizeMin = 0 ; //用户可以选择的最小点数

      cf.nSizeMax = 0 ; //用户可以选择的最大点数

      return ChooseFont (&cf) ;

}

//初始化对话框字体

void PopFontInitialize (HWND hwndEdit)

{

     GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), //获取系统字体

          (PTSTR)&logfont);

     hFont = CreateFontIndirect(&logfont);   //创建字体

    SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hFont,0);//初始化对话框为系统字体

}

//设置字体

void PopFontSetFont (HWND hwndEdit)

{

     HFONT hFontNew;

     RECT rect;

     hFontNew = CreateFontIndirect(&logfont);

     SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hFontNew, 0);//改变对话框字体

     DeleteObject(hFont);

     hFont = hFontNew;

     GetClientRect(hwndEdit, &rect);

     InvalidateRect(hwndEdit, &rect, TRUE);

}

//删除字体

void PopFontDeinitialize (void)

{

      DeleteObject (hFont) ;

}

■POPPRINTO.C

/*------------------------------------------------------------------------

 POPPRNTO.C -- Popup Editor Printing Functions (dummy version)

--------------------------------------------------------------------------*/

#include <windows.h>

BOOL PopPrntPrintFile ( HINSTANCE hInst, HWND hwnd, HWND hwndEdit,

 PTSTR pstrTitleName)

{

     return FALSE ;

}

       ■资源脚本文件068_POPPAD3.rc

包含一个快捷键资源、对话框资源、ICON图标资源和菜单资源。

/

//

// Icon

//

// Icon with lowest ID value placed first to ensure application icon

// remains consistent on all systems.

PopPad                  ICON                    "favicon.ico"

/

//

// Menu

//

PopPad MENU

BEGIN

    POPUP "&FILE"

    BEGIN

        MENUITEM "&NEW\tCtrl+N",         IDM_FILE_NEW

        MENUITEM "&OPEN...\tCtrl+O",     IDM_FILE_OPEN

        MENUITEM "&SAVE\tCtrl+S",          IDM_FILE_SAVE

        MENUITEM "SAVE &AS...",              IDM_FILE_SAVE_AS

        MENUITEM SEPARATOR

        MENUITEM "&PRINT\tCtrl+P",         IDM_FILE_PRINT

        MENUITEM SEPARATOR

        MENUITEM "E&XIT",                        IDM_APP_EXIT

    END

    POPUP "&EDIT"

    BEGIN

        MENUITEM "&UNDO\tCtrl+Z",            IDM_EDIT_UNDO

        MENUITEM SEPARATOR

        MENUITEM "CU&T\tCtrl+X",                IDM_EDIT_CUT

        MENUITEM "&COPY\tCtrl+C",              IDM_EDIT_COPY

        MENUITEM "&PASTE\tCtrl+V",              IDM_EDIT_PASTE

        MENUITEM "DE&LETE\tDEL",               IDM_EDIT_CLEAR

        MENUITEM SEPARATOR

        MENUITEM "&SELECT ALL",                  IDM_EDIT_SELECT_ALL

    END

    POPUP "&SEARCH"

    BEGIN

        MENUITEM "&FIND...\tCtrl+F",                IDM_SEARCH_FIND

        MENUITEM "FIND &NEXT\tF3",                IDM_SEARCH_NEXT

        MENUITEM "&REPLEACE...\tCtrl+R",       IDM_SEARCH_REPLACE

    END

    POPUP "F&ORMAT"

    BEGIN

        MENUITEM "&FONT...",                    IDM_FORMAT_FONT

    END

    POPUP "&HELP"

    BEGIN

        MENUITEM "&HELP",                         IDM_HELP

        MENUITEM "&ABOUT POPPAD...",    IDM_APP_ABOUT

    END

END

/

//

// Dialog

//

ABOUTBOX DIALOGEX 32, 32, 309, 177

STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU

FONT 8, "MS Shell Dlg", 400, 0, 0x1

BEGIN

    DEFPUSHBUTTON   "确定",IDOK,122,156,50,14

    ICON            "PopPad",IDC_STATIC,15,12,20,20

    CTEXT           "POPPAD",IDC_STATIC,113,28,58,8

    CTEXT           "PopPad Editor for Windows",IDC_STATIC,93,68,119,8

    CTEXT           "(C) Charles Petzold,1998",IDC_STATIC,91,88,115,8

END

PRINTDLGBOX DIALOGEX 0, 0, 309, 176

STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU

CAPTION "POPPAD"

FONT 8, "MS Shell Dlg", 400, 0, 0x1

BEGIN

    PUSHBUTTON      "取消",IDCANCEL,127,155,50,14

    CTEXT           "Sending",IDC_STATIC,113,24,72,8

    LTEXT           "",IDC_STATIC,30,48,246,72

    CTEXT           "to print spooler.",IDC_STATIC,116,138,72,8

END

/

//

// Accelerator

//

IDR_ACCELERATOR1 ACCELERATORS

BEGIN

    VK_BACK,        IDM_EDIT_UNDO,           VIRTKEY, ALT, NOINVERT

    VK_DELETE,      IDM_EDIT_CLEAR,       VIRTKEY, NOINVERT

    VK_F1,          IDM_HELP,                      VIRTKEY, NOINVERT

    VK_F3,          IDM_SEARCH_NEXT,    VIRTKEY, NOINVERT

    VK_INSERT,      IDM_EDIT_COPY,       VIRTKEY, CONTROL, NOINVERT

    "C",            IDM_EDIT_COPY,                VIRTKEY, NOINVERT

    "F",            IDM_SEARCH_FIND,            VIRTKEY, NOINVERT

    "N",            IDM_FILE_NEW,                   VIRTKEY, NOINVERT

    "P",            IDM_FILE_PRINT,                   VIRTKEY, NOINVERT

    "R",            IDM_SEARCH_REPLEACE,    VIRTKEY, NOINVERT

    "S",            IDM_FILE_SAVE,                    VIRTKEY, NOINVERT

    "V",            IDM_EDIT_PASTE,                  VIRTKEY, NOINVERT

    "X",            IDM_EDIT_CUT,                   VIRTKEY, NOINVERT

    "Z",            IDM_EDIT_UNDO,                 VIRTKEY, NOINVERT

END

       ■运行结果:

图10-13 公用对话框——文本编辑器

 

总结

实例POPPAD程序加入菜单时,并没有实现几种标准菜单项。现在我们有了充分的准备可以实现POPPAD中打开文件、读取文件、存储文件的程序逻辑。在此过程中,我们还将添加选择字体和査找并替换文本的程序逻辑。

为避免重复第十三章的源代码,在POPPAD3.C的菜单定义中加上了打印选项以及其他一些相关代码。

POPPAD.C包含程序的所有基本源代码。

POPFILE.C中包含了激活打开文件和存储文件对话框的代码,以及文件I/O例程。

POPFIND.C包含了査找和替换文本的程序逻辑。

POPFONT.C包含了选择字体的程序逻辑。

POPPRNTO.C没有实质功能,它将在第十三章被POPPRNT.C所替换,并完成最终的POPPAD程序。

【注意】实例POPPAD程序中关于公用对话框初始化的部分可以被简化,直接将相应的公用对话框结构体初始化为零,然后再初始化几个必要的字段就可以了(参见上一节)。

●Unicode文件的判断——IsTextUnicode(lpBuffer,cb, lpi)

1.lpBuffer参数:要测试的字符串,其缓冲区地址。

2.cb个参数:lpBuffer指向的字节数(注意是不是字符数)

3.lpi:是个in/out类型的,传入时指定哪些测试项目,传出时为符合哪个测试项目。

4.返回值:TRUE或FALSE

●字符串的转化——这里的多字节是广义的,即可指ANSI,也可指UTF_8等。

 1.WideCharToMultiByte——将Unicode字符串转为多字节字符串

字段

功能

CodePage

CodePage参数用于标识要为转换新的字符串的相关代码页,如CP_ACP实现了Unicode与ANSI的转换;CP_UTF8 实现了Unicode与UTF-8的转换

dwFlags

进行额外的控制,会影响使用了读音符号(比如重音)的字符

lpWideCharStr

转换为宽字节字符串的缓冲区

cchWideChar

lpWideCharStr指向的缓冲区的字符个数。如果-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度(含\0)。

lpMultiByteStr

接收被转换字符串的缓冲区

cchMultiByte

lpMultiByteStr指向的缓冲区最大值(用字节来计量)

lpDefaultChar

遇到一个不能转换的宽字符,函数便会使用该参数指向的字符。

pfUsedDefaultChar

只要遇到任何一个不能被转换的字符,就会被函数设为TRUE。

2.MultiByteToWideChar——将多字节字符串转为Unicode字符串

字段

功能

CodePage

用来标记与一个多字节字符串相关的代码页

dwFlags

进行额外的控制,会影响使用了读音符号(比如重音)的字符

lpWideCharStr

转换为宽字节字符串的缓冲区

cchWideChar

lpWideCharStr指向的缓冲区的字符个数,如果-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度(含\0)。

lpMultiByteStr

接收被转换字符串的缓冲区

cchMultiByte

lpMultiByteStr指向的缓冲区最大值(用字节来计量)

lpDefaultChar

遇到一个不能转换的宽字符,函数便会使用该参数指向的字符。

pfUsedDefaultChar

只要遇到任何一个不能被转换的字符,就会被函数设为TRUE。

●查找和替换公用对话框

1.对话框是非模态的,所以消息循环应该调用IsDialogMessage。

2.FINDREPLACE结构不能声明为窗口过程的局部变量,必须是静态变量或全局变量。因为当调用FindText或ReplaceText调出对话框后,PopFindFindDlg(PopFindReplaceDlg)这些函数会立即返回。但该结构会作为消息的lParam参数被发送到父窗口的消息过程。为防止该结构被释放,要声明为静态变量。

3.“查找”或“替换”对话框与父窗口会进行一种特殊的消息进行通信。

所以程序首先须通过FINDMSGSTR这个名字,向系统申请获得该特殊消息的ID号,即msgID =RegisterWindowMessage (FINDMSGSTRING)后就可以利用msgID进行通信了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/46701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JVM基础02】——组成-程序计数器解读

目录 1- 引言&#xff1a;程序计数器1-1 程序计数器是什么&#xff1f;为什么用程序计数器&#xff1f;(What)(Why) 2- 核心&#xff1a;程序计数器的原理&#xff08;How&#xff09;2-1 使用 javap 查看程序计数器的作用2-2 多线程下程序计数器原理举例 3- 小结&#xff1a;什…

object-C 解答算法:移动零(leetCode-283)

移动零(leetCode-283) 题目如下图:(也可以到leetCode上看完整题目,题号283) 解题思路: 本质就是把非0的元素往前移动,接下来要考虑的是怎么移动,每次移动多少? 这里需要用到双指针,i 记录每次遍历的元素值, j 记录“非0元素值”需要移动到的位置; 当所有“非0元素值”都移…

vue3前端开发-小兔鲜项目-热门品牌推荐栏目

vue3前端开发-小兔鲜项目-热门品牌推荐栏目&#xff01;这一期内容&#xff0c;大家一定要认真的看完。因为&#xff0c;黑马官方教程视频里面老师没有讲这个&#xff0c;但是内容其实不难。只是按照之前的流程操作就行了。我把自己写好的代码分享给大家。做个参考demo。 第一步…

可用内存为什么可以超过实际内存

一、虚拟CPU和虚拟内存&#xff1a; 1、虚拟cpu&#xff1a; 利用进程机制&#xff0c;所有的现代操作系统都支持在同一时间来完成多个任务。尽管某个时刻&#xff0c;真实的CPU只能运行一个进程&#xff0c;但是从进程自己的角度来看&#xff0c;它会认为自己在独享CPU&…

安科瑞受邀参加2024年杭州建筑电气年会

24年7月4-5日&#xff0c;由杭州市土木建筑学会建筑电气专业委员会主办&#xff0c;中国联合工程有限公司&#xff0c;浙江省建设投资集团股份有限公司工程设计总院&#xff0c;大象建筑设计有限公司承办的2024年杭州建筑电气年会在杭州万华国际酒店隆重举办。杭州市各设计院所…

服务器数据恢复—RAID5阵列重建重建导致数据丢失的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台服务器&#xff0c;有一组由5块硬盘组建的raid5磁盘阵列。 服务器在运行过程中一块有磁盘掉线&#xff0c;由于raid5阵列支持一块磁盘掉线的特性&#xff0c;服务器还在正常工作。不久之后服务器出现故障&#xff0c;管理员在不了…

【洁净室】压缩气体检测参考标准:悬浮粒子、微生物、水油检测

在洁净室&#xff0c;特别是达到ISO 5或更高级别的环境中&#xff0c;维护严格的污染控制是不可或缺的。其中&#xff0c;压缩气体的质量是一个至关重要的潜在污染源。为确保压缩气体不会引入损害洁净室完整性的微粒&#xff0c;适当的气体取样成为了一项核心任务。国际标准ISO…

C2W1.LAB.Vocabulary Creation+Candidates from String Edits

理论课&#xff1a;C2W1.Auto-correct 文章目录 Vocabulary CreationImports and DataPreprocessingCreate Vocabulary法1.集合法法2.词典加词频法Visualization Ungraded Exercise Candidates from String EditsImports and DataSplitsDelete Edit Ungraded Exercise 理论课&…

【中项第三版】系统集成项目管理工程师 | 第 5 章 软件工程① | 5.1 - 5.3

前言 第5章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于技术的内容&#xff0c;学习要以教材为准。 目录 5.1 软件工程定义 5.2 软件需求 5.2.1 需求的层次 5.2.2 质量功能部署 5.2.3 需求获取 5.2.4 需求分析 5.2.5 需求规格说明书 5.2.6 需求变…

C++写一个线程池

C写一个线程池 文章目录 C写一个线程池设计思路测试数据的实现任务类的实现线程池类的实现线程池构造函数线程池入口函数队列中取任务添加任务函数线程池终止函数 源码 之前用C语言写了一个线程池&#xff0c;详情请见&#xff1a; C语言写一个线程池 这次换成C了&#xff01;…

获取淘宝商品详情app原数据item_get_app响应参数解析(二):商品标题、销量、sku、价格、视频

API名&#xff1a;item_get_app 功能说明&#xff1a;通过传入商品id获取该商品的详情页原数据。因为是原数据&#xff0c;响应参数较多。 请求示例&#xff08;curl&#xff09;&#xff1a; -- 请求示例 url 默认请求参数已经URL编码处理 curl -i "https://api-服…

Java 在PDF中替换文字(详解)

目录 使用工具 Java在PDF中替换特定文字的所有实例 Java在PDF中替换特定文字的第一个实例 Java在PDF中使用正则表达式替换特定文字 其他替换条件设置 可能出现的问题及解决方案 PDF文档中的信息随时间的推移可能会发生变化&#xff0c;比如产品价格、联系方式等。为了确保…

2024可信数据库发展大会|存算分离架构驱动电信数据平台革新

7 月 16 日 - 17 日&#xff0c;由中国通信标准化协会和中国信息通信研究院主办&#xff0c;大数据技术标准推进委员会承办&#xff0c;InfoQ 联合主办的「2024 可信数据库发展大会」&#xff08;TDBC&#xff09;在北京召开。 酷克数据解决方案架构师吴昊受邀参与“电信行业数…

算法-计数质数

题目&#xff1a; 给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 思路&#xff1a; 使用埃式筛法 当n大于等于2时&#xff0c;如果当前遍历的数 i 是质数&#xff0c;那么从 i*i 开始&#xff0c;直到 n 为止&#xff0c;把 i 的倍数都标记为合数 代码&a…

为什么提示词写作技能会让生成式AI工程师更上一层楼?

欢迎来到云闪世界。 “为什么我的经理对我的文章吹毛求疵&#xff1f;把措辞从 X 改为 Y 有什么区别&#xff1f;” 当你看到你的经理在你的文档中提出了无数建议时&#xff0c;你可能发现自己有这样的想法&#xff1b;我知道我有过。事实上&#xff0c;我曾经认为写作是数据科…

npm安装依赖包报错,npm ERR! code ENOTFOUND

一、报错现象&#xff1a; npm WARN registry Unexpected warning for https://registry.npmjs.org/: Miscellaneous Warning ETIMEDOUT: request to https://registry.npmjs.org/vue failed, reason: connect ETIMEDOUT 104.16.23.35:443 npm WARN registry Using stale data…

“点点通“餐饮点餐小程序-计算机毕业设计源码11264

"点点通"餐饮点餐小程序 XXX专业XX级XX班&#xff1a;XXX 指导教师&#xff1a;XXX 摘要 随着中国经济的飞速增长&#xff0c;消费者的智能化水平不断提高&#xff0c;许多智能手机和相关的软件正在得到更多的关注和支持。其中&#xff0c;微信的餐饮点餐小程序更…

《Exploring Aligned Complementary Image Pair for Blind Motion Deblurring》

这篇论文的标题《Exploring Aligned Complementary Image Pair for Blind Motion Deblurring》可以翻译为《探索对齐的互补图像对用于盲运动去模糊》。从标题可以推断,论文的焦点在于开发一种算法或技术,利用成对的图像来解决运动模糊问题,特别是在不知道模糊核(即造成模糊…

wifi preamble code, 前导码

WiFi packets 很神奇&#xff0c;自从802.11 协议诞生以来 就对信息传输 产生了无尽的影响&#xff0c; 闲来无事 看看wireless 空口包 发现 前导码 非常奇怪。 为什么前导码有两部分组成&#xff0c; 1. radiotap header 2. 802.11 radio information 并且 radiotap 是有在…

AIGC工具:IPAdapter和ControlNet 指导控制生成工具

ControlNet强调对生成过程的直接控制,如通过线条、边缘、形状等信息;而IPAdapter侧重于风格迁移和内容的间接引导。 IPAdapter 它专注于通过迁移图片风格来生成新的图像内容。IPAdapter的强项在于能够将一张图片的风格迁移到另一张图片上,实现风格融合,甚至可以进行多图风格…