ICZelion Tut34

zhaozj2021-02-11  192

Tutorial 34: Richedit Control: More Text Operations

You'll Learn More About Text Operations Under Richedit Control. Specify, You'll Know How To Search for / Replace Text, Jumping To Specific Line Number.

Download The Example.

THEORY

Searching for text

TheRe Several Text Operations Under Richedit Control. Searching for Text Is Done by Sending Em_FindText or EM_FINDTEXTEX. These Messages Has A Small Difference.

EM_FINDTEXT

WPARAM == Search Options. can be any combination of the value in the table below.these Options Are Identical For Both

EM_FINDTEXT AND EM_FINDTEXTEX

FR_DOWNIf this flag is specified, the search starts from the end of the current selection to the end of the text in the control (downward) This flag has effect only for RichEdit 2.0 or later:. This behavior is the default for RichEdit 1.0 The. default behavior of RichEdit 2.0 or later is to search from the end of the current selection to the beginning of the text (upward) .In summary, if you use RichEdit 1.0, you can not do anything about the search direction: it always searches downward. If you use RichEdit 2.0 and you want to search downward, you must specify this flag else the search would be upward.FR_MATCHCASEIf this flag is specified, the search is case-sensitive.FR_WHOLEWORDIf this flag is set, the search finds the whole Word That Matches The Specified Search String.

Actually, There Are A Few More Flags But They Are Relevant To Non-English Languages.

LPARAM == Pointer to the FindText Structure.

Findtext struct

CHRG Charrange <>

LPSTRTEXT DWORD?

FindText Ends

Chrg Is a Charrange Structure Which is defined as Follows:

Charrange struct

CPMIN DWORD? CPMAX DWORD?

Charrange Ends

Cpmin contains the character in the character array (range).

CPMAX Contains The Character Index of The Character Immediely Following The Last Character in The Character Array.

In Essence, To Search for a Text String, You Have to Specify The Character Range In Which To Search. The meaning of cpmin

And cpmax diffording to WHETHER THETY IS DOWNWARD or UPWARD. IF The search is Downward, CPMIN

Specifies The Starting Character Index To Search In and Cpmax The Ending Character Index. if The Search IS Upward, The Search Is Upward, The

Reverse is true, ie. cpmin contains the ending character index while cpmax the starting character index.

LPSTRTEXT IS The Pointer To The Text String to Search for.

EM_FINDTEXT RETURns The Character Index of The First Character in The matching text string in the richedit control. It Returns -1 IF

No match is found.

EM_FINDTEXTEX

WPARAM == The Search Options. Same As Those of EM_FINDTEXT.

LPARAM == Pointer to the Findtextex Structure.

FindtexTex Struct

CHRG Charrange <>

LPSTRTEXT DWORD?

Chrgtext Charrange <>

FindtexTex Ends

THE FIRST TWO MEMBERS OF FINDTEXTEX THOSE OF FINDTEXT STRUCTURE. Chrgtext Is A Charrange Structure That Will

BE Filled with the starting / ending characterindices if a match is found.

The return value of em_findtextex is the Same as this of em_findtext.

The Difference Between EM_FINDTEXT AND EM_FINDTEXTEX IS That The Findtextex Structure Has An Additional MEMBER,

Chrgtext, Which Will Be Filled with The Starting / Ending Character Indices IF A Match Is Found. This is Convenient IF WA WANT To DO

More text operations on the string.replace / insert text

Richedit Control Provides EM_SETTEXTEX for Replacing / Inserting Text. This Message Combines The FunctionAlity Of WM_SETTEXT AND EM_REPLACESEL. IT HAS The FOLLOWING SYNTAX:

EM_SETTEXTEX

WPARAM == Pointer to settextex structure.

Settextex struct

Flags DWORD?

CodePage DWORD?

SetTexTex Ends

Flags Can Be The Combination of The Following Values:

ST_DEFAULTDELETES The undo stack, discards rich-text formatting, replaces all text.st_keepundokeeps the undo stackst_selectionReplaces Selection and Keeps Rich-text Formatting

.

Text Selection

We can select the text programmatically with EM_SETSEL or EM_EXSETSEL. Either one works fine. Choosing which message to use depends on the available format of the character indices. If they are already stored in a CHARRANGE structure, it's easier to use EM_EXSETSEL.

EM_EXSETSEL

WPARAM == NOT USED. Must BE 0

LPARAM == Pointer to a Charrange Structure That Contains the Character Range to Be SELECTED.

Event notification

In the case of a multiline edit control, you have to subclass it in order to obtain the input messages such as mouse / keyboard events. RichEdit control provides a better scheme that will notify the parent window of such events. In order to register for notifications , The Parent WinDow Sends Em_seteventmask Message To The Richedit Control, Specifying Which Events It's INTERESTED IN. EM_SETEVENTMASK HAS THE FOLLOWING SYNTAX:

EM_SETEVENTMASK

WPARAM == NOT USED. Must BE 0

. LParam == event mask value It can be the combination of the flags in the table below.ENM_CHANGESends EN_CHANGE notificationsENM_CORRECTTEXTSends EN_CORRECTTEXT notificationsENM_DRAGDROPDONESends EN_DRAGDROPDONE notificationsENM_DROPFILESSends EN_DROPFILES notifications.ENM_KEYEVENTSSends EN_MSGFILTER notifications for keyboard eventsENM_LINKRich Edit 2.0 and later: Sends EN_LINK notifications when the mouse pointer is over text that has the CFE_LINK and one of several mouse actions is performed.ENM_MOUSEEVENTSSends EN_MSGFILTER notifications for mouse eventsENM_OBJECTPOSITIONSSends EN_OBJECTPOSITIONS notificationsENM_PROTECTEDSends EN_PROTECTED notificationsENM_REQUESTRESIZESends EN_REQUESTRESIZE notificationsENM_SCROLLSends EN_HSCROLL and EN_VSCROLL notificationsENM_SCROLLEVENTSSends EN_MSGFILTER notifications for mouse wheel eventsENM_SELCHANGESends EN_SELCHANGE notificationsENM_UPDATE Sends EN_UPDATE notifications.Rich Edit 2.0 and later: this flag Is Ignored and The En_Update Noti Fications Are Always Sent. However, IF Rich Edit 3.0 Emulates Rich Edit 1.0, You Must Use this flag to send en_update notification

All the above notifications will be sent as WM_NOTIFY message: you have to check the code member of NMHDR structure for the notification message For example, if you want to register for mouse events. (Eg you want to provide a context sensitive popup menu.) You Must Do Something Like this:

Invoke SendMask, Hwndrichedit, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS

.....

.....

WNDPROC PROC HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

.....

....

.ELSEIF uMSG == WM_NOTIFY

PUSH ESI

Mov ESI, LPARAM

Assume ESI: PTR NMHDR

.IF [ESI] .code == en_msgfilter

....

[Do Something Here]

....

.endifpop ESI

EXAMPLE:

The following example is the update of IczEdit in tutorial no. 33. It adds search / replace functionality and accelerator keys to the program. It also processes the mouse events and provides a popup menu on right mouse click.

.386

.Model flat, stdcall

Option CaseMAP: NONE

INCLUDE /MASM32/INCLUDE/Windows.inc

INCLUDE /MASM32/INCLUDE/USER32.INC

INCLUDE /MASM32/INCLUDE/COMDLG32.INC

INCLUDE /MASM32/INCLUDE/gdi32.inc

INCLUDE /MASM32/INCLUDE / WANEL32.INC

INCLUDELIB /MASM32/LIB/GDI32.LIB

INCLUDELIB /MASM32/LIB/COMDLG32.LIB

INCLUDELIB /MASM32/LIB/USER32.LIB

INCLUDELIB /MASM32/LIB/kernel32.lib

Winmain Proto: DWORD,: DWORD,: DWORD,: DWORD

.const

IDR_MAINMENU EQU 101

IDM_Open EQU 40001

IDM_SAVE EQU 40002

IDM_Close EQU 40003

IDM_SAVEAS EQU 40004

IDM_EXIT EQU 40005

IDM_COPY EQU 40006

IDM_CUT EQU 40007

IDM_PASTE EQU 40008

IDM_DELETE EQU 40009

IDM_SELECTALL EQU 40010

IDM_OPTION EQU 40011

IDM_UNDO EQU 40012

IDM_REDO EQU 40013

IDD_OPTIONDLG EQU 101

IDC_BACKCOLORBOX EQU 1000

IDC_TextColorBox EQU 1001

IDR_MAINACCEL EQU 105

IDD_FINDDLG EQU 102

IDD_GOTODLG EQU 103

IDD_REPLACEDLG EQU 104

IDC_FindEdit EQU 1000

IDC_MatchCase EQU 1001

IDC_ReplaceEdit EQU 1001

IDC_WholeWord EQU 1002

IDC_DOWN EQU 1003

IDC_UP EQU 1004

IDC_LINENO EQU 1005IDM_FIND EQU 40014

IDM_FINDNEXT EQU 40015

IDM_REPLACE EQU 40016

IDM_GOTOLINE EQU 40017

IDM_FINDPREV EQU 40018

Richeditid EQU 300

.DATA

ClassName DB "iczeditclass", 0

Appname DB "iczedit Version 2.0", 0

Richeditdll DB "Riched20.dll", 0

Richeditclass DB "Richedit20a", 0

Norichedit DB "Cannot Find Riched20.dll", 0

Asmfilterstring DB "ASM Source Code (* .asm)", 0, "*. ASM", 0

DB "all files (*. *)", 0, "*. *", 0, 0

OpenFileFail DB "Cannot Open THE FILE", 0

Wannasave DB "The Data IN THE CONTOL IS MODIFIED. WANT TO SAVE IT?", 0

FILEOPENED DD FALSE

BackgroundColor DD 0FFFFFFH; Default to White

TextColor DD 0; Default to Black

HSEARCH DD?; Handle to The Search / Replace Dialog Box

Haccel DD?

.DATA?

Hinstance DD?

HRICHEDIT DD?

HWNDRICHEDIT DD?

FILENAME DB 256 DUP (?)

AlternateFileName DB 256 DUP (?)

Customcolors DD 16 DUP (?)

FindBuffer DB 256 DUP (?)

ReplaceBuffer DB 256 DUP (?)

UFLAGS DD?

FindText Findtextex <>

.code

Start:

MOV BYTE PTR [Findbuffer], 0

MOV BYTE PTR [ReplaceBuffer], 0

Invoke getModuleHandle, NULL

Mov Hinstance, EAX

Invoke Loadlibrary, AddR Richeditdll

.IF EAX! = 0

Mov HrichEdit, EAX

Invoke Winmain, Hinstance, 0, 0, SW_SHOWDEFAULT

Invoke Freelibrary, HrichEdit

.lse

Invoke Messagebox, 0, AddR Norichedit, Addr Appname, MB_OK OR MB_ICONERROR

.endif

Invoke EXITPROCESS, EAX

Winmain Proc Hinst: DWORD, HPREVINST: DWORD, CMDLINE: DWORD, CMDSHOW: DWORD

Local WC: WNDCLASSEX

Local MSG: MSG

Local hwnd: DWORD

Mov wc.cbsize, sizeof wndclassex

Mov wc.style, cs_hredraw or cs_vredrawmov wc.lpfnwndproc, Offset WndProc

Mov wc.cbclsextra, NULL

Mov wc.cbwndextra, null

Push hinst

POP wc.hinstance

Mov wc.hbrbackground, Color_Window 1

Mov wc.lpszMenuname, IDR_MainMenu

MOV wc.lpszclassname, Offset ClassName

Invoke Loadicon, NULL, IDI_APPLICATION

Mov wc.hicon, EAX

Mov wc.hiconsm, EAX

Invoke loadcursor, null, IDC_ARROW

Mov wc.hcursor, EAX

Invoke RegisterClassex, Addr WC

Invoke CreateWindowex, Null, Addr ClassName, Addr Appname, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, HINST, NULL

MOV HWND, EAX

Invoke ShowWindow, Hwnd, SW_SHOWNORMAL

Invoke UpdateWindow, HWnd

Invoke loadingAccelerators, Hinstance, IDR_MAINACCEL

Mov Haccel, EAX

.While true

Invoke GetMessage, Addr MSG, 0,0,0

.break .if (! EAX)

Invoke isDialogmessage, HSearch, Addr MSG

.IF EAX == false

Invoke TranslateAccelerator, HWnd, Haccel, Addr MSG

.IF EAX == 0

Invoke TranslateMessage, Addr MSG

Invoke DispatchMessage, Addr MSG

.endif

.endif

.endw

Mov Eax, Msg.wParam

RET

Winmain ENDP

StreamInproc Proc Hfile: DWORD, PBUFFER: DWORD, Numbytes: DWORD, PBYTESREAD: DWORD

Invoke Readfile, Hfile, Pbuffer, Numbytes, Pbytesread, 0

XOR Eax, 1

RET

StreaminProc ENDP

StreamoutProc Proc Hfile: DWORD, PBUFFER: DWORD, Numbytes: DWORD, PBYTESWRITEN: DWORD

Invoke Writefile, Hfile, Pbuffer, Numbytes, Pbyteswritten, 0

XOR Eax, 1

RET

StreamoutProc ENDP

CheckModifyState Proc HWND: DWORD

Invoke SendMessage, Hwndrichedit, EM_GETMODIFY, 0, 0

.IF EAX! = 0

Invoke Messagebox, Hwnd, Addr Wannasave, Addr Appname, MB_YESNOCANCEL

.IF eax == iDYES

Invoke SendMessage, Hwnd, WM_Command, IDM_SAVE, 0

.ELSEIF EAX == Idcancel

Mov Eax, False

RET

.endif

.endif

Mov Eax, True

RET

CheckModifyState Endp

SetColor Proc

Local CFM: CharFormat

Invoke SendMessage, Hwndrichedit, EM_SETBKGNDCOLOR, 0, BackgroundColor

Invoke RTLZERMEMORY, AddR CFM, Sizeof CFM

Mov Cfm.cbsize, Sizeof CFM

Mov cfm.dwmask, cfm_color

Push TextColor

POP cfm.crtextColor

Invoke SendMessage, Hwndrichedit, EM_SETCHARFORMAT, SCF_ALL, ADDR CFM

RET

SetColor ENDP

Optionproc Proc HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

Local CLR: Choosecolor

.IF uMSG == WM_INITDIALOG

.ELSEIF uMSG == WM_COMMAND

Mov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == idcancel

Invoke SendMessage, HWnd, WM_Close, 0, 0

.ELSEIF AX == IDC_BACKCOLORBOX

Invoke RTLZERMEMORY, ADDR CLR, SIZEOF CLR

Mov CLR.LSTRUCTSIZE, SIZEOF CLR

Push hwnd

POP CLR.HWNDOWNER

Push hinstance

POP CLR.HINSTANCE

Push Backgroundcolor

POP CLR.RGBRESULT

Mov CLR.LPCustColors, Offset Customcolors

Mov CLR.FLAGS, CC_Anycolor or CC_RGBINIT

Invoke Choosecolor, AddR CLR

.IF EAX! = 0

Push CLR.RGBRESULT

Pop BackgroundColor

Invoke getdlgitem, hwnd, idc_backcolorbox

Invoke InvalidateERECT, EAX, 0, TRUE

.endif

.ELSEIF AX == IDC_TextColorBox

Invoke RTLZERMEMORY, ADDR CLR, SIZEOF CLR

Mov CLR.LSTRUCTSIZE, SIZEOF CLR

Push hwnd

POP CLR.HWNDOWNER

Push hinstance

POP CLR.HINSTANCE

Push TextColor

POP CLR.RGBRESULT

Mov CLR.LPCustColors, Offset Customcolors

Mov CLR.FLAGS, CC_Anycolor or CC_RGBINIT

Invoke Choosecolor, AddR CLR

.IF EAX! = 0

Push CLR.RGBRESULT

Pop TextColor

Invoke getdlgitem, hwnd, idc_textcolorbox

Invoke InvalidateERECT, EAX, 0, TRUE

.endif

.ELSEIF AX == IDOK

Invoke SendMessage, Hwndrichedit, EM_GETMODIFY, 0, 0

Push EAX

Invoke setColor

POP EAX

Invoke SendMessage, HwndrichEdit, Em_SetModify, Eax, 0invoke Enddialog, HWnd, 0

.endif

.endif

.ELSEIF uMSG == WM_CTLCOLORSTATIC

Invoke getdlgitem, hwnd, idc_backcolorbox

.IF EAX == LPARAM

Invoke Createsolidbrush, BackgroundColor

RET

.lse

Invoke getdlgitem, hwnd, idc_textcolorbox

.IF EAX == LPARAM

Invoke Createsolidbrush, TextColor

RET

.endif

.endif

Mov Eax, False

RET

.ELSEIF uMSG == WM_Close

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

OptionProc ENDP

SearchProc Proc Hwnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

.IF uMSG == WM_INITDIALOG

Push hwnd

POP HSEARCH

Invoke CheckRadiobutton, HWnd, IDC_Down, IDC_UP, IDC_DOWN

Invoke Senddlgitemmessage, HWnd, IDC_Findedit, WM_SETTEXT, 0, AddR Findbuffer

.ELSEIF uMSG == WM_COMMAND

Mov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == iDOK

Mov uflags, 0

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR FindText.chrg

Invoke getdlgitemtext, hwnd, idc_findedit, AddR Findbuffer, Sizeof Findbuffer

.IF EAX! = 0

Invoke isdlgbuttonchecked, hwnd, idc_down

.IF eax == bst_checked

Or uflags, fr_down

Mov Eax, FindText.chrg.cpmin

.IF EAX! = FindText.chrg.cpmax

Push FindText.chrg.cpmax

POP FindText.chrg.cpmin

.endif

MOV Findtext.chrg.cpmax, -1

.lse

MOV Findtext.chrg.cpmax, 0

.endif

Invoke isdlgbuttonchecked, hwnd, idc_matchcase

.IF eax == bst_checked

Or uflags, fr_matchcase

.endif

Invoke isdlgbuttonchecked, hwnd, idc_wholeword

.IF eax == bst_checked

Or uflags, fr_wholeword

.endif

MOV FindText.lpstrText, Offset Findbuffer

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, UFLAGS, AddR Findtext

.IF EAX! = - 1

Invoke SendMessage, Hwndrichedit, EM_EXSETSEL, 0, AddR FindText.chrgText.Endif

.endif

.ELSEIF AX == IDCANCEL

Invoke SendMessage, HWnd, WM_Close, 0, 0

.lse

Mov Eax, False

RET

.endif

.endif

.ELSEIF uMSG == WM_Close

Mov HSearch, 0

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

SearchProc ENDP

ReplaceProc Proc HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

Local setText: SetTextex

.IF uMSG == WM_INITDIALOG

Push hwnd

POP HSEARCH

Invoke setdlgitemtext, hwnd, idc_findedit, AddR Findbuffer

Invoke setdlgitemtext, hwnd, idc_replaceedit, Addr ReplaceBuffer

.ELSEIF uMSG == WM_COMMAND

Mov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == idcancel

Invoke SendMessage, HWnd, WM_Close, 0, 0

.ELSEIF AX == IDOK

Invoke getdlgitemtext, hwnd, idc_findedit, AddR Findbuffer, Sizeof Findbuffer

Invoke getdlgitemtext, hwnd, idc_replaceEdit, AddR ReplaceBuffer, Sizeof ReplaceBuffer

Mov Findtext.chrg.cpmin, 0

MOV Findtext.chrg.cpmax, -1

MOV FindText.lpstrText, Offset Findbuffer

Mov setText.Flags, ST_SELECTION

MOV setText.codepage, CP_ACP

.While true

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, fr_down, addr findxt

.IF EAX == - 1

.break

.lse

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

Invoke SendMessage, Hwndrichedit, EM_SETTEXTEX, ADDR Settext, Addr ReplaceBuffer

.endif

.endw

.endif

.endif

.ELSEIF uMSG == WM_Close

Mov HSearch, 0

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

ReplaceProc ENDP

Gotoproc Proc Hwnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

LOCAL LINENO: DWORD

Local Chrg: Charrange

.IF uMSG == WM_INITDIALOG

Push hwnd

POP HSEARCH

.ELSEIF uMSG == WM_Commandmov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == idcancel

Invoke SendMessage, HWnd, WM_Close, 0, 0

.ELSEIF AX == IDOK

Invoke getdlgitemint, hwnd, IDC_LINENO, NULL, FALSE

Mov Lineno, EAX

Invoke SendMessage, Hwndrichedit, EM_GETLINECUNT, 0, 0

.IF EAX> Lineno

Invoke SendMessage, Hwndrichedit, EM_LINEINDEX, LINENO, 0

Mov Chrg.cpmin, EAX

Mov Chrg.cpmax, EAX

Invoke SendMessage, Hwndrichedit, EM_EXSETSEL, 0, AddR chrg

Invoke setfocus, HWNDRICHEDIT

.endif

.endif

.endif

.ELSEIF uMSG == WM_Close

Mov HSearch, 0

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

Gotoproc ENDP

PrepareEditmenu Proc Hsubmenu: DWORD

Local Chrg: Charrange

Invoke SendMessage, Hwndrichedit, EM_CANPASTE, CF_TEXT, 0

.IF EAX == 0; No Text in the clipboard

Invoke EnableMenuItem, HSubmenu, IDM_Paste, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_Paste, MF_ENABLED

.endif

Invoke SendMessage, Hwndrichedit, EM_CANUNDO, 0, 0

.IF EAX == 0

Invoke EnableMenuItem, HSubmenu, IDM_UNDO, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_UNDO, MF_ENABLED

.endif

Invoke SendMessage, Hwndrichedit, EM_CANREDO, 0, 0

.IF EAX == 0

Invoke EnableMenuItem, Hsubmenu, IDM_REDO, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_REDO, MF_ENABLED

.endif

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR chrg

Mov Eax, Chrg.cpmin

.IF eax == chrg.cpmax; no current selection

Invoke EnableMenuItem, HSubmenu, IDM_COPY, MF_GRAYED

Invoke EnableMenuItem, HSubmenu, IDM_CUT, MF_GRAYED

Invoke EnablemenuItem, HSubmenu, IDM_DELETE, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_COPY, MF_ENABLED

Invoke EnableMenuItem, HSubmenu, IDM_CUT, MF_ENABLED

Invoke EnableMenuItem, HSubmenu, IDM_DELETE, MF_ENABLED.ENDIF

RET

PrepareEDitMenu ENDP

WNDPROC PROC HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

LOCAL OFN: OpenFileName

Local buffer [256]: Byte

Local EditStream: EditStream

Local Hfile: DWORD

Local HPOPUP: DWORD

LOCAL PT: POINT

Local Chrg: Charrange

.IF uMSG == WM_CREATE

invoke CreateWindowEx, WS_EX_CLIENTEDGE, addr RichEditClass, 0, WS_CHILD or WS_VISIBLE or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_NOHIDESEL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, RichEditID, hInstance, 0

Mov hwndrichedit, EAX

Invoke SendMessage, HwndrichEdit, EM_LIMITTEXT, -1, 0

Invoke setColor

Invoke SendMessage, Hwndrichedit, EM_SETMODIFY, FALSE, 0

Invoke SendMask, Hwndrichedit, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS

Invoke SendMessage, Hwndrichedit, EM_EMPTYUNDOBUFER, 0, 0

.ELSEIF uMSG == WM_NOTIFY

PUSH ESI

Mov ESI, LPARAM

Assume ESI: PTR NMHDR

.IF [ESI] .code == en_msgfilter

Assume ESI: PTR MSGFilter

.IF [ESI] .msg == WM_RBUTTONDOWN

Invoke GetMenu, HWND

Invoke GetSubmenu, Eax, 1

MOV HPOPUP, EAX

Invoke PrepareEditmenu, HPOPUP

Mov Edx, [ESI] .lparam

MOV ECX, EDX

And EDX, 0FFFFH

SHR ECX, 16

MOV PT.X, EDX

Mov pt.y, ECX

Invoke Clienttoscreen, Hwnd, Addr Pt

Invoke TRACKPOPUPMENU, HPOPUP, TPM_LEFTALIGN OR TPM_BOTTOMALIGN, PT.X, PT.Y, NULL, HWND, NULL

.endif

.endif

POP ESI

.ELSEIF uMSG == WM_INITMENUPOPUP

Mov Eax, LPARAM

.IF AX == 0; File Menu

.IF fileopened == true; a file is already OPENED

Invoke EnableMenuItem, WPARAM, IDM_OPEN, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_CLOSE, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_SAVE, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_SAVEAS, MF_ENABLED

.lse

Invoke EnableMenuItem, WPARAM, IDM_OPEN, MF_ENABLINVOKE ENABLEMENUITEM, WPARAM, IDM_CLOSE, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_SAVE, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_SAVEAS, MF_GRAYED

.endif

.ELSEIF AX == 1; Edit Menu

Invoke PrepareEditmenu, WPARAM

.ELSEIF AX == 2; Search Menu Bar

.IF fileopened == TRUE

Invoke EnableMenuItem, WPARAM, IDM_FIND, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_FINDNEXT, MF_ENABED

Invoke EnableMenuItem, WPARAM, IDM_FINDPREV, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_REPLACE, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_GOTOLINE, MF_ENABLED

.lse

Invoke EnableMenuItem, WPARAM, IDM_FIND, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_FINDNEXT, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_FINDPREV, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_REPLACE, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_GOTOLINE, MF_GRAYED

.endif

.endif

.ELSEIF uMSG == WM_COMMAND

.IF lparam == 0; Menu Commands

Mov Eax, WPARAM

.IF AX == idm_open

Invoke RTLZERMEMORY, ADDR OFN, SIZEOF OFN

Mov ofn.lstructsize, Sizeof off

Push hwnd

POP OFN.HWNDOWNER

Push hinstance

POP OFN.HINSTANCE

Mov off.lpstrfilter, offset asmfilterstring

Mov ofn.lpstrfile, offset filename

MOV BYTE PTR [filename], 0

Mov ofn.nmaxfile, Sizeof FileName

Mov off.flags, OFN_FILEMUSTEXIST or OFN_HIDEREADOSLY OR OFN_PATHMUSTEXIST

Invoke GetopenFileName, Addr OFN

.IF EAX! = 0

Invoke Createfile, Addr FileName, Generic_Read, File_Share_read, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0

.IF EAX! = INVALID_HANDLE_VALUE

Mov Hfile, EAX

; ================================================== ===============; stream the text int Into the Richedit Control

; ================================================== ================

Mov EditStream.dwcookie, EAX

Mov EditStream.pfncallback, Offset StreamInproc

Invoke SendMessage, Hwndrichedit, EM_STREAMIN, SF_TEXT, ADDR EditStream

; ================================================== =========

; Initialize the Modify State To False

; ================================================== =========

Invoke SendMessage, Hwndrichedit, EM_SETMODIFY, FALSE, 0

Invoke Closehandle, HFile

Mov FileOpened, True

.lse

Invoke Messagebox, Hwnd, Addr OpenFilefail, Addr Appname, MB_OK OR MB_ICONERROR

.endif

.endif

.ELSEIF AX == IDM_Close

Invoke CheckmodifyState, Hwnd

.IF EAX == True

Invoke SetWindowText, Hwndrichedit, 0mov FileOpened, False

.endif

.ELSEIF AX == IDM_SAVE

Invoke CreateFile, Addr FileName, Generic_Write, File_Share_read, null, crete_always, file_attribute_normal, 0

.IF EAX! = INVALID_HANDLE_VALUE

@@:

Mov Hfile, EAX

; ================================================== ================

Stream the text to the file

; ================================================== ================

Mov EditStream.dwcookie, EAX

Mov EditStream.pfncallback, Offset streamoutproc

Invoke SendMessage, Hwndrichedit, EM_STREAMOUT, SF_TEXT, AddR EditStream

; ================================================== =========

; Initialize the Modify State To False

; ================================================== =========

Invoke SendMessage, HwndrichEdit, Em_SetModify, False, 0Invoke Closehandle, Hfile

.lse

Invoke Messagebox, Hwnd, Addr OpenFilefail, Addr Appname, MB_OK OR MB_ICONERROR

.endif

.ELSEIF AX == IDM_COPY

Invoke SendMessage, Hwndrichedit, WM_COPY, 0, 0

.ELSEIF AX == IDM_CUT

Invoke SendMessage, Hwndrichedit, WM_CUT, 0, 0

.ELSEIF AX == IDM_PASTE

Invoke SendMessage, Hwndrichedit, WM_Paste, 0,0

.ELSEIF AX == IDM_DELETE

Invoke SendMessage, HwndrichEdit, EM_REPLACESEL, TRUE, 0

.ELSEIF AX == IDM_SELECTALL

Mov chrg.cpmin, 0

Mov chrg.cpmax, -1

Invoke SendMessage, Hwndrichedit, EM_EXSETSEL, 0, AddR chrg

.ELSEIF AX == IDM_UNDO

Invoke SendMessage, Hwndrichedit, EM_UNDO, 0, 0

.ELSEIF AX == IDM_REDO

Invoke SendMessage, Hwndrichedit, EM_REDO, 0, 0

.ELSEIF AX == IDM_OPTION

Invoke Dialogboxparam, Hinstance, IDD_OptionDLG, HWND, Addr Optionproc, 0

.ELSEIF AX == IDM_SAVEAS

Invoke RTLZERMEMORY, ADDR OFN, SIZEOF OFN

Mov ofn.lstructsize, Sizeof off

Push hwnd

POP OFN.HWNDOWNER

Push hinstance

POP OFN.HINSTANCE

Mov off.lpstrfilter, offset asmfilterstring

Mov ofn.lpstrfile, Offset AlternateFileName

MOV BYTE PTR [AlternateFileName], 0

Mov ofn.nmaxfile, Sizeof AlternateFileName

Mov off.flags, OFN_FILEMUSTEXIST or OFN_HIDEREADOSLY OR OFN_PATHMUSTEXIST

Invoke GetsaveFileName, AddR OFN

.IF EAX! = 0

Invoke createfile, addr alternatefilename, generic_write, file_share_read, null, create_always, file_attribute_normal, 0

.IF EAX! = INVALID_HANDLE_VALUE

JMP @B

.endif

.endif

.ELSEIF AX == IDM_FIND

.IF hSearch == 0

Invoke CreateDialogparam, Hinstance, IDd_Findlg, Hwnd, AddR searchProc, 0

.endif

.ELSEIF AX == IDM_REPLACE

.IF hSearch == 0

Invoke CreateDialogparam, Hinstance, IDD_REPLAG, HWND, AddR ReplaceProc, 0.Endif

.ELSEIF AX == idm_gotoline

.IF hSearch == 0

Invoke CreateDialogparam, Hinstance, IDD_GOTODLG, HWND, Addr gotoproc, 0

.endif

.ELSEIF AX == IDM_FINDNEXT

Invoke Lstrlen, AddR Findbuffer

.IF EAX! = 0

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR FindText.chrg

Mov Eax, FindText.chrg.cpmin

.IF EAX! = FindText.chrg.cpmax

Push FindText.chrg.cpmax

POP FindText.chrg.cpmin

.endif

MOV Findtext.chrg.cpmax, -1

MOV FindText.lpstrText, Offset Findbuffer

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, fr_down, addr findxt

.IF EAX! = - 1

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

.endif

.endif

.ELSEIF AX == IDM_FINDPREV

Invoke Lstrlen, AddR Findbuffer

.IF EAX! = 0

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR FindText.chrg

MOV Findtext.chrg.cpmax, 0

MOV FindText.lpstrText, Offset Findbuffer

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, 0, AddR Findtext

.IF EAX! = - 1

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

.endif

.endif

.ELSEIF AX == IDM_EXIT

Invoke SendMessage, HWnd, WM_Close, 0, 0

.endif

.endif

.ELSEIF uMSG == WM_Close

Invoke CheckmodifyState, Hwnd

.IF EAX == True

Invoke DestroyWindow, HWnd

.endif

.ELSEIF uMSG == WM_SIZE

Mov Eax, LPARAM

Mov Edx, EAX

And Eax, 0FFFFH

SHR EDX, 16

Invoke MoveWindow, Hwndrichedit, 0,0, Eax, EDX, True

.ELSEIF uMSG == WM_DESTROY

Invoke PostquitMessage, NULL

.lse

Invoke DefWindowProc, Hwnd, UMSG, WPARAM, LPARAM

RET

.endif

XOR EAX, EAX

RET

WNDPROC ENDP

End Start

Analysis

The search-for-text capability is implemented with EM_FINDTEXTEX. When the user clicks on Find menuitem, IDM_FIND message is sent and the Find dialog box is displayed.invoke GetDlgItemText, hWnd, IDC_FINDEDIT, addr FindBuffer, sizeof FindBuffer

.IF EAX! = 0

.

Mov uflags, 0

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR FindText.chrg

