第九章 对话框

  在 Miscrosoft Windows中,对话框就是应用程序创建的用于获取用户输入的一个临时窗口。应用程序一般用对话框来提示用户输入命令的附加信息。对话框通常都含有一个或多个用户可以输入文本、选择可选择项或者指导命令操作的控件。

对话框的基础知识

一、对话框概述
  Windows提供了许多函数、消息和预定义的控件,用于帮助创建和管理对话框。这样,开发应用程序用户接口就变得更容易了。
  Windows还提供了许多支持诸如 File Open和File Print等命令的预定义对话框(也称为“公共”对话框)。不管执行命令的是什么类型的应用程序,使用这些命令的应用程序都可以用公共对话框来提示同样的用户输入。当用户在另一个窗口中工作时,许多应用程序也用对话框显示信息选项。例如,字处理应用程序经常在文本搜索命令中使用一个对话框。应用程序在搜索文本期间,该对话框将保存在屏幕上。用户可以返回到该对话框中,并再次搜索同样的字符串、或者改变该对话框中的输入、搜索一个新的字符串。以这种方式使用对话框的应用程序,在该应用程序运行期间或在用户明确地关闭对话框之前,一般都将创建并保持显示一个对话框。
为了支持应用程序以不同的方法使用对话框,Windows提供了两种类型的对话框:模式对话框和无模式对话框。  模式对话框在允许应用程序继续运行之前,要求用户必须提供信息或取消该对话框,应用程序把模式对话框与不输入附加信息就不能继续执行的命令一起使用;无模式对话框允许用户提供信息并返回前一任务,但不关闭该对话框。 
  由于模式对话框通过调用单个函数就可以创建、执行它们的任务,所以比无模式对话框更容易管理。 不管是创建一个模式对话框还是无模式对话框,应用程序都必须提供一个对话框模板来描述对话框的样式和内容,并提供一个对话框过程来完成任务。对话框模板就是对话框及其所含控件的一个二进制描述。开发人员可以创建这个模板,把它做为从可执行文件中装入的一个资源,对话框过程就是一个应用程序自定义的回调函数。尽管对话框过程与窗口过程是相似的,但它们各自所负的责任是不同的。
  应用程序一般可以用 DialogBox 或 CreateDialog函数创建对话框。 DialogBox 用于创建模式对话框; CreateDialog 函数用于创建一个无模式对话框。这两个函数将从应用程序的可执行文件中装入对话框模板,并创建一个与该模板对应的规格相符的弹出式窗日。还有其他一些函数可以用内存中的模板创建对话框,并在对话框创建完后把附加信息传递给对话框过程。对话框通常都属于一个预定义的专有窗口类。不管是模式对 话框还是无模式对话框, Windows 都使用这个窗口类及与其对应 的窗口过程。调用这个过程时,它将先创建对话框的窗口,以及 该对话框中所有控件的窗口,然后再给对话框过程发送消息。在 对话框可见期间,预定义的窗口过程将管理所有消息,处理一些 消息,并把其他消息传给对话框父窗日的消息处理函数。应用程 序不能直接访问预定义窗口类或窗口过程,但是它们可以用对话 框模板和对话框过程修改对话框的样式和特性。
二、无模式对话框
  无模式对话框应该是一个弹出式窗口,其中包含有系统菜单、标题栏和边界,也就是说,对话框模板应该指定 WS_ POPUP、WS_ CAPTION、WS_ BORDER和 WS_ SYSMENU等风格。 Windows不会自动显示该对话框,只有在指定该模板的风格为WS_ VISIBLE时才会自动显示。
  应用程序用CreateDialog或CreateDialogIndirect函数创建无模式对话框。其中函数CreateDialog的原型定义如下:
HWND CreateDialOg(
  HmSTANCEhlnstance, //应用程序句柄
  LPCTSTRlpTemplate, //对话框模板
  HWNDhWndParent, //父窗口句柄
  DLGPROClpDialogFunc //窗口过程
);
函数CreateDialoglndirect的原型定义如下:
HWND CreateDialoglndirect(
  HINSTANCEhlnstance, //应用程序句柄
  LPCDLGTEMPLATElpTemplate, //对话框模板
  HWNDhWndParent, //父窗口句柄
  DLGPROClpDialogFunc //窗口过程
);
  无模式对话框既不能使父窗口无效,也不给它发送消息。在创建对话框时,Windows将使其成为活动窗口,但用户或应用程序任何时候都可以改变活动窗口。如果该对话框变成了非活动的,应用程序将负责为对话框检取和分发输入消息。大多数应用程序都是使用这消息循环来完成这一项工作的。但是,为了允许用户用键盘移动到控件上并选取控件,应用程序必须调用IsDialogMessage函数,该函数的原型定义如下:
BOOL IsDialogMessage(
  HWND hDlg, //对话框名柄
  LPMSG lpMsg //消息结构体 
);
  无模式对话框不像模式对话框那样给应用程序返回一个值,但是对话框过程可以用SendMessage函数给父窗口发送消息。
  应用程序在结束前必须销毁所有的无模式对话框。这可以通过调用Destroywindow函数销毁一个无模式对话框。在大多数情况下,单击Cancel按钮时,程序调用DestroyWindow函数,如果用户不以这种方式关闭对话框,则应用程序必须在其他地方调用DestroyWindow函数。
  函数DestroyWindow将使对话框的窗口句柄变为无效,从而使得对使用这个句柄的函数的任何后续调用都返回错误值。为了防止出现错误,对话框过程应该通知其父窗口,说明该对话框已经被销毁。许多应用程序都需要维护一个含有该对话框句柄的全局变量,当对话框过程销毁对话框时,它将把该全局变量设置成NULL,说明该对话框已经不再存在了。无模式对话框的对话框过程不能调用EndDialog函数来销毁它。
三、模式对话框
  模式对话框也是一个弹出式窗口,应用程序通过DialogBox函数和DialogBoxIndirect函数可以创建模式对话框。DialogBox函数的原型定义如下:
int DialogBox(
  HINSTANCE hlnstance, //应用程序句柄
  LPCTSTR lpTemplate, //对话框模板
  HWND hWndParent, //父窗口句柄
  DLGPROC lpDialogFunc //对话框过程
);
函数DialogBoxhdirect的原型定义如下:
int DialogBoxlndirect(
  HINSTANCE hlnstance, //应用程序句柄
  LPDLGTEMPLATE lpTemplate, //对话框模板
  HWND hWndParent, //父窗口句柄
  DLGPROC lpDialogFunc //对话框过程
);
  在创建模式对话框时,Windows将使其成为活动窗口。该对话框将一直保持为活动状态,直到对话框过程调用了EndDialog函数,或Windows激活了另一个应用程序中的一个窗口。在模式对话框销毁之前,用户或应用程序都不能使其父窗口成为活动窗口。
  当应用程序创建模式对话框时,如果其父窗口还不是无效的,则Windows将自动使该窗口和属于该窗口的所有子窗口都变成无效。在该对话框销毁之前,其父窗口将一直保持无效。尽管对话框过程任何时候都有能力使父窗口变成有效的,但是使父窗口有效就达不到使用模式对话框的目的,因此不建议这样做。 当Windows创建模式对话框时,它将给当前捕获鼠标输入的窗口发送WM CANCELMODE消息。接收这条消息的应用程序应该释放鼠标,以便用户可以在模式对话框中使用鼠标。由于Windows将使父窗口无效,所以,在接收到这条消息时,如果父窗口不能释放鼠标,则所有的鼠标输入都将丢失。
  为了处理模式对话框的消息,Windows将启动自己的消息循环,临时接管对整个应用程序消息队列的控制。如果Windows检取到一条明显不是用于对话框的消息,则把消息分发给正确的窗口。如果它检取到一条 WM_QUIT消息,则它将该消息投递回应用程序的消息队列,使得应用程序的主消息循环最终能够检取到该消息。
  只要应用程序的消息队列为空,Windows就把WM_CANCELDLE消息发送给父窗口,应用程序可以利用这条消息,在对话框仍然占据屏幕期间,完成一项后台任务。如果应用程序以这种方式使用消息,则它必须频繁交出控制权,使模式对话框可以接收用户输入。应用程序可以在创建该对话框时通过指定DS_NOIDLEMSG风格,禁止模式对话框发送 WM_ENTEAIDLE。应用程序通过EndDialog函数来销毁一个模式对话框,这个函数的原型定义如下:
BOOL EndDialog(
  HWND hDlg, //对话框名柄
  int nResult //返回值
);
  Windows在销毁一个模式对话框后一般都会有一个返回值,大多数应用程序就是通过这个返回值来判断对话框是否成功地完成了任务。在对话框调用EndDialog函数之前,Windows不会从创建该对话框的函数中返回控制权。

自定义对话框的应用

下面是一个用户自定义对话框的应用实例。
#include"stdafx.h"
#include "resource.h"
#include
#define MAX_LOADSTRING 100 
// 全局变量
HINSTANCE hInst;// 当前应用程序句柄
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏
TCHAR szWindowClass[MAX_LOADSTRING]; // 标题栏
//函数声明
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); 
//函数: WinMain(HINSTANCE,hPrevInstance, lpCmdLine,nCmdShow)
//目的: 入口函数
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow)
{
  MSG msg;
  // 初始化字符串
  LoadString(hInstance,IDS_APP_TITLE,szTitle, MAX_LOADSTRING);
  LoadString(hInstance, IDC_HELLO, szWindowClass, MAX_LOADSTRING);
  MyRegisterClass(hInstance);
  // 应用程序初始化
  if (!InitInstance (hInstance, nCmdShow)) {return FALSE; }
  // 主消息循环:
  while (GetMessage(&msg, NULL, 0, 0)) 
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}
// 函数: MyRegisterClass()
// 目的: 注册窗口类
ATOM MyRegisterClass(HINSTANCE hInstance)
{
  WNDCLASSEX wcex;
  wcex.cbSize = sizeof(WNDCLASSEX); 
  wcex.style= CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc= (WNDPROC)WndProc;
  wcex.cbClsExtra= 0;
  wcex.cbWndExtra= 0;
  wcex.hInstance= hInstance;
  wcex.hIcon= LoadIcon(hInstance, (LPCTSTR)IDI_HELLO);
  wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wcex.lpszMenuName = (LPCSTR)IDC_HELLO;
  wcex.lpszClassName= szWindowClass;
  wcex.hIconSm=LoadIcon(wcex.hInstance,(LPCTSTR)IDI_SMALL);
  return RegisterClassEx(&wcex);
}
//函数:: InitInstance(HANDLE, int)
//目的: 保存实例句柄和创建主窗口
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
  HWND hWnd;
  hInst = hInstance; 
  hWnd = CreateWindow(szWindowClass, szTitle,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, 0, 
            CW_USEDEFAULT, 0,
            NULL, NULL, hInstance, NULL);
  if (!hWnd) { return FALSE; }
  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  return TRUE;
}
// 函数: WndProc(HWND, unsigned, WORD, LONG)
// 目的: 处理主窗口的消息.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  int wmId, wmEvent;
  PAINTSTRUCT ps;
  HDC hdc;
  TCHAR szHello[MAX_LOADSTRING];
  LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
  switch (message) 
  {
    case WM_COMMAND://处理菜单命令
    wmId = LOWORD(wParam); 
    wmEvent = HIWORD(wParam); 

    switch (wmId)
    {
      case IDM_ABOUT:
      //处理单击About菜单项触发的消息
      DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
      break;

      case IDM_EXIT://处理单击Exit菜单项触发的消息
      DestroyWindow(hWnd);
      break;

      default://缺省命令处理
      return DefWindowProc(hWnd, message, wParam, lParam);
    }
    break;

    case WM_PAINT://处理重绘窗口消息
    hdc = BeginPaint(hWnd, &ps);
    RECT rt;
    GetClientRect(hWnd, &rt);
    DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
    EndPaint(hWnd, &ps);
    break;

    case WM_DESTROY://处理结束应用程序消息
    PostQuitMessage(0);
    break;

    default://缺省消息处理
    return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}
// 函数: About(HWND, UINT, WPARAM, LPARAM)
// 目的: About对话框消息处理函数.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
  {
    case WM_INITDIALOG://初始化对话框
    return TRUE;

    case WM_COMMAND://处理对话框中的命令
    if(LOWORD(wParam)==IDOK||LOWORD(wParam) == IDCANCEL) 
    {
      EndDialog(hDlg, LOWORD(wParam));
      return TRUE;
    }
    break;
  }
  return FALSE;
}
  在例中,当用户单击某一菜单项时,Windows系统将向应用程序发送一条WM_COMMAND消息,并在参数wParam的低位字节中记录了触发命令消息的菜单项标识符。如果单击帮助菜单下的“关于”菜单项,则其菜单项标识符 IDM_ ABOUT,这时应用程序调用函数DialogBox来生成一个对话框。在例中,指定DialogBox的lpTemplate参数的值为 IDD_ABOUTBOX,这个对话框是在 Visual C+十中定制的对话框。
  例中指定DialogBox函数的lpDialogFunc参数的值为About,这是对话框消息处理函数的人口,About函数在程序中的具体定义如下所示:
LRESUL CALLBACK AbOut(HWND hDlg,UINT message,WPARAM wParam,IPARAM lParam)
{
  switch(message)
  {
    case WM INITDIALOG: //初始化对话框
    return TRUE;

    case WM COMMAND: //命令消息
    if(LOWORD(wParam)==IDOK||LOWORD(wParam)==IDCANCEL)
    {
      EndDialog(hDlg,LOWORD(wParam)); //关闭对话框
      return TRUE;
    }
    break;
  }
  retum FALSE;
}
  About函数有一个和主窗口消息处理函数WndProc类似的结构,实际上,对话框也是一个窗口,也有其消息处理函数,这个消息处理函数在下面的例中就是About函数。
  About函数处理了两类消息:WM_INIDIALOG和WM_COMMAND。当用户在对话框中选择某一个按钮时,将会触发相应的命令消息,其中控件的标识符保存在参数WParam的低位字节中。

公用对话框

  公共对话框使 Windows 应用程序的设计变得更为简单。公共对话框是应用程序通过调用某个函数而不是通过提供对话框过程和包含对话框模板的资源文件来创建对 话框。在动态链接库 COMMDLG . DLL 中定义了各种公共对话框 的过程和模板。每个默认对话框过程处理公共对话框和它控制的 消息,默认对话框模板定义公共对话框的外观和它的控制。
  由于公共对话框提供执行某些操作的一组标准控件,因此它们除了 简化 Windows 应用程序的开发外,也对用户有帮助。当 Windows 开 发者在它们的应用程序中使用公共对话框后,用户会发现一旦在 一个应用程序中掌握了公共对话框,就能在其他的应用程序中很 轻易地执行同样的操作。

名称
说明
Open 打开文件对话框
Save AS 另存为对话框
Font 字体选择对话框
Find 查找对话框
Replace 替换对话框
Color 颜色对话框
Print 打印对话框
Print Setup 打印设置对话框

  Open和 Save As对话框: Open对话框和 Save AS对话框的外形类似,每个对话框都包含能使用户指定文件或一级文件位置和名字的控件。在Open对话框中,用户选择要打开的文件。在Save As对话框中,用户选取要保存的文件。
Open对话框如图所示。

Save As 对话框如图所示。

  Font对话框:Font对话框允许用户选择字体、字体风格、点阵大小以及字体效果的控件。
Font对话框如图所示。

  Find和 Replace对话框: Find和Replace对话框外形相似。Find对话框用于给应用程序增加字符串查找能力,用Replace对话框可以给应用程序增加字符串查找和替换的能力。Find和Replace对话框是非模式对话框,这是它们和其他对话框的主要不同之处。这意味着可以在该对话框中与建立该对话框的父窗口之间来回切换。
Find对话框如图所示。

Replace对话框如图所示。

  Color对话框: Color对话框用于设定应用程序中使用的颜色。
Color对话框如图所示。

  Color对话框使用的颜色模型分为RGB和HSL两种,但是这两种模型的内部存储方式均是采用RGB模型完成的。 在RGB模型中,有效的红色、绿色和蓝色的值的范围是0~255。0表示最小值,255表示最大值。常见的八种颜色对应的RGB值如表所示。
  Windows按照32位RGB值存储内部颜色。高位字的高位字节被保留;高位字的低位字节指定蓝色成分;低位字的高位字节指定绿色成分;低位字的低位字节指定颜色的红色成分。

颜色
RGB值
颜色
RGB值
255,0,0 品红 255,0,255
绿 0,255,0 255,255,0
0,0,255 255,255,255
深蓝 0,255,255 0,0,0

  HSL模型采用色调、饱和度和亮度来定制颜色。在Color对话框中,饱和度和亮度的值必须介于0~240范围内,色调必须在0~239范围内。常见颜色对应的HSL值如表

颜色
HSL值
颜色
HSL值
0,240,120 品红 240,120,120
绿 80,240,120 40,240,120
160,240,120 0,0,240
深蓝 120,240,120 0,0,0

  错误检测:当调用公有对话框函数失败时,应用程序可以调用CommDlgExtendError函数找出失败的原因。CommDlgExtendError函数返回表示最近错误原因的错误值。函数CommDlgExtendError的原型定义如下:
  DWORD CommDlgExtendError(VOID);
  在CDERR.H头文件中定义了六个常量,用于标识由CommDlgExtendError函数返回错误分类的错误值范围,这些常量的说明如表所示。

常量
说明
取值范围
CDERR_GENERALCODES 公用对话框的通用错误码 0x0000~0x0FFF
POERR_PRlNTERCODES Print对话框的错误码 0x1000~0x1FFF
CFERR_CHOOSEFONTCODES Font对话框的错误码 0x2000~0x2FFF
FNERR_FLENAMECODES Open和Save As对话框的错误码 0x3000~0x3FFF
FRERR_FINDREPLACECODE Find和Replace对话框的错误码 0x4000—0x4FFF
CCERR_CHOOSECOLORCODES Color对话框的错误码 0x5000~0x5FFF

公用对话框的综合应用
#include
#include
#include
#include
#include
#include "Edit.h"
#define EDITID 1
#define UNTITLED "(untitled)"
#define MAX_STRING_LEN 256
static char szFindText [MAX_STRING_LEN];
static char szReplText [MAX_STRING_LEN];
static OPENFILENAME ofn;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM);
// 打开和保存文件的函数声明
void PopFileInitialize (HWND);
BOOL PopFileOpenDlg (HWND, PSTR, PSTR);
BOOL PopFileSaveDlg (HWND, PSTR, PSTR);
BOOL PopFileRead (HWND, PSTR);
BOOL PopFileWrite (HWND, PSTR);
// 查找和替换的函数声明
HWND PopFindFindDlg (HWND);
HWND PopFindReplaceDlg (HWND);
BOOL PopFindFindText (HWND, int *, LPFINDREPLACE);
BOOL PopFindReplaceText (HWND, int *, LPFINDREPLACE);
BOOL PopFindNextText (HWND, int *);
BOOL PopFindValidFind (void);
void DoCaption (HWND hwnd, char *szTitleName);
void OkMessage (HWND hwnd, char *szMessage, char *szTitleName);
// 全局变量
static char szAppName[] = "编辑器";
static HWND hDlgModeless;
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{
  MSG msg;
  HWND hwnd;
  HACCEL hAccel;
  WNDCLASSEX wndclass;
  //窗口类定义
  wndclass.cbSize= sizeof (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= "POPPAD";
  wndclass.lpszClassName= szAppName;
  wndclass.hIconSm= LoadIcon (hInstance, szAppName);
  RegisterClassEx (&wndclass);//注册窗口类
  //创建窗口
  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))
    {
      if (!TranslateAccelerator (hwnd, hAccel, &msg))
      {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
      }
    }
  }
  return msg.wParam;
}
//函数:DoCaption
//作用:设置标题栏
void DoCaption (HWND hwnd, char *szTitleName)
{
  char szCaption[64 + _MAX_FNAME + _MAX_EXT];
  wsprintf (szCaption, "%s - %s", szAppName, szTitleName[0] ?szTitleName : UNTITLED) ;
  SetWindowText (hwnd, szCaption);
}
//函数:OkMessage
//作用:通知用户消息
void OkMessage (HWND hwnd, char *szMessage, char *szTitleName)
{
  char szBuffer[64 + _MAX_FNAME + _MAX_EXT];
  wsprintf (szBuffer, szMessage, szTitleName[0] ? szTitleName : UNTITLED);
  MessageBox (hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION);
}
//函数:AskAboutSave
//作用:询问是否保存文件
short AskAboutSave (HWND hwnd, char *szTitleName)
{
  char szBuffer[64 + _MAX_FNAME + _MAX_EXT];
  int iReturn;
  wsprintf (szBuffer, "当前文件已经修改,是否保存? %s?",
       szTitleName[0] ? szTitleName : UNTITLED) ;
  //弹出一个消息框提示用户是否保存文件
  iReturn = MessageBox (hwnd, szBuffer, szAppName,MB_YESNOCANCEL | MB_ICONQUESTION);
  if (iReturn == IDYES)
    if (!SendMessage (hwnd, WM_COMMAND, IDM_SAVE, 0L))//保存文件
      iReturn = IDCANCEL;
  return iReturn;

//函数:WndProc
//作用:主窗口消息循环
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
  static BOOL bNeedSave = FALSE; //是否保存文件的标志
  static char szFileName[_MAX_PATH];//文件名
  static char szTitleName[_MAX_FNAME + _MAX_EXT];
  static HINSTANCE hInst;//应用程序句柄
  static HWND hwndEdit;//编辑框句柄
  static int iOffset;
  static UINT iMsgFindReplace;
  LPFINDREPLACE pfr;

  switch (iMsg)
  {
    case WM_CREATE: //创建窗口
    hInst = ((LPCREATESTRUCT) lParam) -> hInstance ;
    //创建编辑框
    hwndEdit = CreateWindow("edit", NULL,
                WS_CHILD | WS_VISIBLE | WS_HSCROLL
                | WS_VSCROLL |WS_BORDER | ES_LEFT |
                ES_MULTILINE |ES_NOHIDESEL | 
                ES_AUTOHSCROLL | ES_AUTOVSCROLL,
                0, 0, 0, 0,
                hwnd, (HMENU) EDITID, hInst, NULL) ;
                SendMessage (hwndEdit, EM_LIMITTEXT, 32000, 0L);
    PopFileInitialize (hwnd); //初始化ofn
    //注册消息FINDMSGSTRING
    iMsgFindReplace = RegisterWindowMessage (FINDMSGSTRING) ;
    lstrcpy (szFileName, (PSTR) (((LPCREATESTRUCT) lParam)->lpCreateParams)) ;
    if (strlen (szFileName) > 0)
    {
      GetFileTitle (szFileName, szTitleName, sizeof (szTitleName));
      //获取文件名
      if (!PopFileRead (hwndEdit, szFileName))//读文件
        OkMessage (hwnd, "文件 %s 不能读取!", szTitleName);
    }

    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_COMMAND:// 菜单命令
    if (lParam && LOWORD (wParam) == EDITID)
    { 
      switch (HIWORD (wParam))
      { 

        case EN_UPDATE:
        bNeedSave = TRUE;
        return 0;

        case EN_ERRSPACE:

        case EN_MAXTEXT:

        MessageBox (hwnd, "编辑框超出边界!.", szAppName, MB_OK | MB_ICONSTOP);
        return 0;
      }
      break;
    }

    switch (LOWORD (wParam))
    {
      // 来自文件菜单的消息
      case IDM_NEW://新建
      if (bNeedSave && IDCANCEL ==AskAboutSave (hwnd, szTitleName))
      return 0;
      SetWindowText (hwndEdit, "\0");
      szFileName[0] = '\0';
      szTitleName[0] = '\0';
      DoCaption (hwnd, szTitleName);
      bNeedSave = FALSE;
      return 0;

      case IDM_OPEN://打开文件
      if (bNeedSave && IDCANCEL ==AskAboutSave (hwnd, szTitleName)) return 0 ;
      //弹出Open对话框
      if (PopFileOpenDlg (hwnd, szFileName, szTitleName))
      {
        //读文件
        if (!PopFileRead (hwndEdit, szFileName))
        {
          OkMessage (hwnd, "不能读取文件%s!",szTitleName);
          szFileName[0] = '\0';
          szTitleName[0] = '\0';
        }
      }
      DoCaption (hwnd, szTitleName);
      bNeedSave = FALSE;
      return 0;

      case IDM_SAVE://保存
      if (szFileName[0])
      {
        //写文件
        if (PopFileWrite (hwndEdit, szFileName))
        {
          bNeedSave = FALSE;
          return 1;
        }
        else
        OkMessage (hwnd, "不能写文件 %s",szTitleName) ;
        return 0;
      } 

      case IDM_SAVEAS://另存为
      //弹出Save AS对话框
      if (PopFileSaveDlg (hwnd, szFileName, szTitleName))
      {
        DoCaption (hwnd, szTitleName) ;
        if (PopFileWrite (hwndEdit, szFileName))
        {
          bNeedSave = FALSE;
          return 1;
        }
        else
        OkMessage (hwnd, "不能写文件%s",szTitleName) ;
      }
      return 0;

      case IDM_EXIT://结束
      SendMessage (hwnd, WM_CLOSE, 0, 0);
      return 0;

      case IDM_UNDO ://撤消
      SendMessage (hwndEdit, WM_UNDO, 0, 0);
      return 0; 

      case IDM_CUT: //剪切
      SendMessage (hwndEdit, WM_CUT, 0, 0);
      return 0;

      case IDM_COPY://复制
      SendMessage (hwndEdit, WM_COPY, 0, 0);
      return 0;

      case IDM_PASTE://粘贴
      SendMessage (hwndEdit, WM_PASTE, 0, 0);
      return 0;

      case IDM_CLEAR://清空
      SendMessage (hwndEdit, WM_CLEAR, 0, 0);
      return 0;

      case IDM_SELALL://全选
      SendMessage (hwndEdit, EM_SETSEL, 0, -1);
      return 0;

      case IDM_FIND://查找
      SendMessage (hwndEdit, EM_GETSEL, NULL,(LPARAM) &iOffset);
      hDlgModeless = PopFindFindDlg (hwnd);
      return 0;

      case IDM_NEXT://查找下一处
      SendMessage (hwndEdit, EM_GETSEL, NULL,(LPARAM) &iOffset);
      if (PopFindValidFind ())
        PopFindNextText (hwndEdit, &iOffset);
      else
        hDlgModeless = PopFindFindDlg (hwnd);
      return 0;

      case IDM_REPLACE://替换
      SendMessage (hwndEdit, EM_GETSEL, NULL,(LPARAM) &iOffset);
      hDlgModeless = PopFindReplaceDlg (hwnd);
      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:
    PostQuitMessage (0);
    return 0;

    default:
    //处理"Find-Replace" 消息
    if (iMsg == iMsgFindReplace)
    {
      pfr = (LPFINDREPLACE) lParam ;
      if (pfr->Flags & FR_DIALOGTERM) hDlgModeless = NULL;
      if (pfr->Flags & FR_FINDNEXT)
        if (!PopFindFindText (hwndEdit, &iOffset, pfr))
          OkMessage (hwnd, "文本没找到!", "\0") ;

      if (pfr->Flags & FR_REPLACE ||pfr->Flags & FR_REPLACEALL)
        if (!PopFindReplaceText (hwndEdit, &iOffset, pfr))
          OkMessage (hwnd, "文本没找到!", "\0") ;

      if (pfr->Flags & FR_REPLACEALL)

      while (PopFindReplaceText (hwndEdit, &iOffset, pfr)); 
      return 0 ;
    }
    break ;
  }
  return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
//函数:PopFileInitialize
//作用:初始化全局变量ofn
void PopFileInitialize (HWND hwnd)
{
  static char szFilter[] = "文本文件(*.TXT)\0*.txt\0"
               \"ASCII文件(*.ASC)\0*.asc\0" \
               "所有文件 (*.*)\0*.*\0\0" ;
  ofn.lStructSize= sizeof (OPENFILENAME) ;
  ofn.hwndOwner= hwnd ;
  ofn.hInstance= NULL ;
  ofn.lpstrFilter= szFilter ;
  ofn.lpstrCustomFilter = NULL ;
  ofn.nMaxCustFilter= 0 ;
  ofn.nFilterIndex= 0 ;
  ofn.lpstrFile= NULL ; 
  ofn.nMaxFile= _MAX_PATH ;
  ofn.lpstrFileTitle= NULL ; 
  ofn.nMaxFileTitle= _MAX_FNAME + _MAX_EXT ;
  ofn.lpstrInitialDir= NULL ;
  ofn.lpstrTitle= NULL ;
  ofn.Flags= 0 ; 
  ofn.nFileOffset= 0 ;
  ofn.nFileExtension= 0 ;
  ofn.lpstrDefExt= "txt" ;
  ofn.lCustData= 0L ;
  ofn.lpfnHook= NULL ;
  ofn.lpTemplateName= NULL ;
}
//函数:PopFileOpenDlg
//作用:弹出Open对话框
BOOL PopFileOpenDlg (HWND hwnd, PSTR pstrFileName, PSTR pstrTitleName)
{
  ofn.hwndOwner= hwnd ;
  ofn.lpstrFile= pstrFileName ;
  ofn.lpstrFileTitle= pstrTitleName ;
  ofn.Flags= OFN_HIDEREADONLY;
  return GetOpenFileName (&ofn) ;//弹出Open对话框
}
//函数:PopFileSaveDlg
//作用:弹出Save As对话框
BOOL PopFileSaveDlg (HWND hwnd, PSTR pstrFileName, PSTR pstrTitleName)
{
  ofn.hwndOwner= hwnd ;
  ofn.lpstrFile= pstrFileName ;
  ofn.lpstrFileTitle= pstrTitleName ;
  ofn.Flags= OFN_OVERWRITEPROMPT ;
  return GetSaveFileName (&ofn) ;
}
//函数:PopFileLength
//作用:计算文件长度
static long PopFileLength (FILE *file)
{
  int iCurrentPos, iFileLength ;
  iCurrentPos = ftell (file) ;
  fseek (file, 0, SEEK_END) ;
  iFileLength = ftell (file) ;
  fseek (file, iCurrentPos, SEEK_SET) ;
  return iFileLength ;
}
//函数:PopFileRead
//作用:读取文件
BOOL PopFileRead (HWND hwndEdit, PSTR pstrFileName)
{
  FILE *file;
  int iLength;
  PSTR pstrBuffer;
  //打开文件
  if (NULL == (file = fopen (pstrFileName, "rb"))) return FALSE;
  iLength = PopFileLength (file);//获取文件长度
  if (NULL == (pstrBuffer = (PSTR) malloc (iLength)))
  {
    fclose (file); //关闭文件
    return FALSE;
  }
  fread (pstrBuffer, sizeof(char), iLength, file); //读取文件
  fclose (file);
  pstrBuffer[iLength] = '\0';
  SetWindowText (hwndEdit, pstrBuffer); 
  //设置编辑框中的文本内容
  return TRUE;
}
//函数:PopFileWrite
//作用:写文件
BOOL PopFileWrite (HWND hwndEdit, PSTR pstrFileName)
{
  FILE *file ;
  int iLength ;
  PSTR pstrBuffer ;
  if (NULL == (file = fopen (pstrFileName, "wb"))) return FALSE ;//打开文件
  iLength = GetWindowTextLength (hwndEdit) ;
  //获取编辑框中的文本内容长度
  if (NULL == (pstrBuffer = (PSTR) malloc (iLength + 1)))
  {
    fclose (file) ;//关闭文件
    return FALSE ;
  }
  //获取编辑框中的文本内容
  GetWindowText (hwndEdit, pstrBuffer, iLength + 1) ;
  //写文件
  if (iLength != (int) fwrite (pstrBuffer, 1, iLength, file))
  {
    fclose (file); //关闭文件
    free (pstrBuffer);
    return FALSE;
  }
  fclose (file);
  free (pstrBuffer);
  return TRUE;
}
//函数:PopFindFindDlg
//作用:弹出Find对话框
HWND PopFindFindDlg (HWND hwnd)
{
  static FINDREPLACE fr; 
  //初始化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;
  fr.wFindWhatLen= sizeof (szFindText);
  fr.wReplaceWithLen= 0;
  fr.lCustData = 0;
  fr.lpfnHook= NULL;
  fr.lpTemplateName= NULL;
  return FindText (&fr);// 弹出Find对话框
}
//函数:PopFindReplaceDlg
//作用:弹出Replace对话框
HWND PopFindReplaceDlg (HWND hwnd)
{
  static FINDREPLACE fr; 
  //初始化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= sizeof (szFindText);
  fr.wReplaceWithLen= sizeof (szReplText);
  fr.lCustData= 0;
  fr.lpfnHook= NULL;
  fr.lpTemplateName= NULL;
  return ReplaceText (&fr); //弹出Replace对话框
}
//函数:PopFindFindText
//作用:查找字符串
BOOL PopFindFindText (HWND hwndEdit, int *piSearchOffset, LPFINDREPLACE pfr)
{
  int iLength, iPos;
  PSTR pstrDoc, pstrPos;
  //获取编辑框中的文本内容长度
  iLength = GetWindowTextLength (hwndEdit);
  if (NULL == (pstrDoc = (PSTR) malloc (iLength + 1))) return FALSE;
  //获取编辑框中的文本内容
  GetWindowText (hwndEdit, pstrDoc, iLength + 1);
  pstrPos = strstr (pstrDoc + *piSearchOffset, pfr->lpstrFindWhat);
  free (pstrDoc);
  if (pstrPos == NULL)return FALSE;
  iPos = pstrPos - pstrDoc;
  *piSearchOffset = iPos + strlen (pfr->lpstrFindWhat);
  SendMessage (hwndEdit, EM_SETSEL, iPos, *piSearchOffset);
  SendMessage (hwndEdit, EM_SCROLLCARET, 0, 0);
  return TRUE;
}
//函数:PopFindNextText
//作用:查找下一处字符串
BOOL PopFindNextText (HWND hwndEdit, int *piSearchOffset)
{
  FINDREPLACE fr;
  fr.lpstrFindWhat = szFindText;
  return PopFindFindText (hwndEdit, piSearchOffset, &fr);
}
//函数:PopFindReplaceText
//作用:替换文本
BOOL PopFindReplaceText (HWND hwndEdit, int *piSearchOffset, LPFINDREPLACE pfr)
{
  if (!PopFindFindText (hwndEdit, piSearchOffset, pfr)) return FALSE;
  //弹出Replace对话框 
  SendMessage (hwndEdit, EM_REPLACESEL, 0, (LPARAM) pfr->lpstrReplaceWith);
  return TRUE;
}
BOOL PopFindValidFind (void)
{
  return *szFindText != '\0';
}
  首先声明了一个OPENFILENAME结构体的全局静态变量ofn,这个变量用于记录打开一个文件时系统需要的各种信息。
OPENFILENAME结构体的具体定义如下:
typedef structtagOFN{
  DWORD lStructSize; //结构体大小
  HWND hWndOwner; //父窗口句柄
  HINSTANCE hlnstance; //应用程序句柄
  LPCTSTR lpstrFilter; //文件过滤条件
  LPTSTR lpstrCustomFilter; //用户定制的过滤条件
  DWORD nMaxCustFilter; //lpstrCustomFilter缓冲区的大小
  DWORD nFilterlndex; //过滤索引
  LPTSTR lpstrFile; //文件名(不含路径)
  DWORD nMaxFile; //lpstrFile缓冲区的大小
  LPTSTR lpstrFileTitle; //文件名(含路径)
  DWORD nMaxFileTitle; //lpstrFileTitle缓冲区的大小
  LPCTSTR lpstrlnitialDir; //初始化目录
  LPCTSTR lpstrTitle; //对话框标题
  DWORD Flags; //文件打开属性
  WORD nFileOffset; //lpstrFile所指向的字符串在lpstrFileTitle中的偏移值
  WORD nFileExtension; //文件扩展名
  LPCTSTR lpstrDefExt; //默认扩展名
  DWORD lCustData; //用户数据
  LPOFNHOOKPROC lpfnHook; //Windows Hook函数指针
  LPCTSTR lpTemplateName;//对话框模板名
}OPENFILENAME;
  在调用打开文件对话框打开一个文件之前,必须先对OFN变量的各个域进行初始化。
  在处理消息WM_CREATE时,程序调用自定义的函数PopFilelnitialize对OFN进行初始化操作。
函数 PopFileInitialize 的完整定义如下:
void PopFilelnitialize(HWND hWnd)
{
  static charszFilter[]"TextFiles(*.TXT)\0*.txt\0" \
  "ASCII Files(*.ASC)\0*.asc\0"\
  "All Files(*.*)\0*.*\0\0";
  ofn.lStructSize=sizeof(OPENF ILENAME);
  ofn.hWndOwner=hWnd;
  ofn.hlnstance=NULL;
  ofn.lpstrFilter=szFilter;
  ofn.1pstrCustomFilter=NULL;
  ofn.nMaxCustFilter=0;
  ofn.nFilterlndex=0;
  ofn.lpstrFile=NULL;
  ofn.nMaxFile=MAX PATH;
  ofn.lpstrFileTitle=NULL;
  ofn.nMaxFileTitle=_MAX_FNAME+_MAX_EXT;
  ofn.lpstrlnitialDir=NULL;
  ofn.lpstrTitle=NULL;
  ofn.Flags=0;
  ofn.nFileOffset=0;
  ofn.nFileExtension=0;
  ofn.lpstrDefExt="txt";
  ofn.lCustData=0L;
  ofn.lpfnHook:NULL;
  ofn.lpTemplateName=NULL;
}
  然后,程序调用函数RegisterWindowMessage对消息FINDMSGSTRING进行注册。Windows允许用户使用系统预定义的消息,也允许用户使用自定义的消息,但是在使用自定义的消息之前,必须对消息进行注册。
函数RegisterWindowMessage的原型定义如下:
UINT RegisterWindowMessage(
  LPCTSTR lpString //消息字符串指针
);
程序通过如下语句取得在命令行中指定的文件名:
  lstrcpy(szFileName,(PSTR)(((LPCREATESTRUCT)lParam)->lpCreateParams));
  其中,lParatn是消息处理函数的参数lParam是指向CREATESTRUCT结构体的指针,CREATESTRUCT结构体的成员变量 lpCreateParams中记录在创建窗口时,程序传递给CreateWindow函数的 lpParam参数的值 szCmdLine,而 szCmdLine又是 WinMain函数用于接收用户命令行的参数。
  所以,上述语句的目的就是取得用户的命令行参数。lstrcpy用于把字符串复制到另一个字符串中,函数原型定义如下:
LPTSTR lstrcpy(
  LPTSTR lpStringl, //接收字符串的指针
  LPCTSTR lpString2 //被复制的字符串指针
);
如果命令行中指定了打开的文件名,即szFileName不为空,则程序调用如下语句来加以处理:
if(strlen(szFileName)>0)
{
GetFileTitle(szFileName,szTitleName,sizeof(szTitleName)); //获取文件名
if(!PopFileRead(hWndEdit,szFileName)) //读文件
OkMessage(hWnd,"File%s cannot be read!",szTitleName);
}
其中,函数GetFileTitle用于获取文件名,函数原型定义如下所示。
short GetFileTitle(
  LPCTSTR lpszFile, //包含路径及文件名的字符串
  LPTSTR lpszTitle, //只包含文件名的字符串
  WORD cbBuf //lpszTitle字符串的长度
);
   在取得文件名后,程序调用函数PopFileRead把文件中的数据读人到编辑框中。
函数PopFileRead的具体定义如下:
BOOL POpFileRead(HWND hWndEdit,PSTR pstrFileName)
{
  FIIE *file;
  int iLength;
  PSTR pstrBuffer;
  if(NULL==(file=fopen(pstrFileName,"rb"))) //打开文件
  return FALSE;
  iLength=PopFileLength(file); //获取文件长度
  if(NULL==(pstrBuffer=(PSTR)malloc(iLength)))
  {
    fclose(file); //关闭文件
    return FALSE;
  }
  fread(pstrBufier,1,iLength,file); //读取文件
  fclose(file);
  pstrBuffer[iLength]='\0';
  SetWindowText(hWndEdit,pstrBufier); //设置编辑框中的文本内容
  free(pstrBuffer); //释放pstrBufier缓冲区
  return TRUE;
}
  在 PopFileRead 函数中,首先定义了文件指针 file ,然后通过函数 fopen 打开由pstrFileName 指定的文件, fopen 函数的原型定义如下:
FILE fopen(
  const char *fllename,//文件名指针
  const char *mode //打开文件的模式
);
然后,程序调用 PopFileLength采取得文件的长度,PopFileLength也是自定义的函数,其具体定义如下:
static long PopFileLength(FILE *file)
{
  int iCurrentPos,iFileLength;
  iCurrentPos=ftell(file);
  fseek(file,0,SEEK_END);
  iFileLength=ftell(file);
  fseek(file,iCurrentPos,SEEK_SET);
  return iFileLength;
}
  函数PopFileLength中首先通过ftell取得文件指针的当前位置,并把结果保存在iCurrentPos中,ftell函数的原型定义如下:
long ftell(
  FILE *stream //文件指针
);
PopFileLength然后调用 fseek函数移动文件指针到文件末尾处,fseek函数的原型定义如下:
int fseek(
  FILE *stream, //文件指针
  long offset, //距离origin的偏移值
  int origin //初始位置
);
  程序中指定 offset参数的值为 0,指定 origin参数的值为 SEEK_END,表示把文件指针移动到距离文件末尾为0的位置,即文件的末尾处。
  在把文件指针移动到文件末尾后,再一次调用函数ftell取得当前的文件指针的位置,并把结果保存在iFileLength变量中。
  在取得文件的长度后,还必须把文件指针复位,以便后续的文件操作。
函数fread实现读取文件中的数据,这个函数的原型定义如下;
size_t fread(
  void *buffer, //记录数据的缓冲区
  size tsize, //文件中的每一项的长度
  size tcount, //文件中的项数
  FILE *stream //文件指针
);
函数SetWindowsText用于把读取到的数据显示在编辑框中,函数原型定义如下:
BOOL SetWindowText(
  HWND hWnd, //窗口句柄
  LPCTSTR lpString //指向被显示的字符串的指针
);
  OkMessage是自定义的一个通用函数,其主要作用是当程序顺利完成某一项操作后向用户通报操作成功的消息。DoCaption也是自定义的一个通用函数,其主要作用是处理某个窗口的标题。如果用户选择了文件菜单下的“打开”菜单项,则程序通过图形代码来进行相应的处理。
case IDM OPEN: //打开文件
  if(bNeedSave && IDCANCEL==AskAboutSave(hWnd,szTitleName)) return 0;
  //弹出Open对话框
  if(POpFileOpenDlg(hWnd,szFUeName,szTitleName))
  {
    //读文件
    if(!PopFileRead(hWndEdit,szFileName))
    {
      OkMessage(hWnd,"Could not read file %s!",szTitleName);
      szFileName[0]='\0';
      szTitleName[0]='\0';
    }
  }
  DoCaption(hWnd,szTitleName);
  bNeedSave=FALSE;
return 0;
  用户选择文件菜单下的“打开”菜单项的目的就是希望打开一个新文件,但是在打开新文件之前必须检查编辑框中的内容是否已经保存,如果没有保存,则bNeedSave变量将被置成TRUE,通过检查bNeedSave变量的值可以决定是否需要对编辑框中的内容进行保存操作。函数AskAboutSave是自定义的函数,其作用是提示用户对没有保存的内容进行保存。函数AskAboutSave的具体定义如下:
short AskAboutSave(HWND hWnd,Char *szTitleName)
{
  char szBuffer[64+_MAX_FNAME+_MAX_EXT];
  int iReturn;
  wsprintf(szBuffer,"Save current changes in %S?",szTitleName[0]? szTitleName:UNTJTLED);
  //弹出一个消息框提示用户是否保存文件
  iReturn=MessageBox (hWnd,szBuffer,szAppName,MB_YESNOCANCEL | MB_ICONQUESTION);
  if(iReturn==IDYES)
    if(!SendMessage(hWnd,WM_COMMAND,IDM_SAVE,0L))//保存文件
      iReturn=IDCANCEL;
  return iReturn;
}
在上述程序中,函数MessageBox用于弹出一个消息框,函数原型定义如下:
  如果用户认为需要保存文件,则必然会单击消息框中的Yes按钮,这时MessageBox函数的返回值为IDYES,程序于是接着调用SendMessage函数向应用程序发送一条WM_COMMAND消息,对这条消息的附加信息指定为IDM_SAVE。应用程序在接收到这条消息后,程序流程将转到对保存菜单项进行相应处理的代码处。
int MessageBox(
  HWND hWnd, //父窗口句柄
  LPCTSTR lpText, //提示信息字符串指针
  LPCTSTR lpCaption, //标题字符串指针
  UINT uType //消息框风格
);
真正实现弹出 Open对话框的是PopFileOpenDlg函数,函数的定义如下:
BOOL PopfileOpenDlg(HWND hWnd,PSTR pstrPileName,PSTR pstrTitleName)
{
  ofn.hWndOwner=hWnd;
  ofn.lpstrFile=pstrFileName;
  ofn.lpstrFileTitle=pstrTitleName;
  ofn.Flags=OFN_HIDEREADONLY | OFN_CREATEPROMPT;
  return GetOpenFileName(&ofn);//弹出Open对话框
}
上述程序段中通过对 Windows API函数 GetOpenFileName的调用来实现弹出 Open对话框,GetOpenFileName函数的原型定义如下:
BOOL GetOpenPileName(
  LPOPENFILENAME lpofn //OPENFILENAME结构体指针
);
  如果成功地打开某一个文件后,PopFileOpeDlg函数将返回TRUE,于是程序接着调用函数DoCaption改变窗口标题,同时把变量bNeedSave的值设置为FALSE。其他对话框的使用大致也遵循和Open对话框类似的过程。 
例题的头文件Edit.h如下:
#define IDM NEW 10
#define IDM OPEN 11
#define IDM SAVE 12
#define IDM SAVEAS 13
#define IDM PRINT 14
#define IDM EXIT 15
#define IDM UNDO 20
#define IDM CUT 21
#define IDM FIND 30
#define IDM NEXT 31
#define IDM REPLACE 32
#define IDM HELP 50
#define IDM ABOUT 51
#define IDD FNAME 10
例题的资源文件如下:
#include "resource.h"
#include "Edit.h"
//菜单
POPPAD MENU DISCARDABLE
BEGIN
  POPUP"文件"
  BEGIN
    MENUITEM"新建", IDM_NEW
    MENUITEM"打开", IDM_OPEN
    MENUITEM"保存", IDM_SAVE
    MENUITEM"另存为", IDM_SAVEAS
    MENUITEM SEPARATOR
    MENUITEM"结束", IDM_EXIT
  END
  POPUP"编辑"
  BEGIN
    MENUITEM"撤消", IDM_UNDO
    MENUITEM SEPARATOR
    MENUITEM"剪切", IDM_CUT
    MENUITEM"复制", IDM_COPY
    MENUITEM"粘贴", IDM_PASTE
    MENUITEM"删除", IDM_CLEAR
    MENUITEM SEPARATOR
    MENUITEM"全选", IDM_SELALL
  END
POPUP"搜索"
  BEGIN
    MENUITEM"查找", IDM_FIND
    MENUITEM"查找厂一个", IDM_NEXT
    MENUITEM"替换", IDM_REPLACE
  END
END
//加速键
POPPAD ACCELERATORS MOVEABIE PURE
BEGIN
  "^N", IDM_NEW, ASCII
  "^O", IDM_OPEN, ASCII
  "^S", IDM_SAVE, ASCII
  "^P", IDM_PRINT, ASCII
  "^Z", IDM_UNDO, ASCII
  VK_BACK, IDM_UNDO, VIRTKEY,ALT
  "^X", IDM_CUT, ASCII
  VK_DELETE, IDM_CUT, VIRTKEY,SHIFT
  "^C", IDM_COPY, ASCII
  VK_INSERT, IDM_COPY, VIRTKEY,CONTROL
  "^V", IDM_PASTE, ASCII
  VK_lNSERT, IDM_PASTE, VIRTKEY,SHIFT
  VK_DELETE, IDM_CLEAR, VIRTKEY
  "^F", IDM_FIND, ASCII
  VK_F3, IDM_NEXT, VIRTKEY
  "^R", IDM_REPLACE, ASCII
  VK_F1, IDM_HELP, VIRTKEY
END
//对话框
ABOUTBOX DIALOG DISCARDABLE 20,20,160,80
STYLE WS_POPUP | WS_DLGFRAME
BEGIN
  CTEXT "POpPad",-1,0,12,160,8
  ICON "PopPad",-1,8,8,0,0
  CTEXT "Popup Editor for Microsoft Windows",-1,0,36,160,8
  CTEXT "Copyright(c)Charles Petzold,1996",-1,0,48,160,8
  DEFPUSHBUTTON "OK",IDOK,64,60,32,14,WS_GROUP
END
PRINTDLGBOX DIALOG DISCARDABLE 20,20,100,76
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "PopPad"
BEGIN
  CTEXT "Sending",-1,0,10,100,8
  CTEXT "",IDD_FNAME,0,20,100,8
  CTEXT "to print spooler",-1,0,30,100,8
  DEFPUSHBUTTON "Cancel",IDCANCEL,34,50,32,14,WS_GROUP
END
例题执行结果如图所示。

你可能感兴趣的:(UI/MFC/界面库,VC++相关,Windows编程)