windows程序设计 「PopPad3」范例分析笔记
2010-10-06 21:39
459 查看
/*---------------------------------------
POPPAD.C
-- Popup Editor
(c) Charles Petzold, 1998
---------------------------------------*/
#include <windows.h>
#include <commdlg.h> //使用通用对话框,必须包含此头文件
#include "resource.h" //资源文件
#define EDITID
1
#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) ;
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) ;
HWND PopFindReplaceDlg
(HWND) ;
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) ;
// 全局变量
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))
{
//拦截快捷键消息
if (!TranslateAccelerator
(hwnd, hAccel, &msg))
{
TranslateMessage
(&msg) ;
DispatchMessage
(&msg) ;
}
}
}
return msg.wParam ;
}
void DoCaption
(HWND hwnd, TCHAR * szTitleName)
{
TCHAR szCaption[64 + MAX_PATH
] ;
//将窗口名和打开的文件路径拼接起来,如果未打开任何文件则显示(UNTITLED)
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
) //如果用户选择的YES,就向父窗口发送保存消息
//如果消息执行失败,根据程序设计,返回0,则将用户选择设为CANCEL
if (!SendMessage
(hwnd, WM_COMMAND
, IDM_FILE_SAVE
, 0))
iReturn = IDCANCEL
;
//返回用户选择
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 ;
//创建编辑控件的子窗口,ID为 EDITID
hwndEdit = CreateWindow
(TEXT ("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
) ;
//限制编辑控件最大只能输入32000个字符
SendMessage
(hwndEdit, EM_LIMITTEXT
, 32000, 0L) ;
PopFileInitialize
(hwnd) ; //初始化OPENFILENAME结构
PopFontInitialize
(hwndEdit) ; //创建系统字体副本,运用到编辑控件中
/*调用FindText函数前,必须调用该函数以得到FINDMSGSTRING信息的标识符,
对话框函数在用户点击FindNext按钮或对话框被关闭时利用此标识符传送信息。
FINDMSGSTRING信息的IParam参数包含一个指向FINDREPLACE结构的指针。*/
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) //LOWORD (lParam):弹出式菜单索引(从0开始) ;HIWORD (lParam):系统菜单为1,其它为0
{
case 1: // 编辑菜单
//如果编辑控件能够执行Undo动作,那么SendMessage呼叫传回非零值。在这种情况下,选项被启用;否则,选项无效化
EnableMenuItem
((HMENU) wParam, IDM_EDIT_UNDO
, //撤销
SendMessage
(hwndEdit, EM_CANUNDO
, 0, 0L) ? MF_ENABLED
: MF_GRAYED
) ;
//IsClipboardFormatAvailable 判断剪贴板上的数据,如果是CF_TEXT,则该函数返回值为true,否则为false
//剪贴板数据格式:CF_TEXT 以NULL结尾的ASCII字符的文本格式
EnableMenuItem
((HMENU) wParam, IDM_EDIT_PASTE
, //粘贴
IsClipboardFormatAvailable
(CF_TEXT
) ? MF_ENABLED
: MF_GRAYED
) ;
//向编辑控件发送EM_GETSEL消息,将得到目前选中的文字第一位和最后一位的超尾位置
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: // 搜索菜单
//如果非模态对话框(查找、替换)
未激活
,则有效,否则无效
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
:
// lParam:子窗口句柄;LOWORD (wParam):子窗口ID
// 判断条件:句柄不为空,消息是由编辑控件发出 。菜单发出的该消息 lParam 参数为0
if (lParam && LOWORD (wParam) == EDITID
)
{
switch (HIWORD (wParam)) // 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
{
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 ;
//调用自定义函数,激活OPEN通用对话框,如果成功返回非零
if (PopFileOpenDlg
(hwnd, szFileName, szTitleName))
{
/*如果打开文件成功,GetOpenFileName将ofn.lpstrFile成员指向的缓冲区,设置为含有全路径和用户指定的文件名,
ofn.lpstrFile 是一个指向 szFileName 指针的指针,所以szFileName将含有全路径和用户指定的文件名。
PopFileRead 读取打开的文件数据,并显示在编辑控件上。如果成功返回TRUE */
if (!PopFileRead
(hwndEdit, szFileName))
{
//如果读取文件失败,则弹出消息提示框,并将文件路径和文件名置空
OkMessage
(hwnd, TEXT ("Could not read file %s!
"),szTitleName) ;
szFileName[0] = '/0
' ;
szTitleName[0] = '/0
' ;
}
}
DoCaption
(hwnd, szTitleName) ; //设置窗口标题文字 szTitleName 为用户打开的文件名和扩展名
bNeedSave = FALSE
; //标记编辑控件内容为未改变
return 0 ;
case IDM_FILE_SAVE
: //保存
if (szFileName[0]) //如果文件路径存在
{ //调用自定义函数,保存编辑控件中的文本
if (PopFileWrite
(hwndEdit, szFileName))
{
//如果保存成功,设编辑控件内容未改变,返回1
bNeedSave = FALSE
;
return 1 ;
}
else
{
//如果保存失败,弹出消息框,返回0
OkMessage
(hwnd, TEXT ("Could not write file %s
"), szTitleName) ;
return 0 ;
}
}
//连续执行 如果文件路径为空,或者用户选择另存为菜单项
case IDM_FILE_SAVE_AS
: //另存为
//调用自定义函数,激活SAVE通用对话框
if (PopFileSaveDlg
(hwnd, szFileName, szTitleName))
{
//在窗口标题中加入刚命名的文件名和文件扩展名
DoCaption
(hwnd, szTitleName) ;
//调用自定义函数,将编辑控件中的文本,写入到 szFileName 参数中保存的文件路径中
if (PopFileWrite
(hwndEdit, szFileName))
{
//如果保存成功,设编辑控件内容未改变,返回1
bNeedSave = FALSE
;
return 1 ;
}
else
{
//如果保存失败,弹出消息框,返回0
OkMessage
(hwnd, TEXT ("Could not write file %s
"), szTitleName) ;
return 0 ;
}
}
return 0 ;
case IDM_FILE_PRINT
: //打印
//PopPrntPrintFile尚未定义直接返回FALSE,该语句用消息框提示信息
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 ;
//发送对应的消息给编辑控件
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) ; //如果LPARAM参数为-1,则表示选择全部
return 0 ;
case IDM_SEARCH_FIND
: //查找
//取得编辑控件中目前选择的起始位置和末尾超尾位置,将超尾位置记录在iOffset中
SendMessage
(hwndEdit, EM_GETSEL
, 0, (LPARAM) &iOffset) ;
//激活Find对话框,如果成功,hDlgModeless 保存对话框窗口句柄
hDlgModeless = PopFindFindDlg
(hwnd) ;
return 0 ;
case IDM_SEARCH_NEXT
: //查找下一个
//取得编辑控件中目前选择的起始位置和末尾超尾位置,将超尾位置记录在iOffset中
SendMessage
(hwndEdit, EM_GETSEL
, 0, (LPARAM) &iOffset) ;
//判断用于查找的字符串是否为空,不为空时返回TRUE
if (PopFindValidFind
())
//调用自定义函数,执行查找处理
PopFindNextText
(hwndEdit, &iOffset) ;
else
//如果用于查找的字符串为空,则激活Find对话框,hDlgModeless 保存对话框窗口句柄
hDlgModeless = PopFindFindDlg
(hwnd) ;
return 0 ;
case IDM_SEARCH_REPLACE
: //替换
SendMessage
(hwndEdit, EM_GETSEL
, 0, (LPARAM) &iOffset) ;
//激活Replace对话框,如果成功,hDlgModeless 保存对话框窗口句柄
hDlgModeless = PopFindReplaceDlg
(hwnd) ;
return 0 ;
case IDM_FORMAT_FONT
: //字体
//调用自定义函数,激活Font对话框。如果用户点击OK,便根据新字体重绘编辑控件内的文本
if (PopFontChooseFont
(hwnd))
PopFontSetFont
(hwndEdit) ;
return 0 ;
case IDM_HELP
: //调用自定义函数弹出HELP提示消息框
OkMessage
(hwnd, TEXT ("Help not yet implemented!
"),
TEXT ("/0
")) ;
return 0 ;
case IDM_APP_ABOUT
: //激活模态对话框 AboutBox ,挂钩到 AboutDlgProc 对话框程序
DialogBox
(hInst, TEXT ("AboutBox
"), hwnd, AboutDlgProc) ;
return 0 ;
}
break ;
case WM_CLOSE
: //关闭
/* 如果 bNeedSave 为FLASE,证明编辑控件中的内容未改变。根据逻辑运算符规则,
当 || 运算符的左边表达式成立时,便不会计算后面的表达式。
否者调用自定义函数,弹出询问消息框,用于保存数据。*/
if (!bNeedSave || IDCANCEL
!= AskAboutSave
(hwnd, szTitleName))
DestroyWindow
(hwnd) ; //向窗口消息处理程序发送一个WM_DESTROY消息
return 0 ;
case WM_QUERYENDSESSION
: //系统关闭时的广播消息
//如果文件不需要保存,或成功保存时,同意系统关机。
if (!bNeedSave || IDCANCEL
!= AskAboutSave
(hwnd, szTitleName))
return 1 ;
return 0 ;
case WM_DESTROY
:
PopFontDeinitialize
() ; //删除之前建立的逻辑字体对象
/* 让系统把WM_QUIT消息放入消息队列中,此消息不会到达窗口消息处理程序,
因为它使GetMessage传回0,并终止消息循环,从而也终止了程序。*/
PostQuitMessage
(0) ;
return 0 ;
default:
//执行查找和替换操作
if (message == messageFindReplace)
{
pfr = (LPFINDREPLACE) lParam ; //取出消息中的FINDREPLACE结构
//FR_DIALOGTERM: 表明对话框已经关闭.
//如果该标记存在,清空保存的窗口句柄
if (pfr->Flags & FR_DIALOGTERM
)
hDlgModeless = NULL
;
//FR_FINDNEXT: 表明用户在查找或替换对话框中点击了"查找下一个"按钮
if (pfr->Flags & FR_FINDNEXT
)
//调用自定义函数,执行查找处理,如果未查找到,弹出消息提示框
if (!PopFindFindText
(hwndEdit, &iOffset, pfr))
OkMessage
(hwnd, TEXT ("Text not found!
"),
TEXT ("/0
")) ;
//FR_REPLACE: 表明用户点击了替换对话框中的"替换"按钮
//FR_REPLACEALL:表明用户点击了替换对话框中的"全部替换替换"按钮
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) ;
}
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) ; //如果点击OK按钮则结束该对话框
return TRUE
;
}
break ;
}
return FALSE
;
}
/*------------------------------------------
POPFILE.C
-- Popup Editor File Functions
------------------------------------------*/
#include <windows.h>
#include <commdlg.h>
static OPENFILENAME ofn ;
void PopFileInitialize
(HWND hwnd)
{
/*第一个字符串是过滤器描述的显示字符串(例如,“文本文件”),
第二个字符指定过滤样式(例如,“*.TXT”)。
要为一个显示字符串指定多个过滤样式,使用分号(“;”)分隔样式(例如,“*.TXT;*.DOC;*.BAK”)。
一个样式字符串中可以包含有效的文件名字字符及星号(*)通配符。不能在样式字符串中包含空格。*/
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 ; //指向对话框所有者窗口的句柄
ofn.hInstance = NULL
; //自定义对话框模板资源被载入内存后的句柄
/*指向一对以空字符结束的过滤字符串的一个缓冲。缓冲中的最后一个字符串必须以两个NULL字符结束。*/
ofn.lpstrFilter = szFilter ;
/*指向一个静态缓冲,它包含了一对以空字符结束的过滤器字符串,这个字符串是为了保留用户选择的过滤样式.
在下一次对话框被建立时系统使用这个字符串去初始化用户自定义的文件过滤器*/
ofn.lpstrCustomFilter = NULL
;
/*指明lpstrCustomFilter以TCHARs为单位的缓冲大小。
ANSI版本是字节的个数;Unicode版本是字符的个数。这缓冲应该最小在40个字符长。*/
ofn.nMaxCustFilter = 0 ;
/*指定在文件类型控件中当前选择的过滤器的索引.
缓冲指向被lpstrFilter包含的一对定义了的过滤器的字符串。过滤器的第一对字符串的索引值为1,第二对为2,等等。
0索引指出是通过lpstrCustomFilter指定的定制过滤器.
你可以为对话框指定一个索引作为最初的过滤器描述及过滤器样式。
当用户选择了一个文件时,nFilterIndex返回当前显示的过滤器的索引。
如果nFilterIndex是0及lpstrCustomFilter是NULL,系统使用在lpstrFilter缓冲中的第一个过滤器。
如果所有的三个成员都是0或NULL,系统不使用任何过滤器,在对话框的列表文件中不显示任何文件。*/
ofn.nFilterIndex = 0 ;
/*指向包含初始化文件名编辑控件使用的文件名的缓冲。
如果不需要初始值,这个缓冲的第一个字符必须是NULL。
当GetOpenFileName或GetSaveFileName函数返回成功时,这个缓冲包含驱动器,路径,文件名,及所选择的文件的扩展名。*/
ofn.lpstrFile = NULL
;
/*指定lpstrFile以TCHARs为单位的缓冲大小。ANSI版本是字节的个数;Unicode版本是字符的个数。*/
ofn.nMaxFile = MAX_PATH
;
ofn.lpstrFileTitle = NULL
; //指向接收选择的文件的文件名和扩展名的缓冲(不带路径信息)
ofn.nMaxFileTitle = MAX_PATH
; //指定lpstrFileTitle以TCHARs为单位的缓冲大小。
ofn.lpstrInitialDir = NULL
; //指向以空字符结束的字符串,可以在这个字符串中指定初始目录。
/*指向在对话框的标题栏中放置的字符串。如果这个成员是NULL,系统使用默认标题(另存为或打开)*/
ofn.lpstrTitle = NULL
;
ofn.Flags = 0 ; //位标记的设置,可以使用来初始化对话框。当对话框返回时,它设置的这些标记指出用户的输入。
/*指定从路径开始到通过lpstrFile指定的文件名字符串基于0的偏移,以TCHARs为单位.
例如,如果lpstrFile指向下列的字符串,“c:/dir1/dir2/file.ext”,这个成员包含指出“file.ext”字符串偏移的位置值13.
如果用户选择了多于一个的文件,nFileOffset是到第一个文件名的偏移。*/
ofn.nFileOffset = 0 ;
/*指定从路径开始到通过lpstrFile指定的文件名字符串中扩展名基于0的偏移,以TCHARs为单位.
如果用户没有输入一个扩展名并且lpstrDefExt是NULL,这个成员指定的偏移是结束字符NULL。
如果用户在文件名中输入一个“.”作为最后的字符,这个成员是0。*/
ofn.nFileExtension = 0 ;
/*指向包含默认扩展名的缓冲。如果用户忘记输入扩展名,GetOpenFileName和GetSaveFileName附加这个扩展名到文件名中。
这个字符串可以是任一长度,但只有头三个字符被附加。字符串不包含一个句点(.)*/
ofn.lpstrDefExt = TEXT ("txt
") ;
/*自定义数据,该数据将被lpfnHook成员指出的钩子程序识别.
当系统发送WM_INITDIALOG消息到程序,消息的lParam参数指向当对话框建立时指定的OPENFILENAME结构。*/
ofn.lCustData = 0L ;
ofn.lpfnHook = NULL
; //指向一个钩子程序。除非Flags成员中包含OFN_ENABLEHOOK标记,否则该成员被忽略
/*指向一个以空字符结束的字符串,字符串是对话框模板资源的名字,资源保存在能被hInstance成员识别的模块中 */
ofn.lpTemplateName = NULL
;
}
BOOL PopFileOpenDlg
(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
{
ofn.hwndOwner = hwnd ;
//注意:参数 pstrFileName 是一个指针 ,ofn.lpstrFile 也是一个指针。
//这里的赋值操作,表明了ofn.lpstrFile 是一个指向 pstrFileName 指针的指针。
ofn.lpstrFile = pstrFileName ;
//ofn.lpstrFileTitle 是一个指向 pstrTitleName 指针的指针。
ofn.lpstrFileTitle = pstrTitleName ;
//OFN_HIDEREADONLY:隐藏只读复选框
//OFN_CREATEPROMPT:如果用户指定了一个不存在的文件,这个标记使用对话框能提示用户是否新建这个文件
ofn.Flags = OFN_HIDEREADONLY
| OFN_CREATEPROMPT
;
/* 该函数创建一个Open通用对话框.
如果用户指定了一个文件名,点击OK按钮,返回值为非零.
成功时OPENFILENAME结构的IPstrFile成员指向的缓冲区含有全路径和用户指定的文件名.
如果用户取消或关闭Open对话框或错误出现,返回值为零. */
return GetOpenFileName
(&ofn) ;
}
BOOL PopFileSaveDlg
(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
{
ofn.hwndOwner = hwnd ;
ofn.lpstrFile = pstrFileName ;
ofn.lpstrFileTitle = pstrTitleName ;
//如果选择的文件已经存在,则产生一个消息框。用户必须确认是否复盖这个文件。
ofn.Flags = OFN_OVERWRITEPROMPT
;
//该函数创建一个Save通用对话框,返回消息和 GetOpenFileName 类似
return GetSaveFileName
(&ofn) ;
}
BOOL PopFileRead
(HWND hwndEdit, PTSTR pstrFileName)
{
BYTE bySwap ;
DWORD dwBytesRead ;
HANDLE hFile ;
int i, iFileLength, iUniTest ;
PBYTE pBuffer, pText, pConv ;
//INVALID_HANDLE_VALUE表示出错
if (INVALID_HANDLE_VALUE
==
/* CreateFile(pstrFileName 要打开的文件名,GENERIC_READ 表示允许对设备进行读访问,
FILE_SHARE_READ 允许对文件进行共享读访问,
NULL 指向一个SECURITY_ATTRIBUTES结构的指针-定义了文件的安全特性,
OPEN_EXISTING 表示文件必须已经存在-向设备提出要求,0 不设置文件属性,
NULL 如果不为零-则指定一个文件句柄-新文件将从这个文件中复制扩展属性) */
// hFile 接受打开的文件句柄
(hFile = CreateFile
(pstrFileName, GENERIC_READ
, FILE_SHARE_READ
,
NULL
, OPEN_EXISTING
, 0, NULL
)))
return FALSE
; //如果打开文件失败,则返回 FALSE
/* GetFileSize(hFile 文件的句柄,
NULL 指定一个长整数,用于装载一个64位文件长度的头32位。如这个长度没有超过2^32字节,则该参数可以设为NULL) */
//iFileLength 接受文件的大小,单位为字节
iFileLength = GetFileSize
(hFile, NULL
) ;
//分配文件大小加2个字节的内存空间
pBuffer = malloc
(iFileLength + 2) ;
/* ReadFile(hFile 要读取的文件的句柄, pBuffer 用于保存读入数据的一个缓冲区,
iFileLength 要读入的字节数, &dwBytesRead 指向实际读取字节数的指针,
NULL 如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须用这个参数引用一个特殊的结构。
该结构定义了一次异步读取操作。否则,应将这个参数设为NULL) */
ReadFile
(hFile, pBuffer, iFileLength, &dwBytesRead, NULL
) ;
// 关闭打开的文件
CloseHandle
(hFile) ;
//在读取的文件数据末尾追加两个‘/0’,用于表明数据结尾
pBuffer[iFileLength] = '/0
' ;
pBuffer[iFileLength + 1] = '/0
' ;
/*初始化要检查项目
IS_TEXT_UNICODE_SIGNATURE:缓冲区文本含有Unicode字节顺序码(BOM)0XFEFF作为他的第一个字符
IS_TEXT_UNICODE_REVERSE_SIGNATURE: 缓冲区文本含有Unicode反向字节顺序码0XFFFE作为他的第一个字符 */
iUniTest = IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
/*IsTextUnicode(pBuffer 指明想检查的字符串地址。此数据是一个void指针,因为不确定是ANSI字符还是Unicode字符的数组,
iFileLength 指向要检查的字节数,由于不知道数据中的编码,所以该参数单位是字节计数而不是字符计数,
该参数检查的字节越多(当然不能才过数据本身),就越可能得到更精确的结果,
&iUniTest 之前初始化的一个整数的地址。对此整数进行初始化,指明你想让函数执行哪种检查。
也可以向此参数传递NULL,这种情况下函数会执行所有能做的检查)
如果函数认为数据包含的是Unicode文本,返回TRUE;否则,返回FALSE。
如果由参数&iUniTest所指向的整数来指定检查方式,函数会在每种检查之后将结果设置到此整数对应的位,然后再返回。 */
if (IsTextUnicode
(pBuffer, iFileLength, &iUniTest))
{ //如果是Unicode文本
// pText指向数据开始的第二个字符处,跳过文本的字符编码标记
pText = pBuffer + 2 ;
iFileLength -= 2 ;
//按位与操作,判断 IS_TEXT_UNICODE_REVERSE_SIGNATURE 检查项是否成立
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 ;
}
}
//分配新内存空间,大小为原来的数据大小,之前有 iFileLength -= 2 ;用于下面转换字符串编码
pConv = malloc (iFileLength + 2) ;
#ifndef UNICODE
//如果 UNICODE 没有被宏定义过,则执行(把宽字符串转化成它等价的多字节字符串)
/* WideCharToMultiByte(CP_ACP 指定执行转换的代码页(CP_ACP:ANSI代码页),
0 (第二个参数)允许指定附加控制,它影响字符的区分标记,如重音符号。通常不使用该标记,而把0传给它,
(PWSTR) pText 指向将被转换的unicode字符串,
-1 指定 (PWSTR) pText 参数指向的缓冲区的字符个数。
如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度,
pConv 指向接收被转换字符串的缓冲区,
iFileLength + 2 指定 pConv 参数指向的缓冲区最大值(字节)。
若此值为零,函数返回pConv参数指向的目标缓冲区所必需的字节数,
在这种情况下,pConv参数通常为NULL,
最后两个参数lpDefaultChar和pfUsedDefaultChar:
如果宽字节字符不能被转换,该函数便使用lpDefaultChar参数指向的字符。
如果该参数是NULL,那么该函数使用系统的默认字符,通常是个问号;
pfUsedDefaultChar参数指向一个布尔变量,如果Unicode字符串中至少有一个字符不能转换成等价多字节字符,
那么函数就将该变量置为TRUE。否则将该变量置为FALSE) */
WideCharToMultiByte
(CP_ACP
, 0, (PWSTR) pText, -1, pConv,
iFileLength + 2, NULL
, NULL
) ;
#else //如果 UNICODE 被宏定义过,则执行(复制pText字符串到pConv中)
lstrcpy
((PTSTR) pConv, (PTSTR) pText) ;
#endif //宏定义结束
}
else //如果 IsTextUnicode 检测结果为非 Unicode 文本
{
pText = pBuffer ;
//分配新内存空间,大小为原始数据的两倍,用于存储转换后的宽字符串
pConv = malloc
(2 * iFileLength + 2) ;
//如果程序使用了Unicode编码,而读取的文件是ASCII编码,则需要转换
#ifdef UNICODE
/* 该函数用法和 WideCharToMultiByte 差不多,用于将 ASCII 编码的字符串转换为 Unicode 编码,
只是取消了 参数lpDefaultChar和pfUsedDefaultChar */
MultiByteToWideChar
(CP_ACP
, 0, (PCSTR) pText, -1, (PTSTR) pConv,
iFileLength + 1) ;
#else //如果程序使用ASCII编码,则只需要复制数据即可
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 ;
WORD wByteOrderMark = 0xFEFF ; //Unicode字节顺序码
//以写方式打开文件,第三个参数 0 表示不允许共享访问,CREATE_ALWAYS 表示创建文件,会改写之前的文件
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) //如果内存分配失败,关闭文件,返回FALSE
{
CloseHandle
(hFile) ;
return FALSE
;
}
#ifdef UNICODE
//如果 UNICODE 被宏定义过,则执行
//该语句调用将Unicode字节顺序码写入文件开始处,表明了文件的编码形态。
/* WriteFile(hFile 要写入数据的文件句柄,&wByteOrderMark 要写入的数据缓冲区,
2 (参数三)要写入数据的字节数量。若为零,什么都不写入,但会更新文件的“上一次修改时间”。
针对位于远程系统的命名管道,限制在65535个字节以内,
&dwBytesWritten 实际写入文件的字节数量,
NULL (最后一个参数)倘若在指定FILE_FLAG_OVERLAPPED的前提下打开文件,该参数必须引用一个特殊的结构。
那个结构定义了一次异步写操作。否则,该参数应置为空(将声明变为ByVal As Long,并传递零值)) */
WriteFile
(hFile, &wByteOrderMark, 2, &dwBytesWritten, NULL
) ;
#endif //宏定义结束
//获取编辑控件中的文本到 pstrBuffer 缓冲区中,iLength + 1 指定要保存在缓冲区内的字符的最大个数,其中包含NULL字符。
GetWindowText
(hwndEdit, pstrBuffer, iLength + 1) ;
//写入数据到文件中
WriteFile
(hFile, pstrBuffer, iLength * sizeof (TCHAR),
&dwBytesWritten, NULL
) ;
//如果数据大小与实际写入的文件字节数不符,则返回FALSE
if ((iLength * sizeof (TCHAR)) != (int) dwBytesWritten)
{
CloseHandle
(hFile) ;
free
(pstrBuffer) ;
return FALSE
;
}
//关闭文件,释放分配的内存,返回TRUE
CloseHandle
(hFile) ;
free
(pstrBuffer) ;
return TRUE
;
}
/*--------------------------------------------------------
POPFIND.C
-- Popup Editor Search and Replace Functions
--------------------------------------------------------*/
#include <windows.h>
#include <commdlg.h>
#include <tchar.h> //提供了一系列的替代名称,用于自动调用通配目前程序所用字符集的函数和变量名(ASCII编码 或 Unicode编码)
#define MAX_STRING_LEN
256
static TCHAR szFindText [MAX_STRING_LEN
] ;
static TCHAR szReplText [MAX_STRING_LEN
] ;
HWND PopFindFindDlg
(HWND hwnd)
{
static FINDREPLACE fr ; /* 该结构必须是一个静态变量,因为对话框是非模态的,
函数在对话框显示之后传回,而不是在对话框结束之后传回;
而对话框程序必须仍然能够存取该结构 */
//该结构与 OPENFILENAME 结构十分相似,可以相互参考来分析
fr.lStructSize = sizeof (FINDREPLACE) ; //结构大小
fr.hwndOwner = hwnd ; //对话框拥有者的窗口句柄
fr.hInstance = NULL
; //自定义对话框模板资源被载入内存后的句柄
/* 对话框样式:隐藏向上向下、隐藏区分大小写、隐藏全字匹配 */
fr.Flags = FR_HIDEUPDOWN
| FR_HIDEMATCHCASE
| FR_HIDEWHOLEWORD
;
fr.lpstrFindWhat = szFindText ; //指定缓冲区,保存用于查找的字符串 (指向szFindText指针的指针)
fr.lpstrReplaceWith = NULL
; //指定缓冲区,保存用于替换的字符串
fr.wFindWhatLen = MAX_STRING_LEN
; //指定 fr.lpstrFindWhat 缓冲区的大小
fr.wReplaceWithLen = 0 ; //指定 fr.lpstrReplaceWith 缓冲区的大小
fr.lCustData = 0 ; //应用程序定义的数据
fr.lpfnHook = NULL
; //指向一个窗口函数的钩子程序
/* 指向一个以空字符结束的字符串,字符串是对话框模板资源的名字,资源保存在能被hInstance成员识别的模块中 */
fr.lpTemplateName = NULL
;
/* 激活一个系统定义的非模态Find对话框,FindText函数并不执行查找操作,
当用户点击查找时,对话框把FINDMSGSTRING己登记的信息传送到对话框窗口的窗口函数,
由于 fr.lpfnHook 为空,证明也没有钩子程序拦截执行查找操作,
所以查找操作实际是由 fr.hwndOwner 成员指向的窗口的窗口函数所处理。
FINDMSGSTRING信息的IParam参数包含一个指向FINDREPLACE结构的指针。
如果函数调用成功,返回值是对话框的窗口句柄;如果函数调用失败,返回值为NULL。 */
return FindText
(&fr) ;
}
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 ; //指定缓冲区,保存用于被替换的字符串 (指向szFindText指针的指针)
fr.lpstrReplaceWith = szReplText ; //指定缓冲区,保存用于替换的字符串 (指向szReplText指针的指针)
fr.wFindWhatLen = MAX_STRING_LEN
;
fr.wReplaceWithLen = MAX_STRING_LEN
;
fr.lCustData = 0 ;
fr.lpfnHook = NULL
;
fr.lpTemplateName = NULL
;
/* 激活一个系统定义的非模态Replace对话框,
ReplaceText函数并不执行文本替换操作,其运作方式与FindText函数类似。 */
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))))
//如果分配内存失败,返回FALSE
return FALSE
;
//取得编辑控件中的文本,保存到 pstrDoc 指向的内存中
GetWindowText
(hwndEdit, pstrDoc, iLength + 1) ;
/* 在字符串(pstrDoc + * piSearchOffset)中搜索另一个字符串(pfr->lpstrFindWhat),
若成功则返回一个指向后者第一次出现的位置,否则返回NULL
piSearchOffset 传递的是用户当前选择的文本的超尾位置,所以搜索会从超尾位置之后开始进行。*/
pstrPos = _tcsstr
(pstrDoc + * piSearchOffset, pfr->lpstrFindWhat) ;
free
(pstrDoc) ;
//如果没有找到要查找的字符串,则返回FALSE
if (pstrPos == NULL
)
return FALSE
;
// pstrPos 记录的是查找到的字符串第一个字符的首次出现位置
// iPos 记录查找到的字符串开始位置
// *piSearchOffset 记录查找到的字符串超尾位置
/* 分析:字符串以0开始索引,设 pstrPos 为10,pfr->lpstrFindWha 长度为5.
其 pfr->lpstrFindWha 在字符串中的位置便为10到14.
所以 *piSearchOffset 得到的必定是字符串的超尾位置。*/
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 ;
//调用自定义函数,执行查找处理,返回是否找到(FALSE或TRUE)
return PopFindFindText
(hwndEdit, piSearchOffset, &fr) ;
}
BOOL PopFindReplaceText
(HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)
{
//执行查找文本操作
if (!PopFindFindText
(hwndEdit, piSearchOffset, pfr))
return FALSE
;
//向编辑控件发送EM_REPLACESEL消息,使用LPARAM参数中字符串,替换当前选择的字符串。
SendMessage
(hwndEdit, EM_REPLACESEL
, 0, (LPARAM) pfr->lpstrReplaceWith) ;
return TRUE
;
}
BOOL PopFindValidFind (void)
{
//判断用于查找的字符串是否为空,返回BOOL值
return * szFindText != '/0
' ;
}
/*------------------------------------------
POPFONT.C
-- Popup Editor Font Functions
------------------------------------------*/
#include <windows.h>
#include <commdlg.h>
static LOGFONT logfont ;
static HFONT hFont ;
BOOL PopFontChooseFont
(HWND hwnd)
{
CHOOSEFONT cf ;
cf.lStructSize = sizeof (CHOOSEFONT) ; //结构大小
cf.hwndOwner = hwnd ; //指向对话框所有者窗口的句柄
cf.hDC = NULL
; //一个设备上下文句柄或信息的打印机,其将在对话框中列出的字体。
cf.lpLogFont = &logfont ; //用于初始化对话框中选择的字体,用户点击OK,该结构用于记录选择的字体信息
cf.iPointSize = 0 ;
//CF_INITTOLOGFONTSTRUCT: 使用结构的lpLogFont成员初始化对话框控件
//CF_SCREENFONTS:使对话框仅列出屏幕系统所支持的字体。
//CF_EFFECTS: 使对话框显示控制,允许用户指定删除线,下划线和文字的颜色选择
cf.Flags = CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS | CF_EFFECTS
;
cf.rgbColors = 0 ; //指定初始文本的颜色,并记录用户选择的文字颜色的RGB值
cf.lCustData = 0 ; //自定义程序数据
cf.lpfnHook = NULL
; //对话框窗口的钩子函数名
cf.lpTemplateName = NULL
; //自定义对话框模板资源的名称
cf.hInstance = NULL
; //自定义对话框模板资源被载入内存后的句柄
/* 如果CF_USESTYLE标志被指定,对话框使用此缓冲区中的数据来初始化组合框的字体风格.
用户点击OK,该缓冲区用于记录用户选择的字体风格(斜体,下划线,粗体等等) */
cf.lpszStyle = NULL
;
/* 指定字体类型,返回给对话框程序
BOLD_FONTTYPE: 字体为粗体的重量。此信息被复制在LOGFONT结构lfWeight成员,相当于FW_BOLD。
ITALIC_FONTTYPE: 斜体字体属性设置。此信息被复制在LOGFONT结构lfItalic成员。
REGULAR_FONTTYPE: 字体重量是正常的。此信息被复制在LOGFONT结构lfWeight成员,相当于FW_REGULAR。*/
cf.nFontType = 0 ;
cf.nSizeMin = 0 ; //可以选择的最小字体数值
cf.nSizeMax = 0 ; //可以选择的最大字体数值
/* 激活一个供用户选择逻辑字体属性的模态对话框。
用户点击OK,返回值为非零值;如果用户取消或关闭Font对话框或出现错误信息,返回值为零。*/
return ChooseFont
(&cf) ;
}
void PopFontInitialize
(HWND hwndEdit)
{ /*GetObject( GetStockObject (SYSTEM_FONT) 系统字体的逻辑对象句柄,
sizeof (LOGFONT) 要写到缓冲区的信息的字节数目,
(PTSTR) &logfont 该缓冲区将要检索指定图形对象的信息)
该语句取得一个依据系统字体建立的LOGFONT结构,由此建立了一个SYSTEM_FONT字体的副本。
因为最终该字体将被删除,而删除现有系统字体是不明智的。*/
GetObject
(GetStockObject
(SYSTEM_FONT
), sizeof (LOGFONT), (PTSTR) &logfont) ;
//创建一个系统字体的副本,返回值是该逻辑字体的句柄
hFont = CreateFontIndirect
(&logfont) ;
//向编辑控件发送字体更改消息,依据WPARAM参数来设置新字体。
SendMessage
(hwndEdit, WM_SETFONT
, (WPARAM) hFont, 0) ;
}
void PopFontSetFont
(HWND hwndEdit)
{
HFONT hFontNew ;
RECT rect ;
//根据用户选择的字体信息,创建一个逻辑字体对象,返回值是该逻辑字体的句柄
hFontNew = CreateFontIndirect
(&logfont) ;
//向编辑控件发送字体更改消息,依据WPARAM参数来设置新字体。
SendMessage
(hwndEdit, WM_SETFONT
, (WPARAM) hFontNew, 0) ;
DeleteObject
(hFont) ; //删除之前建立的逻辑字体对象
hFont = hFontNew ; //为下一次更改字体做准备
//取得编辑控件的矩形坐标,并使其重绘。
GetClientRect
(hwndEdit, &rect) ;
InvalidateRect
(hwndEdit, &rect, TRUE
) ;
}
void PopFontDeinitialize
(void)
{ //删除之前建立的逻辑字体对象
DeleteObject
(hFont) ;
}
/*---------------------------------------------------------------
POPPRNT0.C
-- Popup Editor Printing Functions (dummy version)
---------------------------------------------------------------*/
#include <windows.h>
BOOL PopPrntPrintFile
(HINSTANCE hInst, HWND hwnd, HWND hwndEdit, PTSTR pstrTitleName)
{
return FALSE
;
}
/*---------------------------------------------------------------
RESOURCE.H
---------------------------------------------------------------*/
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by poppad.rc
//
#define IDC_FILENAME
1000
#define IDM_FILE_NEW
40001
#define IDM_FILE_OPEN
40002
#define IDM_FILE_SAVE
40003
#define IDM_FILE_SAVE_AS
40004
#define IDM_FILE_PRINT
40005
#define IDM_APP_EXIT
40006
#define IDM_EDIT_UNDO
40007
#define IDM_EDIT_CUT
40008
#define IDM_EDIT_COPY
40009
#define IDM_EDIT_PASTE
40010
#define IDM_EDIT_CLEAR
40011
#define IDM_EDIT_SELECT_ALL
40012
#define IDM_SEARCH_FIND
40013
#define IDM_SEARCH_NEXT
40014
#define IDM_SEARCH_REPLACE
40015
#define IDM_FORMAT_FONT
40016
#define IDM_HELP
40017
#define IDM_APP_ABOUT
40018
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE
110
#define _APS_NEXT_COMMAND_VALUE
40019
#define _APS_NEXT_CONTROL_VALUE
1001
#define _APS_NEXT_SYMED_VALUE
101
#endif
#endif
/*---------------------------------------------------------------
POPPAD.RC
---------------------------------------------------------------*/
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL
) || defined(AFX_TARG_ENU
)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH
, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h/0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""/r/n"
"/0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"/r/n"
"/0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
ABOUTBOX DIALOG DISCARDABLE 32, 32, 180, 100
STYLE DS_MODALFRAME
| WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK
",IDOK
,66,80,50,14
ICON "POPPAD
",IDC_STATIC
,7,7,20,20
CTEXT "PopPad
",IDC_STATIC
,40,12,100,8
CTEXT "Popup Editor for Windows
",IDC_STATIC
,7,40,166,8
CTEXT "(c) Charles Petzold, 1998
",IDC_STATIC
,7,52,166,8
END
PRINTDLGBOX DIALOG DISCARDABLE 32, 32, 186, 95
STYLE DS_MODALFRAME
| WS_POPUP
| WS_VISIBLE
| WS_CAPTION
| WS_SYSMENU
CAPTION "PopPad
"
FONT 8, "MS Sans Serif"
BEGIN
PUSHBUTTON "Cancel
",IDCANCEL
,67,74,50,14
CTEXT "Sending
",IDC_STATIC
,8,8,172,8
CTEXT "",IDC_FILENAME
,8,28,172,8
CTEXT "to print spooler.
",IDC_STATIC
,8,48,172,8
END
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
POPPAD MENU DISCARDABLE
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 "&Replace.../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
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
POPPAD ACCELERATORS DISCARDABLE
BEGIN
VK_BACK, IDM_EDIT_UNDO
, VIRTKEY, ALT, NOINVERT
VK_DELETE, IDM_EDIT_CLEAR
, VIRTKEY, NOINVERT
VK_DELETE, IDM_EDIT_CUT
, VIRTKEY, SHIFT, NOINVERT
VK_F1, IDM_HELP
, VIRTKEY, NOINVERT
VK_F3, IDM_SEARCH_NEXT
, VIRTKEY, NOINVERT
VK_INSERT, IDM_EDIT_COPY
, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, IDM_EDIT_PASTE
, VIRTKEY, SHIFT, NOINVERT
"^C", IDM_EDIT_COPY
, ASCII, NOINVERT
"^F", IDM_SEARCH_FIND
, ASCII, NOINVERT
"^N", IDM_FILE_NEW
, ASCII, NOINVERT
"^O", IDM_FILE_OPEN
, ASCII, NOINVERT
"^P", IDM_FILE_PRINT
, ASCII, NOINVERT
"^R", IDM_SEARCH_REPLACE
, ASCII, NOINVERT
"^S", IDM_FILE_SAVE
, ASCII, NOINVERT
"^V", IDM_EDIT_PASTE
, ASCII, NOINVERT
"^X", IDM_EDIT_CUT
, ASCII, NOINVERT
"^Z", IDM_EDIT_UNDO
, ASCII, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
POPPAD ICON DISCARDABLE "poppad.ico"
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"ABOUTBOX
", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
"PRINTDLGBOX
", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
POPPAD.C
-- Popup Editor
(c) Charles Petzold, 1998
---------------------------------------*/
#include <windows.h>
#include <commdlg.h> //使用通用对话框,必须包含此头文件
#include "resource.h" //资源文件
#define EDITID
1
#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) ;
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) ;
HWND PopFindReplaceDlg
(HWND) ;
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) ;
// 全局变量
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))
{
//拦截快捷键消息
if (!TranslateAccelerator
(hwnd, hAccel, &msg))
{
TranslateMessage
(&msg) ;
DispatchMessage
(&msg) ;
}
}
}
return msg.wParam ;
}
void DoCaption
(HWND hwnd, TCHAR * szTitleName)
{
TCHAR szCaption[64 + MAX_PATH
] ;
//将窗口名和打开的文件路径拼接起来,如果未打开任何文件则显示(UNTITLED)
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
) //如果用户选择的YES,就向父窗口发送保存消息
//如果消息执行失败,根据程序设计,返回0,则将用户选择设为CANCEL
if (!SendMessage
(hwnd, WM_COMMAND
, IDM_FILE_SAVE
, 0))
iReturn = IDCANCEL
;
//返回用户选择
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 ;
//创建编辑控件的子窗口,ID为 EDITID
hwndEdit = CreateWindow
(TEXT ("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
) ;
//限制编辑控件最大只能输入32000个字符
SendMessage
(hwndEdit, EM_LIMITTEXT
, 32000, 0L) ;
PopFileInitialize
(hwnd) ; //初始化OPENFILENAME结构
PopFontInitialize
(hwndEdit) ; //创建系统字体副本,运用到编辑控件中
/*调用FindText函数前,必须调用该函数以得到FINDMSGSTRING信息的标识符,
对话框函数在用户点击FindNext按钮或对话框被关闭时利用此标识符传送信息。
FINDMSGSTRING信息的IParam参数包含一个指向FINDREPLACE结构的指针。*/
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) //LOWORD (lParam):弹出式菜单索引(从0开始) ;HIWORD (lParam):系统菜单为1,其它为0
{
case 1: // 编辑菜单
//如果编辑控件能够执行Undo动作,那么SendMessage呼叫传回非零值。在这种情况下,选项被启用;否则,选项无效化
EnableMenuItem
((HMENU) wParam, IDM_EDIT_UNDO
, //撤销
SendMessage
(hwndEdit, EM_CANUNDO
, 0, 0L) ? MF_ENABLED
: MF_GRAYED
) ;
//IsClipboardFormatAvailable 判断剪贴板上的数据,如果是CF_TEXT,则该函数返回值为true,否则为false
//剪贴板数据格式:CF_TEXT 以NULL结尾的ASCII字符的文本格式
EnableMenuItem
((HMENU) wParam, IDM_EDIT_PASTE
, //粘贴
IsClipboardFormatAvailable
(CF_TEXT
) ? MF_ENABLED
: MF_GRAYED
) ;
//向编辑控件发送EM_GETSEL消息,将得到目前选中的文字第一位和最后一位的超尾位置
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: // 搜索菜单
//如果非模态对话框(查找、替换)
未激活
,则有效,否则无效
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
:
// lParam:子窗口句柄;LOWORD (wParam):子窗口ID
// 判断条件:句柄不为空,消息是由编辑控件发出 。菜单发出的该消息 lParam 参数为0
if (lParam && LOWORD (wParam) == EDITID
)
{
switch (HIWORD (wParam)) // 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
{
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 ;
//调用自定义函数,激活OPEN通用对话框,如果成功返回非零
if (PopFileOpenDlg
(hwnd, szFileName, szTitleName))
{
/*如果打开文件成功,GetOpenFileName将ofn.lpstrFile成员指向的缓冲区,设置为含有全路径和用户指定的文件名,
ofn.lpstrFile 是一个指向 szFileName 指针的指针,所以szFileName将含有全路径和用户指定的文件名。
PopFileRead 读取打开的文件数据,并显示在编辑控件上。如果成功返回TRUE */
if (!PopFileRead
(hwndEdit, szFileName))
{
//如果读取文件失败,则弹出消息提示框,并将文件路径和文件名置空
OkMessage
(hwnd, TEXT ("Could not read file %s!
"),szTitleName) ;
szFileName[0] = '/0
' ;
szTitleName[0] = '/0
' ;
}
}
DoCaption
(hwnd, szTitleName) ; //设置窗口标题文字 szTitleName 为用户打开的文件名和扩展名
bNeedSave = FALSE
; //标记编辑控件内容为未改变
return 0 ;
case IDM_FILE_SAVE
: //保存
if (szFileName[0]) //如果文件路径存在
{ //调用自定义函数,保存编辑控件中的文本
if (PopFileWrite
(hwndEdit, szFileName))
{
//如果保存成功,设编辑控件内容未改变,返回1
bNeedSave = FALSE
;
return 1 ;
}
else
{
//如果保存失败,弹出消息框,返回0
OkMessage
(hwnd, TEXT ("Could not write file %s
"), szTitleName) ;
return 0 ;
}
}
//连续执行 如果文件路径为空,或者用户选择另存为菜单项
case IDM_FILE_SAVE_AS
: //另存为
//调用自定义函数,激活SAVE通用对话框
if (PopFileSaveDlg
(hwnd, szFileName, szTitleName))
{
//在窗口标题中加入刚命名的文件名和文件扩展名
DoCaption
(hwnd, szTitleName) ;
//调用自定义函数,将编辑控件中的文本,写入到 szFileName 参数中保存的文件路径中
if (PopFileWrite
(hwndEdit, szFileName))
{
//如果保存成功,设编辑控件内容未改变,返回1
bNeedSave = FALSE
;
return 1 ;
}
else
{
//如果保存失败,弹出消息框,返回0
OkMessage
(hwnd, TEXT ("Could not write file %s
"), szTitleName) ;
return 0 ;
}
}
return 0 ;
case IDM_FILE_PRINT
: //打印
//PopPrntPrintFile尚未定义直接返回FALSE,该语句用消息框提示信息
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 ;
//发送对应的消息给编辑控件
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) ; //如果LPARAM参数为-1,则表示选择全部
return 0 ;
case IDM_SEARCH_FIND
: //查找
//取得编辑控件中目前选择的起始位置和末尾超尾位置,将超尾位置记录在iOffset中
SendMessage
(hwndEdit, EM_GETSEL
, 0, (LPARAM) &iOffset) ;
//激活Find对话框,如果成功,hDlgModeless 保存对话框窗口句柄
hDlgModeless = PopFindFindDlg
(hwnd) ;
return 0 ;
case IDM_SEARCH_NEXT
: //查找下一个
//取得编辑控件中目前选择的起始位置和末尾超尾位置,将超尾位置记录在iOffset中
SendMessage
(hwndEdit, EM_GETSEL
, 0, (LPARAM) &iOffset) ;
//判断用于查找的字符串是否为空,不为空时返回TRUE
if (PopFindValidFind
())
//调用自定义函数,执行查找处理
PopFindNextText
(hwndEdit, &iOffset) ;
else
//如果用于查找的字符串为空,则激活Find对话框,hDlgModeless 保存对话框窗口句柄
hDlgModeless = PopFindFindDlg
(hwnd) ;
return 0 ;
case IDM_SEARCH_REPLACE
: //替换
SendMessage
(hwndEdit, EM_GETSEL
, 0, (LPARAM) &iOffset) ;
//激活Replace对话框,如果成功,hDlgModeless 保存对话框窗口句柄
hDlgModeless = PopFindReplaceDlg
(hwnd) ;
return 0 ;
case IDM_FORMAT_FONT
: //字体
//调用自定义函数,激活Font对话框。如果用户点击OK,便根据新字体重绘编辑控件内的文本
if (PopFontChooseFont
(hwnd))
PopFontSetFont
(hwndEdit) ;
return 0 ;
case IDM_HELP
: //调用自定义函数弹出HELP提示消息框
OkMessage
(hwnd, TEXT ("Help not yet implemented!
"),
TEXT ("/0
")) ;
return 0 ;
case IDM_APP_ABOUT
: //激活模态对话框 AboutBox ,挂钩到 AboutDlgProc 对话框程序
DialogBox
(hInst, TEXT ("AboutBox
"), hwnd, AboutDlgProc) ;
return 0 ;
}
break ;
case WM_CLOSE
: //关闭
/* 如果 bNeedSave 为FLASE,证明编辑控件中的内容未改变。根据逻辑运算符规则,
当 || 运算符的左边表达式成立时,便不会计算后面的表达式。
否者调用自定义函数,弹出询问消息框,用于保存数据。*/
if (!bNeedSave || IDCANCEL
!= AskAboutSave
(hwnd, szTitleName))
DestroyWindow
(hwnd) ; //向窗口消息处理程序发送一个WM_DESTROY消息
return 0 ;
case WM_QUERYENDSESSION
: //系统关闭时的广播消息
//如果文件不需要保存,或成功保存时,同意系统关机。
if (!bNeedSave || IDCANCEL
!= AskAboutSave
(hwnd, szTitleName))
return 1 ;
return 0 ;
case WM_DESTROY
:
PopFontDeinitialize
() ; //删除之前建立的逻辑字体对象
/* 让系统把WM_QUIT消息放入消息队列中,此消息不会到达窗口消息处理程序,
因为它使GetMessage传回0,并终止消息循环,从而也终止了程序。*/
PostQuitMessage
(0) ;
return 0 ;
default:
//执行查找和替换操作
if (message == messageFindReplace)
{
pfr = (LPFINDREPLACE) lParam ; //取出消息中的FINDREPLACE结构
//FR_DIALOGTERM: 表明对话框已经关闭.
//如果该标记存在,清空保存的窗口句柄
if (pfr->Flags & FR_DIALOGTERM
)
hDlgModeless = NULL
;
//FR_FINDNEXT: 表明用户在查找或替换对话框中点击了"查找下一个"按钮
if (pfr->Flags & FR_FINDNEXT
)
//调用自定义函数,执行查找处理,如果未查找到,弹出消息提示框
if (!PopFindFindText
(hwndEdit, &iOffset, pfr))
OkMessage
(hwnd, TEXT ("Text not found!
"),
TEXT ("/0
")) ;
//FR_REPLACE: 表明用户点击了替换对话框中的"替换"按钮
//FR_REPLACEALL:表明用户点击了替换对话框中的"全部替换替换"按钮
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) ;
}
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) ; //如果点击OK按钮则结束该对话框
return TRUE
;
}
break ;
}
return FALSE
;
}
/*------------------------------------------
POPFILE.C
-- Popup Editor File Functions
------------------------------------------*/
#include <windows.h>
#include <commdlg.h>
static OPENFILENAME ofn ;
void PopFileInitialize
(HWND hwnd)
{
/*第一个字符串是过滤器描述的显示字符串(例如,“文本文件”),
第二个字符指定过滤样式(例如,“*.TXT”)。
要为一个显示字符串指定多个过滤样式,使用分号(“;”)分隔样式(例如,“*.TXT;*.DOC;*.BAK”)。
一个样式字符串中可以包含有效的文件名字字符及星号(*)通配符。不能在样式字符串中包含空格。*/
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 ; //指向对话框所有者窗口的句柄
ofn.hInstance = NULL
; //自定义对话框模板资源被载入内存后的句柄
/*指向一对以空字符结束的过滤字符串的一个缓冲。缓冲中的最后一个字符串必须以两个NULL字符结束。*/
ofn.lpstrFilter = szFilter ;
/*指向一个静态缓冲,它包含了一对以空字符结束的过滤器字符串,这个字符串是为了保留用户选择的过滤样式.
在下一次对话框被建立时系统使用这个字符串去初始化用户自定义的文件过滤器*/
ofn.lpstrCustomFilter = NULL
;
/*指明lpstrCustomFilter以TCHARs为单位的缓冲大小。
ANSI版本是字节的个数;Unicode版本是字符的个数。这缓冲应该最小在40个字符长。*/
ofn.nMaxCustFilter = 0 ;
/*指定在文件类型控件中当前选择的过滤器的索引.
缓冲指向被lpstrFilter包含的一对定义了的过滤器的字符串。过滤器的第一对字符串的索引值为1,第二对为2,等等。
0索引指出是通过lpstrCustomFilter指定的定制过滤器.
你可以为对话框指定一个索引作为最初的过滤器描述及过滤器样式。
当用户选择了一个文件时,nFilterIndex返回当前显示的过滤器的索引。
如果nFilterIndex是0及lpstrCustomFilter是NULL,系统使用在lpstrFilter缓冲中的第一个过滤器。
如果所有的三个成员都是0或NULL,系统不使用任何过滤器,在对话框的列表文件中不显示任何文件。*/
ofn.nFilterIndex = 0 ;
/*指向包含初始化文件名编辑控件使用的文件名的缓冲。
如果不需要初始值,这个缓冲的第一个字符必须是NULL。
当GetOpenFileName或GetSaveFileName函数返回成功时,这个缓冲包含驱动器,路径,文件名,及所选择的文件的扩展名。*/
ofn.lpstrFile = NULL
;
/*指定lpstrFile以TCHARs为单位的缓冲大小。ANSI版本是字节的个数;Unicode版本是字符的个数。*/
ofn.nMaxFile = MAX_PATH
;
ofn.lpstrFileTitle = NULL
; //指向接收选择的文件的文件名和扩展名的缓冲(不带路径信息)
ofn.nMaxFileTitle = MAX_PATH
; //指定lpstrFileTitle以TCHARs为单位的缓冲大小。
ofn.lpstrInitialDir = NULL
; //指向以空字符结束的字符串,可以在这个字符串中指定初始目录。
/*指向在对话框的标题栏中放置的字符串。如果这个成员是NULL,系统使用默认标题(另存为或打开)*/
ofn.lpstrTitle = NULL
;
ofn.Flags = 0 ; //位标记的设置,可以使用来初始化对话框。当对话框返回时,它设置的这些标记指出用户的输入。
/*指定从路径开始到通过lpstrFile指定的文件名字符串基于0的偏移,以TCHARs为单位.
例如,如果lpstrFile指向下列的字符串,“c:/dir1/dir2/file.ext”,这个成员包含指出“file.ext”字符串偏移的位置值13.
如果用户选择了多于一个的文件,nFileOffset是到第一个文件名的偏移。*/
ofn.nFileOffset = 0 ;
/*指定从路径开始到通过lpstrFile指定的文件名字符串中扩展名基于0的偏移,以TCHARs为单位.
如果用户没有输入一个扩展名并且lpstrDefExt是NULL,这个成员指定的偏移是结束字符NULL。
如果用户在文件名中输入一个“.”作为最后的字符,这个成员是0。*/
ofn.nFileExtension = 0 ;
/*指向包含默认扩展名的缓冲。如果用户忘记输入扩展名,GetOpenFileName和GetSaveFileName附加这个扩展名到文件名中。
这个字符串可以是任一长度,但只有头三个字符被附加。字符串不包含一个句点(.)*/
ofn.lpstrDefExt = TEXT ("txt
") ;
/*自定义数据,该数据将被lpfnHook成员指出的钩子程序识别.
当系统发送WM_INITDIALOG消息到程序,消息的lParam参数指向当对话框建立时指定的OPENFILENAME结构。*/
ofn.lCustData = 0L ;
ofn.lpfnHook = NULL
; //指向一个钩子程序。除非Flags成员中包含OFN_ENABLEHOOK标记,否则该成员被忽略
/*指向一个以空字符结束的字符串,字符串是对话框模板资源的名字,资源保存在能被hInstance成员识别的模块中 */
ofn.lpTemplateName = NULL
;
}
BOOL PopFileOpenDlg
(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
{
ofn.hwndOwner = hwnd ;
//注意:参数 pstrFileName 是一个指针 ,ofn.lpstrFile 也是一个指针。
//这里的赋值操作,表明了ofn.lpstrFile 是一个指向 pstrFileName 指针的指针。
ofn.lpstrFile = pstrFileName ;
//ofn.lpstrFileTitle 是一个指向 pstrTitleName 指针的指针。
ofn.lpstrFileTitle = pstrTitleName ;
//OFN_HIDEREADONLY:隐藏只读复选框
//OFN_CREATEPROMPT:如果用户指定了一个不存在的文件,这个标记使用对话框能提示用户是否新建这个文件
ofn.Flags = OFN_HIDEREADONLY
| OFN_CREATEPROMPT
;
/* 该函数创建一个Open通用对话框.
如果用户指定了一个文件名,点击OK按钮,返回值为非零.
成功时OPENFILENAME结构的IPstrFile成员指向的缓冲区含有全路径和用户指定的文件名.
如果用户取消或关闭Open对话框或错误出现,返回值为零. */
return GetOpenFileName
(&ofn) ;
}
BOOL PopFileSaveDlg
(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
{
ofn.hwndOwner = hwnd ;
ofn.lpstrFile = pstrFileName ;
ofn.lpstrFileTitle = pstrTitleName ;
//如果选择的文件已经存在,则产生一个消息框。用户必须确认是否复盖这个文件。
ofn.Flags = OFN_OVERWRITEPROMPT
;
//该函数创建一个Save通用对话框,返回消息和 GetOpenFileName 类似
return GetSaveFileName
(&ofn) ;
}
BOOL PopFileRead
(HWND hwndEdit, PTSTR pstrFileName)
{
BYTE bySwap ;
DWORD dwBytesRead ;
HANDLE hFile ;
int i, iFileLength, iUniTest ;
PBYTE pBuffer, pText, pConv ;
//INVALID_HANDLE_VALUE表示出错
if (INVALID_HANDLE_VALUE
==
/* CreateFile(pstrFileName 要打开的文件名,GENERIC_READ 表示允许对设备进行读访问,
FILE_SHARE_READ 允许对文件进行共享读访问,
NULL 指向一个SECURITY_ATTRIBUTES结构的指针-定义了文件的安全特性,
OPEN_EXISTING 表示文件必须已经存在-向设备提出要求,0 不设置文件属性,
NULL 如果不为零-则指定一个文件句柄-新文件将从这个文件中复制扩展属性) */
// hFile 接受打开的文件句柄
(hFile = CreateFile
(pstrFileName, GENERIC_READ
, FILE_SHARE_READ
,
NULL
, OPEN_EXISTING
, 0, NULL
)))
return FALSE
; //如果打开文件失败,则返回 FALSE
/* GetFileSize(hFile 文件的句柄,
NULL 指定一个长整数,用于装载一个64位文件长度的头32位。如这个长度没有超过2^32字节,则该参数可以设为NULL) */
//iFileLength 接受文件的大小,单位为字节
iFileLength = GetFileSize
(hFile, NULL
) ;
//分配文件大小加2个字节的内存空间
pBuffer = malloc
(iFileLength + 2) ;
/* ReadFile(hFile 要读取的文件的句柄, pBuffer 用于保存读入数据的一个缓冲区,
iFileLength 要读入的字节数, &dwBytesRead 指向实际读取字节数的指针,
NULL 如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须用这个参数引用一个特殊的结构。
该结构定义了一次异步读取操作。否则,应将这个参数设为NULL) */
ReadFile
(hFile, pBuffer, iFileLength, &dwBytesRead, NULL
) ;
// 关闭打开的文件
CloseHandle
(hFile) ;
//在读取的文件数据末尾追加两个‘/0’,用于表明数据结尾
pBuffer[iFileLength] = '/0
' ;
pBuffer[iFileLength + 1] = '/0
' ;
/*初始化要检查项目
IS_TEXT_UNICODE_SIGNATURE:缓冲区文本含有Unicode字节顺序码(BOM)0XFEFF作为他的第一个字符
IS_TEXT_UNICODE_REVERSE_SIGNATURE: 缓冲区文本含有Unicode反向字节顺序码0XFFFE作为他的第一个字符 */
iUniTest = IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
/*IsTextUnicode(pBuffer 指明想检查的字符串地址。此数据是一个void指针,因为不确定是ANSI字符还是Unicode字符的数组,
iFileLength 指向要检查的字节数,由于不知道数据中的编码,所以该参数单位是字节计数而不是字符计数,
该参数检查的字节越多(当然不能才过数据本身),就越可能得到更精确的结果,
&iUniTest 之前初始化的一个整数的地址。对此整数进行初始化,指明你想让函数执行哪种检查。
也可以向此参数传递NULL,这种情况下函数会执行所有能做的检查)
如果函数认为数据包含的是Unicode文本,返回TRUE;否则,返回FALSE。
如果由参数&iUniTest所指向的整数来指定检查方式,函数会在每种检查之后将结果设置到此整数对应的位,然后再返回。 */
if (IsTextUnicode
(pBuffer, iFileLength, &iUniTest))
{ //如果是Unicode文本
// pText指向数据开始的第二个字符处,跳过文本的字符编码标记
pText = pBuffer + 2 ;
iFileLength -= 2 ;
//按位与操作,判断 IS_TEXT_UNICODE_REVERSE_SIGNATURE 检查项是否成立
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 ;
}
}
//分配新内存空间,大小为原来的数据大小,之前有 iFileLength -= 2 ;用于下面转换字符串编码
pConv = malloc (iFileLength + 2) ;
#ifndef UNICODE
//如果 UNICODE 没有被宏定义过,则执行(把宽字符串转化成它等价的多字节字符串)
/* WideCharToMultiByte(CP_ACP 指定执行转换的代码页(CP_ACP:ANSI代码页),
0 (第二个参数)允许指定附加控制,它影响字符的区分标记,如重音符号。通常不使用该标记,而把0传给它,
(PWSTR) pText 指向将被转换的unicode字符串,
-1 指定 (PWSTR) pText 参数指向的缓冲区的字符个数。
如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度,
pConv 指向接收被转换字符串的缓冲区,
iFileLength + 2 指定 pConv 参数指向的缓冲区最大值(字节)。
若此值为零,函数返回pConv参数指向的目标缓冲区所必需的字节数,
在这种情况下,pConv参数通常为NULL,
最后两个参数lpDefaultChar和pfUsedDefaultChar:
如果宽字节字符不能被转换,该函数便使用lpDefaultChar参数指向的字符。
如果该参数是NULL,那么该函数使用系统的默认字符,通常是个问号;
pfUsedDefaultChar参数指向一个布尔变量,如果Unicode字符串中至少有一个字符不能转换成等价多字节字符,
那么函数就将该变量置为TRUE。否则将该变量置为FALSE) */
WideCharToMultiByte
(CP_ACP
, 0, (PWSTR) pText, -1, pConv,
iFileLength + 2, NULL
, NULL
) ;
#else //如果 UNICODE 被宏定义过,则执行(复制pText字符串到pConv中)
lstrcpy
((PTSTR) pConv, (PTSTR) pText) ;
#endif //宏定义结束
}
else //如果 IsTextUnicode 检测结果为非 Unicode 文本
{
pText = pBuffer ;
//分配新内存空间,大小为原始数据的两倍,用于存储转换后的宽字符串
pConv = malloc
(2 * iFileLength + 2) ;
//如果程序使用了Unicode编码,而读取的文件是ASCII编码,则需要转换
#ifdef UNICODE
/* 该函数用法和 WideCharToMultiByte 差不多,用于将 ASCII 编码的字符串转换为 Unicode 编码,
只是取消了 参数lpDefaultChar和pfUsedDefaultChar */
MultiByteToWideChar
(CP_ACP
, 0, (PCSTR) pText, -1, (PTSTR) pConv,
iFileLength + 1) ;
#else //如果程序使用ASCII编码,则只需要复制数据即可
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 ;
WORD wByteOrderMark = 0xFEFF ; //Unicode字节顺序码
//以写方式打开文件,第三个参数 0 表示不允许共享访问,CREATE_ALWAYS 表示创建文件,会改写之前的文件
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) //如果内存分配失败,关闭文件,返回FALSE
{
CloseHandle
(hFile) ;
return FALSE
;
}
#ifdef UNICODE
//如果 UNICODE 被宏定义过,则执行
//该语句调用将Unicode字节顺序码写入文件开始处,表明了文件的编码形态。
/* WriteFile(hFile 要写入数据的文件句柄,&wByteOrderMark 要写入的数据缓冲区,
2 (参数三)要写入数据的字节数量。若为零,什么都不写入,但会更新文件的“上一次修改时间”。
针对位于远程系统的命名管道,限制在65535个字节以内,
&dwBytesWritten 实际写入文件的字节数量,
NULL (最后一个参数)倘若在指定FILE_FLAG_OVERLAPPED的前提下打开文件,该参数必须引用一个特殊的结构。
那个结构定义了一次异步写操作。否则,该参数应置为空(将声明变为ByVal As Long,并传递零值)) */
WriteFile
(hFile, &wByteOrderMark, 2, &dwBytesWritten, NULL
) ;
#endif //宏定义结束
//获取编辑控件中的文本到 pstrBuffer 缓冲区中,iLength + 1 指定要保存在缓冲区内的字符的最大个数,其中包含NULL字符。
GetWindowText
(hwndEdit, pstrBuffer, iLength + 1) ;
//写入数据到文件中
WriteFile
(hFile, pstrBuffer, iLength * sizeof (TCHAR),
&dwBytesWritten, NULL
) ;
//如果数据大小与实际写入的文件字节数不符,则返回FALSE
if ((iLength * sizeof (TCHAR)) != (int) dwBytesWritten)
{
CloseHandle
(hFile) ;
free
(pstrBuffer) ;
return FALSE
;
}
//关闭文件,释放分配的内存,返回TRUE
CloseHandle
(hFile) ;
free
(pstrBuffer) ;
return TRUE
;
}
/*--------------------------------------------------------
POPFIND.C
-- Popup Editor Search and Replace Functions
--------------------------------------------------------*/
#include <windows.h>
#include <commdlg.h>
#include <tchar.h> //提供了一系列的替代名称,用于自动调用通配目前程序所用字符集的函数和变量名(ASCII编码 或 Unicode编码)
#define MAX_STRING_LEN
256
static TCHAR szFindText [MAX_STRING_LEN
] ;
static TCHAR szReplText [MAX_STRING_LEN
] ;
HWND PopFindFindDlg
(HWND hwnd)
{
static FINDREPLACE fr ; /* 该结构必须是一个静态变量,因为对话框是非模态的,
函数在对话框显示之后传回,而不是在对话框结束之后传回;
而对话框程序必须仍然能够存取该结构 */
//该结构与 OPENFILENAME 结构十分相似,可以相互参考来分析
fr.lStructSize = sizeof (FINDREPLACE) ; //结构大小
fr.hwndOwner = hwnd ; //对话框拥有者的窗口句柄
fr.hInstance = NULL
; //自定义对话框模板资源被载入内存后的句柄
/* 对话框样式:隐藏向上向下、隐藏区分大小写、隐藏全字匹配 */
fr.Flags = FR_HIDEUPDOWN
| FR_HIDEMATCHCASE
| FR_HIDEWHOLEWORD
;
fr.lpstrFindWhat = szFindText ; //指定缓冲区,保存用于查找的字符串 (指向szFindText指针的指针)
fr.lpstrReplaceWith = NULL
; //指定缓冲区,保存用于替换的字符串
fr.wFindWhatLen = MAX_STRING_LEN
; //指定 fr.lpstrFindWhat 缓冲区的大小
fr.wReplaceWithLen = 0 ; //指定 fr.lpstrReplaceWith 缓冲区的大小
fr.lCustData = 0 ; //应用程序定义的数据
fr.lpfnHook = NULL
; //指向一个窗口函数的钩子程序
/* 指向一个以空字符结束的字符串,字符串是对话框模板资源的名字,资源保存在能被hInstance成员识别的模块中 */
fr.lpTemplateName = NULL
;
/* 激活一个系统定义的非模态Find对话框,FindText函数并不执行查找操作,
当用户点击查找时,对话框把FINDMSGSTRING己登记的信息传送到对话框窗口的窗口函数,
由于 fr.lpfnHook 为空,证明也没有钩子程序拦截执行查找操作,
所以查找操作实际是由 fr.hwndOwner 成员指向的窗口的窗口函数所处理。
FINDMSGSTRING信息的IParam参数包含一个指向FINDREPLACE结构的指针。
如果函数调用成功,返回值是对话框的窗口句柄;如果函数调用失败,返回值为NULL。 */
return FindText
(&fr) ;
}
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 ; //指定缓冲区,保存用于被替换的字符串 (指向szFindText指针的指针)
fr.lpstrReplaceWith = szReplText ; //指定缓冲区,保存用于替换的字符串 (指向szReplText指针的指针)
fr.wFindWhatLen = MAX_STRING_LEN
;
fr.wReplaceWithLen = MAX_STRING_LEN
;
fr.lCustData = 0 ;
fr.lpfnHook = NULL
;
fr.lpTemplateName = NULL
;
/* 激活一个系统定义的非模态Replace对话框,
ReplaceText函数并不执行文本替换操作,其运作方式与FindText函数类似。 */
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))))
//如果分配内存失败,返回FALSE
return FALSE
;
//取得编辑控件中的文本,保存到 pstrDoc 指向的内存中
GetWindowText
(hwndEdit, pstrDoc, iLength + 1) ;
/* 在字符串(pstrDoc + * piSearchOffset)中搜索另一个字符串(pfr->lpstrFindWhat),
若成功则返回一个指向后者第一次出现的位置,否则返回NULL
piSearchOffset 传递的是用户当前选择的文本的超尾位置,所以搜索会从超尾位置之后开始进行。*/
pstrPos = _tcsstr
(pstrDoc + * piSearchOffset, pfr->lpstrFindWhat) ;
free
(pstrDoc) ;
//如果没有找到要查找的字符串,则返回FALSE
if (pstrPos == NULL
)
return FALSE
;
// pstrPos 记录的是查找到的字符串第一个字符的首次出现位置
// iPos 记录查找到的字符串开始位置
// *piSearchOffset 记录查找到的字符串超尾位置
/* 分析:字符串以0开始索引,设 pstrPos 为10,pfr->lpstrFindWha 长度为5.
其 pfr->lpstrFindWha 在字符串中的位置便为10到14.
所以 *piSearchOffset 得到的必定是字符串的超尾位置。*/
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 ;
//调用自定义函数,执行查找处理,返回是否找到(FALSE或TRUE)
return PopFindFindText
(hwndEdit, piSearchOffset, &fr) ;
}
BOOL PopFindReplaceText
(HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)
{
//执行查找文本操作
if (!PopFindFindText
(hwndEdit, piSearchOffset, pfr))
return FALSE
;
//向编辑控件发送EM_REPLACESEL消息,使用LPARAM参数中字符串,替换当前选择的字符串。
SendMessage
(hwndEdit, EM_REPLACESEL
, 0, (LPARAM) pfr->lpstrReplaceWith) ;
return TRUE
;
}
BOOL PopFindValidFind (void)
{
//判断用于查找的字符串是否为空,返回BOOL值
return * szFindText != '/0
' ;
}
/*------------------------------------------
POPFONT.C
-- Popup Editor Font Functions
------------------------------------------*/
#include <windows.h>
#include <commdlg.h>
static LOGFONT logfont ;
static HFONT hFont ;
BOOL PopFontChooseFont
(HWND hwnd)
{
CHOOSEFONT cf ;
cf.lStructSize = sizeof (CHOOSEFONT) ; //结构大小
cf.hwndOwner = hwnd ; //指向对话框所有者窗口的句柄
cf.hDC = NULL
; //一个设备上下文句柄或信息的打印机,其将在对话框中列出的字体。
cf.lpLogFont = &logfont ; //用于初始化对话框中选择的字体,用户点击OK,该结构用于记录选择的字体信息
cf.iPointSize = 0 ;
//CF_INITTOLOGFONTSTRUCT: 使用结构的lpLogFont成员初始化对话框控件
//CF_SCREENFONTS:使对话框仅列出屏幕系统所支持的字体。
//CF_EFFECTS: 使对话框显示控制,允许用户指定删除线,下划线和文字的颜色选择
cf.Flags = CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS | CF_EFFECTS
;
cf.rgbColors = 0 ; //指定初始文本的颜色,并记录用户选择的文字颜色的RGB值
cf.lCustData = 0 ; //自定义程序数据
cf.lpfnHook = NULL
; //对话框窗口的钩子函数名
cf.lpTemplateName = NULL
; //自定义对话框模板资源的名称
cf.hInstance = NULL
; //自定义对话框模板资源被载入内存后的句柄
/* 如果CF_USESTYLE标志被指定,对话框使用此缓冲区中的数据来初始化组合框的字体风格.
用户点击OK,该缓冲区用于记录用户选择的字体风格(斜体,下划线,粗体等等) */
cf.lpszStyle = NULL
;
/* 指定字体类型,返回给对话框程序
BOLD_FONTTYPE: 字体为粗体的重量。此信息被复制在LOGFONT结构lfWeight成员,相当于FW_BOLD。
ITALIC_FONTTYPE: 斜体字体属性设置。此信息被复制在LOGFONT结构lfItalic成员。
REGULAR_FONTTYPE: 字体重量是正常的。此信息被复制在LOGFONT结构lfWeight成员,相当于FW_REGULAR。*/
cf.nFontType = 0 ;
cf.nSizeMin = 0 ; //可以选择的最小字体数值
cf.nSizeMax = 0 ; //可以选择的最大字体数值
/* 激活一个供用户选择逻辑字体属性的模态对话框。
用户点击OK,返回值为非零值;如果用户取消或关闭Font对话框或出现错误信息,返回值为零。*/
return ChooseFont
(&cf) ;
}
void PopFontInitialize
(HWND hwndEdit)
{ /*GetObject( GetStockObject (SYSTEM_FONT) 系统字体的逻辑对象句柄,
sizeof (LOGFONT) 要写到缓冲区的信息的字节数目,
(PTSTR) &logfont 该缓冲区将要检索指定图形对象的信息)
该语句取得一个依据系统字体建立的LOGFONT结构,由此建立了一个SYSTEM_FONT字体的副本。
因为最终该字体将被删除,而删除现有系统字体是不明智的。*/
GetObject
(GetStockObject
(SYSTEM_FONT
), sizeof (LOGFONT), (PTSTR) &logfont) ;
//创建一个系统字体的副本,返回值是该逻辑字体的句柄
hFont = CreateFontIndirect
(&logfont) ;
//向编辑控件发送字体更改消息,依据WPARAM参数来设置新字体。
SendMessage
(hwndEdit, WM_SETFONT
, (WPARAM) hFont, 0) ;
}
void PopFontSetFont
(HWND hwndEdit)
{
HFONT hFontNew ;
RECT rect ;
//根据用户选择的字体信息,创建一个逻辑字体对象,返回值是该逻辑字体的句柄
hFontNew = CreateFontIndirect
(&logfont) ;
//向编辑控件发送字体更改消息,依据WPARAM参数来设置新字体。
SendMessage
(hwndEdit, WM_SETFONT
, (WPARAM) hFontNew, 0) ;
DeleteObject
(hFont) ; //删除之前建立的逻辑字体对象
hFont = hFontNew ; //为下一次更改字体做准备
//取得编辑控件的矩形坐标,并使其重绘。
GetClientRect
(hwndEdit, &rect) ;
InvalidateRect
(hwndEdit, &rect, TRUE
) ;
}
void PopFontDeinitialize
(void)
{ //删除之前建立的逻辑字体对象
DeleteObject
(hFont) ;
}
/*---------------------------------------------------------------
POPPRNT0.C
-- Popup Editor Printing Functions (dummy version)
---------------------------------------------------------------*/
#include <windows.h>
BOOL PopPrntPrintFile
(HINSTANCE hInst, HWND hwnd, HWND hwndEdit, PTSTR pstrTitleName)
{
return FALSE
;
}
/*---------------------------------------------------------------
RESOURCE.H
---------------------------------------------------------------*/
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by poppad.rc
//
#define IDC_FILENAME
1000
#define IDM_FILE_NEW
40001
#define IDM_FILE_OPEN
40002
#define IDM_FILE_SAVE
40003
#define IDM_FILE_SAVE_AS
40004
#define IDM_FILE_PRINT
40005
#define IDM_APP_EXIT
40006
#define IDM_EDIT_UNDO
40007
#define IDM_EDIT_CUT
40008
#define IDM_EDIT_COPY
40009
#define IDM_EDIT_PASTE
40010
#define IDM_EDIT_CLEAR
40011
#define IDM_EDIT_SELECT_ALL
40012
#define IDM_SEARCH_FIND
40013
#define IDM_SEARCH_NEXT
40014
#define IDM_SEARCH_REPLACE
40015
#define IDM_FORMAT_FONT
40016
#define IDM_HELP
40017
#define IDM_APP_ABOUT
40018
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE
110
#define _APS_NEXT_COMMAND_VALUE
40019
#define _APS_NEXT_CONTROL_VALUE
1001
#define _APS_NEXT_SYMED_VALUE
101
#endif
#endif
/*---------------------------------------------------------------
POPPAD.RC
---------------------------------------------------------------*/
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL
) || defined(AFX_TARG_ENU
)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH
, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h/0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""/r/n"
"/0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"/r/n"
"/0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
ABOUTBOX DIALOG DISCARDABLE 32, 32, 180, 100
STYLE DS_MODALFRAME
| WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK
",IDOK
,66,80,50,14
ICON "POPPAD
",IDC_STATIC
,7,7,20,20
CTEXT "PopPad
",IDC_STATIC
,40,12,100,8
CTEXT "Popup Editor for Windows
",IDC_STATIC
,7,40,166,8
CTEXT "(c) Charles Petzold, 1998
",IDC_STATIC
,7,52,166,8
END
PRINTDLGBOX DIALOG DISCARDABLE 32, 32, 186, 95
STYLE DS_MODALFRAME
| WS_POPUP
| WS_VISIBLE
| WS_CAPTION
| WS_SYSMENU
CAPTION "PopPad
"
FONT 8, "MS Sans Serif"
BEGIN
PUSHBUTTON "Cancel
",IDCANCEL
,67,74,50,14
CTEXT "Sending
",IDC_STATIC
,8,8,172,8
CTEXT "",IDC_FILENAME
,8,28,172,8
CTEXT "to print spooler.
",IDC_STATIC
,8,48,172,8
END
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
POPPAD MENU DISCARDABLE
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 "&Replace.../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
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
POPPAD ACCELERATORS DISCARDABLE
BEGIN
VK_BACK, IDM_EDIT_UNDO
, VIRTKEY, ALT, NOINVERT
VK_DELETE, IDM_EDIT_CLEAR
, VIRTKEY, NOINVERT
VK_DELETE, IDM_EDIT_CUT
, VIRTKEY, SHIFT, NOINVERT
VK_F1, IDM_HELP
, VIRTKEY, NOINVERT
VK_F3, IDM_SEARCH_NEXT
, VIRTKEY, NOINVERT
VK_INSERT, IDM_EDIT_COPY
, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, IDM_EDIT_PASTE
, VIRTKEY, SHIFT, NOINVERT
"^C", IDM_EDIT_COPY
, ASCII, NOINVERT
"^F", IDM_SEARCH_FIND
, ASCII, NOINVERT
"^N", IDM_FILE_NEW
, ASCII, NOINVERT
"^O", IDM_FILE_OPEN
, ASCII, NOINVERT
"^P", IDM_FILE_PRINT
, ASCII, NOINVERT
"^R", IDM_SEARCH_REPLACE
, ASCII, NOINVERT
"^S", IDM_FILE_SAVE
, ASCII, NOINVERT
"^V", IDM_EDIT_PASTE
, ASCII, NOINVERT
"^X", IDM_EDIT_CUT
, ASCII, NOINVERT
"^Z", IDM_EDIT_UNDO
, ASCII, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
POPPAD ICON DISCARDABLE "poppad.ico"
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"ABOUTBOX
", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
"PRINTDLGBOX
", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
相关文章推荐
- windows程序设计 「PopPad3」之 POPPRNT.C 打印范例分析 笔记
- windows程序设计 之 「HEAD」范例分析笔记
- windows程序设计之 「DevCaps2.C」范例分析 笔记
- windows 程序设计之「NetTime.C」范例分析笔记
- Windows程序设计 BITBLT.C--STRETCH.C--BRICKS1.C--BRICKS2.C--BRICKS3.C 范例分析笔记
- windows 程序设计「StrProg」 范例分析笔记
- windows程序设计 之 「COLORS3.C 」范例分析笔记
- windows 程序设计之「NetTime.C」范例分析笔记
- windows程序设计「GRAFMENU.C」范例分析笔记
- windows程序设计「BLOWUP.C」范例分析笔记
- windows程序设计 之 「CLOCK」范例分析笔记
- Windows程序设计「MDIDemo」 范例分析笔记
- Windows程序设计 HELLOBIT.C -- SKETCH.C 范例分析笔记
- windows 程序设计之「TESTMCI.C」范例分析笔记
- windows程序设计 之 「KeyView1」范例算法分析 笔记
- windows 程序设计之「SINEWAVE.C」范例分析笔记
- windows程序设计「BITMASK.C」范例分析笔记
- windows 程序设计之「RECORD1.C」范例分析笔记
- windows 程序设计之「RECORD2.C」范例分析笔记
- windows程序设计「DIBHEADS.C」范例分析笔记