If the text string is not null, we continue to initialize uFlags variable to 0.This variable is used to store the search flags used with EM_FINDTEXTEX. After that, we obtain the current selection with EM_EXGETSEL because we need to know the starting point of the Search Operation.

Invoke isdlgbuttonchecked, hwnd, idc_down

.IF eax == bst_checked

Or uflags, fr_down

Mov Eax, FindText.chrg.cpmin

.IF EAX! = FindText.chrg.cpmax

Push FindText.chrg.cpmax

POP FindText.chrg.cpmin

.endif

MOV Findtext.chrg.cpmax, -1

.lse

MOV Findtext.chrg.cpmax, 0

.endif

The next part is a little tricky. We check the direction radio button to ascertain which direction the search should go. If the downward search is indicated, we set FR_DOWN flag to uFlags. After that, we check whether a selection is currently in effect by comparing the values ​​of cpMin and cpMax. If both values ​​are not equal, it means there is a current selection and we must continue the search from the end of that selection to the end of text in the control. Thus we need to replace the value Of cpmax with what of cpmin and change the value of cpmax to -1 (0ffffffh). if it is no current selection, The Range To Search Is from The Current Caret Position To The End of Text.

If the user chooses to search upward, we use the range from the start of the selection to the beginning of the text in the control. That's why we only modify the value of cpMax to 0. In the case of upward search, cpMin contains the character index of the last character in the search range and cpMax the character index of the first char in the search range. It's the inverse of the downward search.invoke IsDlgButtonChecked, hWnd, IDC_MATCHCASE

.IF eax == bst_checked

Or uflags, fr_matchcase

.endif

Invoke isdlgbuttonchecked, hwnd, idc_wholeword

.IF eax == bst_checked

Or uflags, fr_wholeword

.endif

MOV FindText.lpstrText, Offset Findbuffer

WE Continue to Check The Checkboxes for the search Flags, IE, fr_matchcase and fr_wholeword. Lastly, We Put The Offset of the text.

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, UFLAGS, AddR Findtext

.IF EAX! = - 1

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

.endif

.endif

We are now ready to issue EM_FINDTEXTEX. After that, we examine the search result returned by SendMessage. If the return value is -1, no match is found in the search range. Otherwise, chrgText member of FINDTEXTEX structure is filled with the character indices Of the matching text. we thus proced to select it with em_exsetsel.

The Replace Operation Is Done in Much The Same Manner.

Invoke getdlgitemtext, hwnd, idc_findedit, AddR Findbuffer, Sizeof Findbuffer

Invoke getdlgitemtext, hwnd, idc_replaceEdit, AddR ReplaceBuffer, Sizeof ReplaceBuffer

We Retrieve the text to search for and the text used to replace.

Mov Findtext.chrg.cpmin, 0

MOV Findtext.chrg.cpmax, -1

MOV FindText.lpstrText, Offset Findbuffer

To make it it is -1.mov setText.Flags, ST_SELECTION AFFECTES

MOV setText.codepage, CP_ACP

................ ..

.While true

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, fr_down, addr findxt

.IF EAX == - 1

.break

.lse

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

Invoke SendMessage, Hwndrichedit, EM_SETTEXTEX, ADDR Settext, Addr ReplaceBuffer

.endif

.endw

We enter an infinite loop, search for the matching text. If one is found, We select it with em_exsetsel and replace it with em_settextex. When no more match is found, we exit the loop.

Find next and find prev. Features Use em_findtextex message in the Similar Manner to the find operation.

WE WILL EXAMINE THE Go To Line Feature Next .hen The User Clicks Go To Line MenuItem, We Display a Dialog BoX Below:

.

Invoke getdlgitemint, hwnd, IDC_LINENO, NULL, FALSE

Mov Lineno, EAX

Obtain the line number from the ed control

Invoke SendMessage, Hwndrichedit, EM_GETLINECUNT, 0, 0

.IF EAX> Lineno

Obtain the number of lines in the control. Check WHETER THE USER SPECIFIES The LINE NUMBER That Out of the Range.

Invoke SendMessage, Hwndrichedit, EM_LINEINDEX, LINENO, 0

If the line number is valid, we want to move the caret to the first character of that line. So we send EM_LINEINDEX message to the richedit control. This message returns the character index of the first character in the specified line. We send the line Number in WParam and in Return, We Has The Character Index.Invoke SendMessage, HwndrichEdit, EM_SETSEL, EAX, EAX

To set the current selection, this time we use EM_SETSEL because the character indices are not already in a CHARRANGE structure thus it saves us two instructions (to put those indices into a CHARRANGE structure).

Invoke setfocus, HWNDRICHEDIT

.endif

The Caret Will Not Be Displayed Unless The Richedit Control Has The Focus. So We call setfocus on it.

转载请注明原文地址:https://www.9cbs.com/read-4689.html

New Post(0)