📄 多个文件的工程---增强poppad.txt
字号:
mov eax,offset szReplText
mov frReplaceDlg.lpstrReplaceWith,eax
mov frReplaceDlg.wFindWhatLen,MAX_STRING_LEN ;
mov frReplaceDlg.wReplaceWithLen,MAX_STRING_LEN ;
mov frReplaceDlg.lCustData,0 ;
mov frReplaceDlg.lpfnHook,NULL ;
mov frReplaceDlg.lpTemplateName,NULL ;
invoke ReplaceText,addr frReplaceDlg
ret
PopFindReplaceDlg endp
PopFindFindText proc hwndEdit:HWND,piSearchOffset:DWORD, pfr:DWORD
;FINDREPLACEA STRUCT
; lStructSize DWORD ?
; hwndOwner DWORD ?
; hInstance DWORD ?
; Flags DWORD ?
; lpstrFindWhat DWORD ?
; lpstrReplaceWith DWORD ?
; wFindWhatLen WORD ?
; wReplaceWithLen WORD ?
; lCustData DWORD ?
; lpfnHook DWORD ?
; lpTemplateName DWORD ?
;FINDREPLACEA ENDS
LOCAL iLength, iPos:DWORD
LOCAL pstrDoc, pstrPos:PTSTR
;Read in the edit document
invoke GetWindowTextLength,hwndEdit
mov iLength,eax
inc eax
mov ecx,sizeof (TCHAR)
mul ecx
invoke LocalAlloc,LMEM_FIXED or LMEM_ZEROINIT,eax
.if eax==NULL
mov eax,FALSE
ret
.else
mov pstrDoc,eax
.endif
invoke GetWindowText,hwndEdit, pstrDoc, iLength + 1
;Search the document for the find string
mov esi,pfr
mov eax,[esi+16] ;pfr->lpstrFindWhat
mov esi,piSearchOffset
mov ebx,[esi]
add ebx,pstrDoc
invoke StrStr,ebx,eax
;pstrPos = _tcsstr (pstrDoc + * piSearchOffset, eax) ;
mov pstrPos,eax
invoke LocalFree,pstrDoc
;Return an error code if the string cannot be found
.if (pstrPos == NULL)
mov eax,FALSE
ret
.endif
;Find the position in the document and the new start offset
mov eax,pstrPos
sub eax,pstrDoc
mov iPos,eax
;invoke wsprintf,addr szReplText,CTEXT("%d"),iPos
;invoke MessageBox,hwndEdit,addr szReplText,NULL,MB_OK
mov esi,pfr
mov eax,[esi+16] ;pfr->lpstrFindWhat
invoke lstrlen,eax
add eax,iPos
mov esi,piSearchOffset
mov [esi],eax
;Select the found text
invoke SendMessage,hwndEdit, EM_SETSEL, iPos,eax
invoke SendMessage,hwndEdit, EM_SCROLLCARET, 0, 0
mov eax,TRUE
ret
PopFindFindText endp
PopFindNextText proc hwndEdit:HWND, piSearchOffset:DWORD
LOCAL fr:FINDREPLACE
mov eax,offset szFindText
mov fr.lpstrFindWhat,eax
invoke PopFindFindText,hwndEdit, piSearchOffset,addr fr
ret
PopFindNextText endp
PopFindReplaceText proc hwndEdit:HWND,piSearchOffset:DWORD, pfr:DWORD
;Find the text
invoke PopFindFindText,hwndEdit, piSearchOffset, pfr
.if (eax==FALSE)
mov eax,FALSE
ret
.endif
;Replace it
mov esi,pfr
invoke SendMessage,hwndEdit, EM_REPLACESEL, 0, [esi+20]
mov eax,TRUE
ret
PopFindReplaceText endp
PopFindValidFind proc
mov eax,TRUE
mov bl,szFindText[0]
cmp bl,0
jz @f
mov eax,FALSE
@@:
ret
PopFindValidFind endp
end
POPPAD.RC
#include "resource.h"
#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
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
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"
POPPAD.ICO
POPPAD.ASM 包含了程序中所有的基本原始码。POPFILE.ASM 具有启动File Open和File Save对话框的程序代码,它还包含文件I/O例程。POPFIND.ASM 中包含了搜寻和替换文字功能。POPFONT.ASM 包含了字体选择功能。
让我们先来看一看POPPAD.ASM 。POPPAD.ASM 含有两个文件名字符串:第一个,储存在WndProc,名称为szFileName,含有详细的驱动器名称、路径名称和文件名称;第二个,储存为szTitleName,是程序本身的文件名称。它用在POPPAD3的DoCaption函数中,以便将文件名称显示在窗口的标题列上;也用在OKMessage函数和AskAboutSave函数中,以便向使用者显示消息框。
POPFILE.ASM 包含了几个显示「File Open」和「File Save」对话框以及实际执行文件I/O的函数。对话框是使用函数GetOpenFileName和GetSaveFileName来显示的。这两个函数都使用一个型态为OPENFILENAME的结构,这个结构在WINDOWS.INC中定义。在POPFILE.ASM中,使用了一个该结构型态的整体变量,取名为ofn。ofn的大多数字段在PopFileInitialize函数中被初始化,POPPAD.ASM在WndProc中处理WM_CREATE消息时呼叫该函数。
将ofn作为静态整体结构变量会比较方便,因为GetOpenFileName和GetSaveFileName给该结构传回的一些信息,并将在以后呼叫这些函数时用到。
尽管通用对话框具有许多选项-包括设定自己的对话框模板,以及为对话框程序增加「挂勾(hook)」-POPFILE.ASM中使用的「File Open」和「File Save」对话框是最基本的。OPENFILENAME结构中被设定的字段只有lStructSize(结构的长度)、hwndOwner(对话框拥有者)、lpstrFilter(下面将简要讨论)、lpstrFile和nMaxFile(指向接收完整文件名称的缓冲区指标和该缓冲区的大小)、lpstrFileTitle和nMaxFileTitle(文件名称缓冲区及其大小)、Flags(设定对话框的选项)和lpstrDefExt(如果使用者在对话框中输入文件名时不指定文件扩展名,那么它就是内定的文件扩展名)。
当使用者在「File」菜单中选择「Open」时,POPPAD3呼叫POPFILE的PopFileOpenDlg函数,将窗口句柄、一个指向文件名称缓冲区的指标和一个指向文件标题缓冲区的指标传给它。PopFileOpenDlg恰当地设定OPENFILENAME结构的hwndOwner、lpstrFile和lpstrFileTitle字段,将Flags设定为OFN_ CREATEPROMPT,然后呼叫GetOpenFileName,显示如图11-6所示的普通对话框。
图11-6 「File Open」对话框
当使用者结束这个对话框时,GetOpenFileName函数传回。OFN_CREATEPROMPT旗标指示GetOpenFileName显示一个消息框,询问使用者如果所选文件不存在,是否要建立该文件。
左下角的下拉式清单方块列出了将要显示在文件列表中的文件型态,此清单方块被称为「筛选清单」。使用者可以通过从下拉式清单方块列表中选择另一种文件型态,来改变筛选条件。在POPFILE.ASM的PopFileInitialize函数中,我在变量szFilter(一个字符串数组)中为三种型态的文件定义了一个筛检清单:带有.TXT扩展名的文本文件、带有.ASC扩展名的ASCII文件和所有文件。OPENFILENAME结构的lpstrFilter字段储存指向此数组第一个字符串的指针。
如果使用者在对话框处于活动状态时改变了筛选条件,那么OPENFILENAME的nFilterIndex字段反映出使用者的选择。由于该结构是静态变量,下次启动对话框时,筛选条件将被设定为选中的文件型态。
POPFILE.C中的PopFileSaveDlg函数与此类似,它将Flags参数设定为OFN_OVERWRITEPROMPT,并呼叫GetSaveFileName启动「File Save」对话框。OFN_OVERWRITEPROMPT旗标导致显示一个消息框,如果被选文件已经存在,那么将询问使用者是否覆盖该文件。
Unicode文件I/O
对于本书中的大多数程序,您都不必注意Unicode和非Unicode版的区别。例如,在POPPAD3的Unicode中,编辑控件将保留Unicode文字和使用Unicode字符串的所有通用对话框。例如,当程序需要搜索和替换时,所有的操作都会处理Unicode字符串,而不需要转换。
不过,POPPAD3得处理文件I/O,也就是说,程序不能闭门造车。如果Unicode版的POPPAD3获得了编辑缓冲区的内容并将其写入磁盘,文件将是使用Unicode存放的。如果非Unicode版的POPPAD3读取了该文件,并将其写入编辑缓冲区,其结果将是一堆垃圾。Unicode版读取由非Unicode版储存的文件时也会这样。
解决的办法在于辨别和转换。首先,在POPFILE.C的PopFileWrite函数中,您将看到Unicode版的程序将在文件的开始位置写入0xFEFF。这定义为字节顺序标记,以表示文本文件含有Unicode文字。
其次,在PopFileRead函数中,程序用IsTextUnicode函数来决定文件是否含有字节顺序标记。此函数甚至检测字节顺序标记是否反向了,亦即Unicode文本文件在Macintosh或者其它使用与Intel处理器相反的字节顺序的机器上建立的。这时,字节的顺序都经过翻转。如果文件是Unicode版,但是被非Unicode版的POPPAD3读取,这时,文字将被WideCharToMultiChar转换。WideCharToMultiChar实际上是一个宽字符ANSI函数(除非您执行远东版的Windows)。只有这时文字才能放入编辑缓冲区。
同样地,如果文件是非Unicode文本文件,而执行的是Unicode版的程序,那么文字必须用MultiCharToWideChar转换。
改变字体
我们将在后面一期中详细讨论字体,但那些都不能代替通用对话框函数来选择字体。
在WM_CREATE消息处理期间,POPFONT.C中的POPPAD呼叫PopFontInitialize。这个函数取得一个依据系统字体建立的LOGFONT结构,由此建立一种字体,并向编辑控件发送一个WM_SETFONT消息来设定一种新的字体(内定编辑控件字体是系统字体,而PopFontInitialize为编辑控件建立一种新的字体,因为最终该字体将被删除,而删除现有系统字体是不明智的)。
当POPPAD收到来自程序的字体选项的WM_COMMAND消息时,它呼叫PopFontChooseFont。这个函数初始化一个CHOOSEFONT结构,然后呼叫ChooseFont显示字体选择对话框。如果使用者按下「OK」按钮,那么ChooseFont将传回TRUE。随后,POPPAD呼叫PopFontSetFont来设定编辑控件中的新字体,旧字体将被删除。
最后,在WM_DESTROY消息处理期间,POPPAD呼叫PopFontDeinitialize来删除最近一次由PopFontSetFont建立的字体。
搜寻与替换
通用对话框链接库也提供两个用于文字搜寻和替换函数的对话框,这两个函数(FindText和ReplaceText)使用一个型态为FINDREPLACE的结构。图10-11中所示的POPFIND.ASM文件有两个例程(PopFindFindDlg和PopFindReplaceDlg)呼叫这些函数,还有两个函数在编辑控件中搜寻和替换文字。
使用搜寻和替换函数有一些考虑。首先,它们启动的对话框是非模态对话框,这意味着必须改写消息循环,以便在对话框活动时呼叫IsDialogMessage。第二,传送给FindText和ReplaceText的FINDREPLACE结构必须是一个静态变量,因为对话框是模态的,函数在对话框显示之后传回,而不是在对话框结束之后传回;而对话框程序必须仍然能够存取该结构。
第三,在显示FindText和ReplaceText对话框时,它们通过一条特殊消息与拥有者窗口联络,消息编号可以通过以FINDMSGSTRING为参数呼叫RegisterWindowMessage函数来获得。这是在WndProc中处理WM_CREATE消息时完成的,消息号存放在静态变量中。
在处理内定消息时,WndProc将消息变量与RegisterWindowMessage传回的值相比较。lParam消息参数是一个指向FINDREPLACE结构的指针,Flags字段指示使用者使用对话框是为了搜寻文字还是替换文字,以及是否要终止对话框。POPPAD3是呼叫POPFIND.ASM中的PopFindFindText和PopFindReplaceText函数来执行搜寻和替换功能的。
--------------------------------------------------------------------------------
<<<上一篇 欢迎访问AoGo汇编小站:http://www.aogosoft.com 下一篇>>>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -