WIN32汇编 Richedit控件的使用

这次来介绍一下一个独特的控件------Richedit    说实话这次也是第一次接触到这个控件,以前虽然听说过但是不知道具体它是干什么的,从字面上看好像是edit控件的扩展一样,其实这样只说对了一半,Richedit控件确实比edit控件功能强大丰富,但是它们的使用位置不同,edit控件以前在学习控件的时候,就出现了许多edit控件,那时候用edit控件主要是实现向一个小的文本框中输入文本而且基本都是用在对话框中,而且大小也有限制,在单行模式下能容纳的文本不能超过32KB,在多行模式下也不能超过64KB,加上这个限制想要实现多文本的输入那就有点麻烦了,而且不能实现文本格式,大小颜色等属性的设置,出于此种原因,Richedit控件就有了大显身手的机会,它可以实现多文本的输入,但是需要指定大小(发送EM_EXLIMITTEXT,因为默认情况下控件还是将最大字符数限制为64KB),这个控件因为功能复杂,代码量较大,微软给它独立使用一个动态链接库存储(Riched32.dll
 1.0版,Riched20.dll(2.0和3.0版)),具体功能看一下下表(罗云斌老师书中的一张介绍图)

不同版本Richedit控件之间的区别
  1.0版 2.0版 3.0版
DLL库文件名 Riched32.dll Riched32.dll Riched32.dll
控件的类名 Richedit Richedit20A

Richedit20W

Richedit20A

Richedit20W

拖放编辑 支持 支持 支持
流输入输出 支持 支持 支持 
Unicode编辑 不支持 支持 支持
非窗口操作 不支持 支持 支持
自动URL识别 不支持 支持 支持
加速键 不支持 支持 支持
分行符 CR+LF CR CR(可模拟1.0版)
撤销/重做 支持单级 支持多级 支持多级
文本搜索 向前搜索 向前/向后搜索 向前/向后搜索
       

知道了Richedit控件的大致功能,接下来就需要知道怎么来实现相关的功能,分为如下几步来实现:

资源文件
菜单 IDR_MENU1  
加速键 IDR_ACCELERATOR1
光标 IDI_ICON1 
实现过程
控件的流操作 _ProcStream()
文件的保存 _SaveFile()
打开文件 _OpenFile()
检测文件修改 _CheckModify()
查找文字 _FindText()
实时改变菜单项状态 _SetStatus()
窗口内容初始化 _Init()
退出程序 _Quit()
窗口过程 _ProcWinMain()
主函数 _WinMain()

下面来回顾一下写程序的时候遇见的一些问题:

首先是资源文件,依然使用ResEdit编写,这次的资源文件需要定义的有图标,菜单,另外一个就是加速键(这个加速键好久没有写过了感觉有点陌生了,以前还是和菜单一起学习的,菜单现在已经非常熟练了,要写加速键还要再翻一下以前的文章。。。)下面简单总结一下:

键名-----表示加速键对应的按钮可以有3种方式定义:

     1.“^字母”:  表示Ctrl加上字母键

     2.“字母” :    表示字母,这时的类型必须指明是VIRTKEY

     3.  数值    :表示ASCII码为该数值的字母,这是类型必须指明为ASCII    

(在使用ResEdit编写的时候直接在键名这一项输入相应的字母,就可以了,工具已经自动处理过了)

命令ID------按下加速键后,windows向程序发送的命令ID,如果要把加速键和菜单关联起来,这里就是要关联菜单项的命令ID。这个容易理解其实就是命令ID

类型---------用来指定键的定义方式,可以是VIRKEY和 ASCII,分别用来表示“键名”字段定义的是虚拟键还是ASCII码

选项-------- 可以是ALt,Control或Shift中的单个或多个,如果指定多个,则中间用逗号隔开,表示加速键是按键加上这些控制键的组合键。

这样就清楚多了。

在使用ResEdit工具添加图标资源的时候,在创建新的图标资源的时候程序总会崩溃(有时候不会),这个我也没有解决,工具出错退出,一开始我以为是误删了什么文件但是从新安装之后还是如此,但是在创建资源文件的时候首先定义图标文件,创建新图标这样一般可以。下面看一下资源代码:

// Generated by ResEdit 1.6.6

// Copyright (C) 2006-2015

// http://www.resedit.net

#include <windows.h>

#include <commctrl.h>

#include <richedit.h>

#include "resource.h"

//

// Menu resources

//

LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

IDR_MENU1 MENU

{

POPUP "文件(&F)"

{

MENUITEM "打开文件(&O)...\tCtrl+O", IDM_OPEN

MENUITEM "保存文件(&S)\tCtrl+S", IDM_SAVE

MENUITEM SEPARATOR

MENUITEM "退出(&X)", IDM_EXIT

}

POPUP "编辑(&E)"

{

MENUITEM "撤销(&Z)\tCtrl+Z", IDM_UNDO

MENUITEM "重复(&Y)\tCtrl+Y", IDM_REDO

MENUITEM SEPARATOR

MENUITEM "全选(&A)\tCtrl+A", IDM_SELALL

MENUITEM "拷贝(&C)\tCtrl+C", IDM_COPY

MENUITEM "剪切(&X)\tCtrl+X", IDM_CUT

MENUITEM "粘贴(&V)\tCtrl+V", IDM_PASTE

MENUITEM SEPARATOR

MENUITEM "查找(&F)\tCtrl+F", IDM_FIND

MENUITEM "查找上一个(&P)\tF2", IDM_FINDPREV

MENUITEM "查找下一个(&N)\tF3", IDM_FINDNEXT

}

}

// Accelerator resources

//

LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

IDR_ACCELERATOR1 ACCELERATORS

{

VK_F2,         IDM_FINDPREV, VIRTKEY

VK_F3,         IDM_FINDNEXT, VIRTKEY

"O",            IDM_OPEN, ASCII

"S",            IDM_SAVE, ASCII

"Z",            IDM_UNDO, ASCII

"Y",            IDM_REDO, ASCII

"A",            IDM_SELALL, ASCII

"C",            IDM_COPY, ASCII

"X",            IDM_CUT, ASCII

"V",            IDM_PASTE, ASCII

"F",            IDM_FIND, ASCII

}

//

// Icon resources

//

LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

IDI_ICON1          ICON           ".\\IDI_ICON1.ico"

下面来看一下程序实现过称中遇见的问题:

首先是一个以前接触很少的问题:文本流(流入流出),说到流操作首先我想到的是C++里面的流输入输出(我接触的编程语言比较少。。只懂点C/C++和汇编)文件流的基本操作:1、打开文件 2、读取数据 3、处理数据 4、数据写回 5、关闭文件。WIN32汇编语言中文件流的操作的相关函数有两个(读入流入:ReadFile()    写出流出:WriteFile()  ),其他的就涉及到需要发送的windows消息。当需要将文件读入到控件的时候,可以向控件发送EM_STREAMIN消息,当需要将文件从控件保存到文本文件时发送EM_STREAMOUT,消息的参数中附带需要流入的文本内容格式,以及回调函数(提前自定义的函数实现读写文件的功能模块)等信息,Richedit控件会循环调用回调函数直到处理完全部的文本内容,在控件每次调用回调函数的时候,控件通过参数(控件会将流操作函数中需要的参数指定,然后再传递给回调函数,我感觉那些参数是控件内部整理的,不需要我们来指定)告诉回调函数要读写的字节数和缓冲区的地址,在程序中流入流出操作的回调函数使用的是同一个子程序_ProcStream(),在该子程序中通过判断
向控件发送的消息中的lParam参数中的lpStream指向的一个EDITSTREAM结构中的dwCookie字段(这个字段可以由我们自己定义程序中定义的是TRUE和FALSE,这些定义都无所谓,都是一样的)来确定是要进行流入(TRUE)还是流出(FALSE)操作,接下来就要使用上面介绍的那两个API函数了,这个问题刚接触很不好理解,有些地方现在依然理解的不到位。

下一个问题就是在查找文字子函数_FindText()中,在设置查找选项的时候程序代码入如下:

                mov  @stFindText.lpstrText,offset szFindText          ;将szFindText变量的地址传递给                                                                                            
          FINDTEXTEX结构体类型的变量@stFindText的lpstrText字段

mov  ecx,stFind.Flags        ;将stFind结构体变量查找标识字段内容传递给ecx

andecx,FR_MATCHCASE or FR_DOWN or FR_WHOLEWORD     ;将stFind结构体变量中的所有查找字符标示屏蔽除了   FR_MATCHCASE
or FR_DOWN or FR_WHOLEWORD这几个标识.

在上面的代码中使用了and运算(按位相与 1 and 1 =1       1 and  0  =0)将其他不需要的标识屏蔽掉(不同的位代表不同的标识)这是我的理解,可能也有错误。

下面就是在保存文件功能模块中遇见的问题

使用两个函数将文件清空,代码如下:

                 invoke      SetFilePointer,hFile,0,0,FILE_BEGIN

invoke      SetEndOfFile,hFile

利用SetFilePointer函数返回当前的文件指针,然后再使用SetEndOfFile函数从当前文件指针处截断,除去后面的内容,从而达到将文件清空的目的。这个有点不容易理解。

下面看一下程序源代码:

                 .386

.model flat,stdcall

option casemap:none

include          windows.inc

include          user32.inc

includelib       user32.lib

include          kernel32.inc

includelib       kernel32.lib

include          comdlg32.inc

includelib       comdlg32.lib

IDR_MENU1        equ        100

IDR_ACCELERATOR1 equ        101

IDI_ICON1        equ        103

IDM_OPEN         equ        40000

IDM_SAVE         equ        40001

IDM_COPY         equ        40002

IDM_EXIT         equ        40003

IDM_UNDO         equ        40004

IDM_REDO         equ        40005

IDM_SELALL       equ        40006

IDM_CUT          equ        40007

IDM_PASTE        equ        40008

IDM_FIND         equ        40009

IDM_FINDPREV     equ        40010

IDM_FINDNEXT     equ        40011

.data?

hInstance        dd          ?

hWinMain         dd          ?

hMenu            dd          ?

hWinEdit         dd          ?

hFile            dd          ?

hFindDialog      dd          ?

idFindMessage    dd          ?

szFileName       db          MAX_PATH  dup (?)

szFindText       db          100 dup   (?)

.data

stFind           FINDREPLACE <sizeof FINDREPLACE,0,0,FR_DOWN,szFindText,0,sizeof szFindText,0,0,0,0>

.const

FINDMSGSTRING    db          ‘commdlg_FindReplace‘,0

szClassName      db          ‘wordpad‘,0

szCaptionMain    db          ‘记事本‘,0

szDllEdit        db          ‘RichEd20.dll‘,0

szClassEdit      db          ‘RichEdit20A‘,0

szNotFound       db          ‘字符串未找到!‘,0

szFilter        db          ‘Text Files(*.txt)‘,0,‘*.txt‘,0

db          ‘All  Files(*.*)‘,0,‘*.*‘,0,0

szDefaultExt     db          ‘txt‘,0

szErrOpenFile    db          ‘无法打开文件!‘,0

szModify         db          ‘文件已修改,是否保存?‘,0

szFont           db          ‘宋体‘,0

.code

_ProcStream      proc        uses ebx edi esi _dwCookie,_lpBuffer,_dwBytes,_lpBytes

.if         _dwCookie

invoke ReadFile,hFile,_lpBuffer,_dwBytes,_lpBytes,0        ;读入

.else

invoke WriteFile,hFile,_lpBuffer,_dwBytes,_lpBytes,0       ;读出

.endif

xor         eax,eax

ret

_ProcStream endp

_SaveFile        proc

LOCAL       @stES:EDITSTREAM

invoke      SetFilePointer,hFile,0,0,FILE_BEGIN

invoke      SetEndOfFile,hFile

mov         @stES.dwCookie,FALSE

mov         @stES.pfnCallback,offset _ProcStream

invoke      SendMessage,hWinEdit,EM_STREAMOUT,SF_TEXT,addr @stES

invoke      SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0

ret

_SaveFile        endp

_OpenFile        proc

LOCAL @stOF:OPENFILENAME

LOCAL @stES:EDITSTREAM

invoke    RtlZeroMemory,addr @stOF,sizeof @stOF

mov       @stOF.lStructSize,sizeof @stOF

push      hWinMain

pop       @stOF.hWndOwner

mov       @stOF.lpstrFilter,offset szFilter

mov       @stOF.lpstrFile,offset szFileName

mov       @stOF.nMaxFile,MAX_PATH

mov       @stOF.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST

mov       @stOF.lpstrDefExt,offset szDefaultExt

invoke    GetOpenFileName,addr @stOF

.if       eax       ;0

invoke   CreateFile,addr szFileName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE,\

0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0

.if      eax  ==  INVALID_HANDLE_VALUE

invoke   MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONSTOP

ret

.endif

push     eax

.if      hFile

invoke CloseHandle,hFile

.endif

pop      eax

mov      hFile,eax

mov      @stES.dwCookie,TRUE

mov      @stES.dwError,NULL

mov      @stES.pfnCallback,offset _ProcStream

invoke   SendMessage,hWinEdit,EM_STREAMIN,SF_TEXT,addr @stES

invoke   SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0

.endif

ret

_OpenFile endp

_CheckModify     proc

LOCAL     @dwReturn

mov       @dwReturn,TRUE

invoke    SendMessage,hWinEdit,EM_GETMODIFY,0,0

.if       eax && hFile

invoke   MessageBox,hWinMain,addr szModify,addr szCaptionMain,MB_YESNOCANCEL or MB_ICONQUESTION

.if      eax  ==  IDYES

call     _SaveFile

.elseif  eax  ==  IDCANCEL

mov      @dwReturn,FALSE

.endif

.endif

mov       eax,@dwReturn

ret

_CheckModify endp

_FindText proc

local @stFindText:FINDTEXTEX

invoke
SendMessage,hWinEdit,EM_EXGETSEL,0,addr @stFindText.chrg

.if stFind.Flags & FR_DOWN

push @stFindText.chrg.cpMax

pop @stFindText.chrg.cpMin

.endif

mov @stFindText.chrg.cpMax,-1

mov @stFindText.lpstrText,offset szFindText

mov ecx,stFind.Flags

and ecx,FR_MATCHCASE or FR_DOWN or FR_WHOLEWORD

invoke
SendMessage,hWinEdit,EM_FINDTEXTEX,ecx,addr @stFindText

.if eax ==-1

mov ecx,hWinMain

.if hFindDialog

mov ecx,hFindDialog

.endif

invoke
MessageBox,ecx,addr szNotFound,NULL,MB_OK or MB_ICONINFORMATION

ret

.endif

invoke
SendMessage,hWinEdit,EM_EXSETSEL,0,addr @stFindText.chrgText

invoke
SendMessage,hWinEdit,EM_SCROLLCARET,NULL,NULL

ret

_FindText endp

_SetStatus proc

local @stRange:CHARRANGE

invoke
SendMessage,hWinEdit,EM_EXGETSEL,0,addr @stRange

mov eax,@stRange.cpMin

.if eax ==@stRange.cpMax

invoke
EnableMenuItem,hMenu,IDM_COPY,MF_GRAYED

invoke
EnableMenuItem,hMenu,IDM_CUT,MF_GRAYED

.else

invoke
EnableMenuItem,hMenu,IDM_COPY,MF_ENABLED

invoke
EnableMenuItem,hMenu,IDM_CUT,MF_ENABLED

.endif

invoke
SendMessage,hWinEdit,EM_CANPASTE,0,0

.if eax

invoke
EnableMenuItem,hMenu,IDM_PASTE,MF_ENABLED

.else

invoke
EnableMenuItem,hMenu,IDM_PASTE,MF_GRAYED

.endif

invoke
SendMessage,hWinEdit,EM_CANREDO,0,0

.if eax

invoke
EnableMenuItem,hMenu,IDM_REDO,MF_ENABLED

.else

invoke
EnableMenuItem,hMenu,IDM_REDO,MF_GRAYED

.endif

invoke
SendMessage,hWinEdit,EM_CANUNDO,0,0

.if eax

invoke
EnableMenuItem,hMenu,IDM_UNDO,MF_ENABLED

.else

invoke
EnableMenuItem,hMenu,IDM_UNDO,MF_GRAYED

.endif

invoke
GetWindowTextLength,hWinEdit

.if eax

invoke
EnableMenuItem,hMenu,IDM_SELALL,MF_ENABLED

.else

invoke
EnableMenuItem,hMenu,IDM_SELALL,MF_GRAYED

.endif

invoke
SendMessage,hWinEdit,EM_GETMODIFY,0,0

.if eax && hFile

invoke
EnableMenuItem,hMenu,IDM_SAVE,MF_ENABLED

.else

invoke
EnableMenuItem,hMenu,IDM_SAVE,MF_GRAYED

.endif

.if szFindText

invoke
EnableMenuItem,hMenu,IDM_FINDNEXT,MF_ENABLED

invoke
EnableMenuItem,hMenu,IDM_FINDPREV,MF_ENABLED

.else

invoke
EnableMenuItem,hMenu,IDM_FINDNEXT,MF_GRAYED

invoke
EnableMenuItem,hMenu,IDM_FINDPREV,MF_GRAYED

.endif

ret

_SetStatus endp

_Init proc

local @stCf:CHARFORMAT

push hWinMain

pop stFind.hwndOwner

invoke
RegisterWindowMessage,addr FINDMSGSTRING

mov idFindMessage,eax

invoke
CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassEdit,NULL,\

WS_CHILD OR WS_VISIBLE OR WS_VSCROLL ORWS_HSCROLL \

OR ES_MULTILINE or ES_NOHIDESEL,\

0,0,0,0,\

hWinMain,0,hInstance,NULL

mov hWinEdit,eax

invoke
SendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0

invoke
RtlZeroMemory,addr @stCf,sizeof @stCf

mov @stCf.cbSize,sizeof @stCf

mov @stCf.yHeight,9 * 20

mov @stCf.dwMask,CFM_FACE or CFM_SIZE or CFM_BOLD

invoke
lstrcpy,addr @stCf.szFaceName,addr szFont

invoke
SendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr @stCf

invoke
SendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1

ret

_Init endp

_Quit proc

invoke
_CheckModify

.if eax

invoke
DestroyWindow,hWinMain

invoke
PostQuitMessage,NULL

.if hFile

invoke
CloseHandle,hFile

.endif

.endif

ret

_Quit endp

_ProcWinMain procuses ebx edi esi hWnd,uMsg,wParam,lParam

local @stRange:CHARRANGE

local @stRect:RECT

mov eax,uMsg

.if eax ==WM_SIZE

invoke
GetClientRect,hWinMain,addr @stRect

invoke
MoveWindow,hWinEdit,0,0,@stRect.right,@stRect.bottom,TRUE

.elseif
eax == WM_COMMAND

mov eax,wParam

movzx eax,ax

.if eax ==IDM_OPEN

invoke
_CheckModify

.if eax

call _OpenFile

.endif

.elseif
eax == IDM_SAVE

call _SaveFile

.elseif
eax == IDM_EXIT

invoke
_Quit

.elseif
eax == IDM_UNDO

invoke
SendMessage,hWinEdit,EM_UNDO,0,0

.elseif
eax == IDM_REDO

invoke
SendMessage,hWinEdit,EM_REDO,0,0

.elseif
eax == IDM_SELALL

mov @stRange.cpMin,0

mov @stRange.cpMax,-1

invoke
SendMessage,hWinEdit,EM_EXSETSEL,0,addr @stRange

.elseif
eax == IDM_COPY

invoke
SendMessage,hWinEdit,WM_COPY,0,0

.elseif
eax == IDM_CUT

invoke
SendMessage,hWinEdit,WM_CUT,0,0

.elseif
eax == IDM_PASTE

invoke
SendMessage,hWinEdit,WM_PASTE,0,0

.elseif
eax == IDM_FIND

and stFind.Flags,not FR_DIALOGTERM

invoke
FindText,addr stFind

.if eax

mov hFindDialog,eax

.endif

.elseif
eax == IDM_FINDPREV

and stFind.Flags,not FR_DOWN

invoke
_FindText

.elseif
eax == IDM_FINDNEXT

or stFind.Flags,FR_DOWN

invoke
_FindText

.endif

.elseif
eax == WM_INITMENU

call _SetStatus

.elseif
eax == idFindMessage

.if stFind.Flags & FR_DIALOGTERM

mov hFindDialog,0

.else

invoke
_FindText

.endif

.elseif
eax == WM_ACTIVATE

mov eax,wParam

.if (ax ==WA_CLICKACTIVE ) || (ax == WA_ACTIVE)

invoke
SetFocus,hWinEdit

.endif

.elseif
eax == WM_CREATE

push hWnd

pop hWinMain

invoke
_Init

.elseif
eax == WM_CLOSE

call _Quit

.else

invoke
DefWindowProc,hWnd,uMsg,wParam,lParam

ret

.endif

xor eax,eax

ret

_ProcWinMain endp

_WinMain proc

local @stWndClass:WNDCLASSEX

local @stMsg:MSG

local @hAccelerator,@hRichEdit

invoke
LoadLibrary,offset szDllEdit

mov @hRichEdit,eax

invoke
GetModuleHandle,NULL

mov hInstance,eax

invoke
LoadMenu,hInstance,IDR_MENU1

mov hMenu,eax

invoke
LoadAccelerators,hInstance,IDR_ACCELERATOR1

mov @hAccelerator,eax

invoke
RtlZeroMemory,addr @stWndClass,sizeof @stWndClass

invoke
LoadIcon,hInstance,IDI_ICON1

mov @stWndClass.hIcon,eax

mov @stWndClass.hIconSm,eax

invoke
LoadCursor,0,IDC_ARROW

mov @stWndClass.hCursor,eax

push hInstance

pop @stWndClass.hInstance

mov @stWndClass.cbSize,sizeof WNDCLASSEX

mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW

mov @stWndClass.lpfnWndProc,offset _ProcWinMain

mov @stWndClass.hbrBackground,COLOR_BTNFACE+1

mov @stWndClass.lpszClassName,offset szClassName

invoke
RegisterClassEx,addr @stWndClass

invoke
CreateWindowEx,NULL,\

offset szClassName,offset szCaptionMain,\

WS_OVERLAPPEDWINDOW,\

CW_USEDEFAULT,CW_USEDEFAULT,700,500,\

NULL,hMenu,hInstance,NULL

mov hWinMain,eax

invoke
ShowWindow,hWinMain,SW_SHOWNORMAL

invoke
UpdateWindow,hWinMain

.while
TRUE

invoke
GetMessage,addr @stMsg,NULL,0,0

.break
.if eax == 0

invoke
TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg

.if eax == 0

invoke
TranslateMessage,addr @stMsg

invoke
DispatchMessage,addr @stMsg

.endif

.endw

invoke
FreeLibrary,@hRichEdit

ret

_WinMain endp

start:

call _WinMain

invoke
ExitProcess,NULL

end start

下面介绍一下一些陌生的结构和API函数以及几个消息:

结构:

EDITSTREAM              STRUCT

       dwCookie              DWORD       ?              ;用户自定义值

       dwError                 DWORD        ?              ;用来返回流操作过程中的错误信息 

       pfnCallback           DWORD        ?              ;   回调函数地址

EDITSTREAM               ENDS

 dwCookie

用户值作为第一个参数传递给回调。指定富编辑控件的应用程序定义的值传递到指定的 pfnCallback 成员的 EditStreamCallback 回调函数。

dwError

指示流入 (读取) 或流出 (写入) 操作的结果。值为 0 表示没有错误。一个非零值,可以是 EditStreamCallback 函数或一个代码,指示该控件遇到一个错误的返回值。

pfnCallback

回调函数的地址

FINDTEXTEX      STRUCT

     chrg                CHARRANGE  <>     ;查找区域

     lpstrText         DWORD            ?      ;查找字符串地址

     chrgtext          CHARRANGE  <>     ; 如果找到则在这里返回找到文字的起始/结束位置

FINDTEXTEX      ENDS

CHARRANGE     STRUCT

        cpMin          DWORD            ?       ;选择区域的起始位置

        cpMax         DWORD             ?      ;选择区域的结束位置

CHARRANGE    ENDS

CHARFORMAT2    STRUCT

   cbSize                  DWORD     ?            ;结构的长度

   dwMask                DWORD     ?            ;字段掩码

   dwEffects            DWORD      ?            ;字段效果

   yHeight                 DWORD     ?            ;文字的高度

   yOffset                 DWORD      ?             ;

   crTextColor          DWORD     ?             ;文本的颜色

bCharSet             BYTE           ?            ;

    bPitchAndFamily   BYTE      ?             ;

   szFaceName        BYTE          LF_FACESIZE    dup(?)                   ;字体名称

   ;CHARFORMAT   结构的定义到此结束

  wWeight                  WORD        ?

  sSpacing                 WORD        ?

  crBackColor            DWORD        ?

  lcid                            DWORD       ?

  dwReserved            DWORD       ?

   sStyle                       WORD         ?

   wKerning                 WORD          ?

   bUnderlineType       BYTE          ?

   bAnimation               BYTE          ?

  bRevAuthor               BYTE           ?

   bReservedl               BYTE          ?

CHARFORMAT2           ENDS       

字段解释:

成员

cbSize:

结构的大小,由于控件使用该字段来判断结构的版本是CHARFORMAT还是CHARFORMAT2,所以在将结构传递给控件前必须将这个字段设置为正确的的数值。

dwMask:

字段掩码,用来指定结构中哪些字段是有效的,如果没有使用对应的标志,即使某些字段的内容被被设置,控件也不会使用它,dwMask中可以使用的标志可以是下列数值的组合:

CFM_BOLD------dwEffects字段中CFE_BOLDZ值是有效的。

CFM_CHARSET---------bCharSet字段是有效的。

CFM_COLOR---------crTextColor字段和dwEffects中的CFE_AUTOCOLOR值是有效的。

CFM_FACE-----------szFaceName字段的值是有效的。

CFM_ITALIC---------dwEffects字段中CFE_ITATIC值是有效的。

CFM_OFFSET--------yOffset字段是有效的。

CFM_PROTECTED-----dwEffects字段中的CFE_PROTECTED值是有效的。

CFM_SIZE------------yHeight字段是有效的。

CFM_STRIKEOUT-------dwEffects字段中的CFE_STRIKEOUT值是有效的。

CFM_UNDERLINE-------dwEffects字段中的CFE_UNDERLINE值是有效的。

dwEffects:

字符效果,可以是下列值的组合

CFE_AUTOCOLOR------使用系统正文颜色

CFE_BOLD,CFE_ITALIC,CFE_STRIKEOUT和CFE_UNDERLINE--------粗体字符,斜体字符,带删除线和带下划线。

CFE_PROTECTED--------字符是受保护的,企图改变字符的话,控件会向父窗口发送一个EN_PROTECTED通知消息

yHeight:

字符高度,单位是1/1440英寸(或1/20磅),如果这里是180,换算到“字体选择”通用对话框中的尺寸就是9磅(180* 1/20=9)。

yOffset:

从基线算起的字符偏移,单位同上,如果该成员是正值,字符显示为上标;如果是负值,字符显示为下标。

crTextColor:

正文颜色,如果在dwEffects字段中指定了CFE_AUTOCOLOR标志,那么这个值就会被忽略。

bCharSet:

字符集

bPitchAndFamily

字符集

szFaceName

用字符串表示的字体名字。

下面总结一下使用的陌生的API函数:

ReadFile()

功能:

文件指针指向的位置开始将数据读入到一个文件中

原型及参数:

BOOL ReadFile(

HANDLE hFile, //文件的句柄

LPVOID lpBuffer, //用于保存读入数据的一个缓冲区

DWORD nNumberOfBytesToRead, //要读入的字节数

LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针

LPOVERLAPPED lpOverlapped) //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。该结构定义了一次异步读取操作。否则,应将这个参数设为NULL  

FILE_FLAG_OVERLAPPED

文件或设备被打开或创建异步I / O。

当后续的I / O操作完成这个句柄,OVERLAPPED结构中指定的事件 将被设置为有信号状态。

如果这个标志被指定,该文件可用于同时读取和写入操作。

如果没有指定这个标志,然后被序列化I / O操作,即使调用读写函数指定一个OVERLAPPED结构。

返回值:

调用成功,返回非0

调用不成功,返回为0

WriteFile()

功能:

从文件指针指向的位置开始将数据写入到一个文件中(读出)

原型及参数:

BOOL WriteFile(

HANDLE hFile, // 文件句柄

LPCVOID lpBuffer, // 数据缓存区指针

DWORD nNumberOfBytesToWrite, // 你要写的字节数

LPDWORD lpNumberOfBytesWritten, // 用于保存实际写入字节数的存储区域的指针

LPOVERLAPPED lpOverlapped // OVERLAPPED结构体指针

);

返回值:

调用成功,返回非0

调用不成功,返回为0

CreateFile()

功能:

CreateFile函数创建或打开以下对象并返回一个句柄,可以用来访问对象:文件、管道、mailslots、通信资源、磁盘设备(Windows
NT只有)、consoles、目录(只开放)

原型:

HANDLE CreateFile(

LPCTSTR lpFileName, //指向文件名的指针

DWORD dwDesiredAccess, //访问模式(写/读)

DWORD dwShareMode, //共享模式

LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针

DWORD dwCreationDisposition, //如何创建

DWORD dwFlagsAndAttributes, //文件属性

HANDLE hTemplateFile //用于复制文件句柄

);

参数:

lpFileName String要打开的文件的名或设备名。这个字符串的最大长度在ANSI版本中为MAX_PATH,在unicode版本中为32767。

dwDesiredAccess指定类型的访问对象。如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息 。

另外,还可以指定下面的控制标志:

标准控制权限(16-23位掩码):

DELETE 删除对象的权限。

READ_CONTROL 从对象的安全描述符中读取信息的权限,但不包括SACL(系统访问控制列表)中的信息。

WRITE_DAC 修改对象安全描述符中的DACL(随机访问控制列表)的权限

WRITE_OWNER 修改对象安全描述符中的属主的权限

SYNCHRONIZE 同步化使用对象的权限,即可以创建一个线程等待信号量释放(但有些对象不支持这个权限)。

STANDARD_RIGHTS_REQUIRED 等价于前面四种权限的总合(通常这四种是必须具有的权限)。

STANDARD_RIGHTS_READ 一般等价于READ_CONTROL

STANDARD_RIGHTS_WRITE 一般等价于READ_CONTROL

STANDARD_RIGHTS_EXECUTE 一般等价于READ_CONTROL

STANDARD_RIGHTS_ALL 等价于前面五种权限的总合。

特殊控制权限(0-15位掩码):

SPECIFIC_RIGHTS_ALL

ACCESS_SYSTEM_SECURITY

MAXIMUM_ALLOWED

GENERIC_READ

GENERIC_WRITE

GENERIC_EXECUTE

GENERIC_ALL

注:实质上是通过ACCESS_MASK结构体的一个双字值来设置标准权限、特殊权限和一般权限的。

dwShareModeLong, 如果是零表示不共享; 如果是FILE_SHARE_DELETE表示随后打开操作对象会成功只要删除访问请求;如果是FILE_SHARE_READ随后打开操作对象会成功只有请求读访问;如果是FILE_SHARE_WRITE 随后打开操作对象会成功只有请求写访问。

lpSecurityAttributesSECURITY_ATTRIBUTES, 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)

dwCreationDispositionLong,下述常数之一:

CREATE_NEW 创建文件;如文件存在则会出错

CREATE_ALWAYS 创建文件,会改写前一个文件

OPEN_EXISTING 文件必须已经存在。由设备提出要求

OPEN_ALWAYS 如文件不存在则创建它

TRUNCATE_EXISTING 将现有文件缩短为零长度

dwFlagsAndAttributesLong:

 一个或多个下述常数

FILE_ATTRIBUTE_ARCHIVE 标记归档属性

FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式

FILE_ATTRIBUTE_NORMAL 默认属性

FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录

FILE_ATTRIBUTE_READONLY 文件为只读

FILE_ATTRIBUTE_SYSTEM 文件为系统文件

FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作

FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作

FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块

FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化

FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化

FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件

也可在Windows NT下组合使用下述常数标记:

SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY

返回值:

如执行成功,则返回文件句柄。

INVALID_HANDLE_VALUE表示出错,会设置GetLastError。即使函数成功,但若文件存在,且指定了CREATE_ALWAYS 或 OPEN_ALWAYS,GetLastError也会设为ERROR_ALREADY_EXISTS

CloseHandle()

功能:

关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等

原型:

BOOL CloseHandle(

HANDLE hObject

);

参数:

hObject :代表一个已打开对象handle。

返回值:

TRUE:执行成功;

FALSE:执行失败

SetFilePointer()

功能:

在一个文件中设置当前的读取位置。

原型:

DWORD SetFilePointer(

HANDLE hFile, // 文件句柄

LONG lDistanceToMove, // 偏移量(低位)

PLONG lpDistanceToMoveHigh, // 偏移量(高位)

DWORD dwMoveMethod // 基准位置FILE_BEGIN:文件开始位置 FILE_CURRENT:文件当前位置 FILE_END:文件结束位置

说明:移动一个打开文件的指针

返回值:

Long,返回一个新位置,它采用从文件起始处开始算起的一个字节偏移量。HFILE_ERROR意味着出错。会设置GetLastError

SetEndOfFile()

功能:

针对一个打开的文件,将当前文件位置设为文件末尾

原型:

BOOL WINAPI SetEndOfFile(

_In_ HANDLE hFile

);

参数:

hFile
Long,一个文件指定句柄。文件的当前位置设为文件尾,文件会根据需要缩短

返回值:

Long(32位整数),非零表示成功,零表示失败

SetFocus()

功能:

该函数对指定的窗口设置键盘焦点。该窗口必须与调用线程的消息队列相关。

原型:

HWND
SetFocus(HWND hWnd)

参数:

hWnd:接收键盘输入的窗口指针。若该参数为NULL,则击键被忽略

返回值:

若函数调用成功,则返回原先拥有键盘焦点的窗口句柄。若hWnd参数无效或窗口未与调用线程的消息队列相关,则返回值为NULL。

LoadLibrary()

功能:

载入指定的动态链接库,并将它映射到当前进程使用的地址空间。一旦载入,即可访问库内保存的资源

原型;

HMODULE
WINAPI LoadLibrary( _In_ LPCTSTR lpFileName);

参数:

lpFileName:要载入文件的名称.

一旦不需要,用FreeLibrary函数释放DLL

返回值:

Long,成功则返回库模块的句柄,零表示失

RegisterWindowMessage()

功能:

函数定义一个新的窗口消息,保证该消息在系统范围内是唯一的。通常调用SendMessage或者PostMessage函数时,可以使用该函数返回的消息值。

原型:

UINT
RegisterWindowMessage( lpString);

参数:

lpString
------- String,(被注册)消息的名字

返回值:

Long,&
C000 到 & FFFF之间的一个消息编号。零意味着出错(注册消息失败)

消息:

EM_GETMODIFY

功能:

得到一个编辑控件的状态的修改标记。表明编辑控件的内容是否已经被修改。你可以发送这个消息到一个编辑控件或丰富的编辑控件

参数:

按钮

未使用,必须为零。

lParam

未使用,必须为零。


返回值:


如果编辑控件的内容已经修改,返回值非零;否则,它是零。


WM_ACTIVATE


参数:

fActive  = LOWORD(wParam);   // activation flag

fMinimized = (BOOL)HIWORD(wParam); // minimized flag

hwndPrevious= (HWND)lParam;   // window handle

fActive 参数主要定义了该窗口发生了什么事情,即该窗口是被激活还是被取消。该

信息保存在 wParam 的低阶字中,可以取以下的值:

WA_CLICKACTIVE       通过鼠标单击激活了该窗口

WA_ACTIVE                   通过鼠标以外的工具(如键盘)激活了该窗口

WA_INACTIVE               取消该窗口的激活

示例代码:

case WM_ACTIVATE:

{

// test if window is being activated

if(LOWORD(wParam)!=WA_INACTIVE)

{

// application is being activated

}

else

{

// application is being deactivated

}

}

break;




时间: 2024-08-06 03:44:33

WIN32汇编 Richedit控件的使用的相关文章

win32 sdk树形控件的项拖拽实现

本课中,我们将学习如何使用树型视图控件.另外还要学习如何在树型视图中完成拖-拉动作,以及如何使用图象列表. 理论: 树型视图是一种特别的窗口,我们可以使用它一目了然地表示某种层次关系.譬如象在资源管理器中左边窗口中的就是树型视图.您可以调用CreateWindowEx来创建树型视图,传递一个类名""SysTreeView32"",或者您也可以把它放到一个对话框中去.不要忘了在您的代码中加入InitCommonControls函数. 树型视图有几种特有的风格.下面是几

GUI库中RichEdit控件开发的林林总总

之前开发了RichEdit控件,现在回顾总结一下. Rich text format格式(通常缩写为RTF)是一种专有的文档文件格式,是1987年Microsoft对文件跨平台交换开发发布的规范,详情参考维基百科Rich text format(http://en.wikipedia.org/wiki/Rich_Text_Format),该格式支持在文档中显示多种类型的文本对象.该格式文档以带有转义序列的纯文本形式存储和交换. 游戏UI库中的richtext一般包含带颜色效果文本,图片,表情,超

Win32中TreeView控件的使用方法,类似于资源管理器中文件树形显示方式

首先是头文件,内容如下: #include <tchar.h> #include "..\CommonFiles\CmnHdr.h" #include <Windows.h> #include <WindowsX.h> #include <CommCtrl.h> #include "resource.h" #pragma comment (lib,"comctl32.lib") BOOL InitT

实现:win32实现EDIT控件读取和保存

#pragma warning(disable:4996) #include<windows.h> #include<string> #include<fstream> #define HDC_EDIT_1 0x100 #define HDC_BUTTON_1 0x101 #define HDC_BUTTON_2 0x102 //全局变量声明 HINSTANCE hinst; //函数声明 int WINAPI WinMain(HINSTANCE, HINSTANCE,

Duilib中为RichEdit\Edit控件添加自定义右键菜单

前言 Duilib中的RichEdit控件在使用中发现,基本上对复制.粘贴.剪切等快捷方式都是支持的,不过唯一缺点是没有右键菜单,感觉不够好,于是就想着加上右键菜单. 右键菜单基本思路是,在RichEdit的消息处理函数中对鼠标的右键消息处理,发送一个自定义的Notify消息出来,主窗口中受到这个消息后弹出自己的右键菜单. 实现方法 第一步:把鼠标右键消息转发出来 MessageHandler中修改原有代码 bool bWasHandled = true; if( (uMsg >= WM_MOU

通过编写串口助手工具学习MFC过程&mdash;&mdash;(六)添加Edit编辑框控件

通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个串口助手再次熟悉一下MFC,并做了一下记录,以便方便以后查阅.做的过程中多是遇到问题直接百度和谷歌搜索来的,所以很多都是不求甚解,知其然不知其所以然.另外做此工具只是为了熟悉了解,许多功能还没有完善!(开发工具VS2008) (六)添加Edit编辑框控件 属性说明: Auto HScroll 设置T

VCL组件之编辑控件

Note 以后将用两种方式提及组件,以组件的名称或定义组件的VCL类的名称.可以说“Label组件用于……”或说“TLabel用于……”,这两种方式谈到的是同一组件. 编辑控件(Edit Control) Delphi共有5个编辑控件组件,Edit.Memo.MaskEdit.RichEdit(该控件不是标准Windows控件)和SpinEdit(数字编辑框),在此讨论因为它与其他编辑控件有许多相同的特点. 1.Edit组件 Edit组件封装基本的单行编辑控件,这个组件没有Align和Align

发布 Victor 串口控件, 版本 1.5.0.6 VCL/FMX for C++ Builder 10.2 Tokyo, 10.1 Berlin, 10.0 Seattle, XE8, XE7, XE6 包括源码、演示程序

本次发布的 Victor 串口控件 1.5.0.6 包括 VCL 和 FMX (Firemonkey), 支持 C++ Builder 10.2 Tokyo, 10.1 Berlin, 10.0 Seattle, XE8, XE7, XE6 - Win32/Win64 支持其他版本 C++ Builder 的控件的发布和更新进度请关注网站主页的内容. Victor 串口控件 1.5.0.6 VCL/FMX 更新内容: ? 增加支持 FMX (Firemonkey) Win32/Win64,控件包

Victor 串口控件 1.5.0.6 VCL/FMX for C++ Builder 10.2 Tokyo, 10.1 Berlin, 10.0 Seattle, XE8, XE7, XE6 已经发布

Victor 串口控件 1.5.0.6 更新内容: ? 增加支持 FMX (Firemonkey) Win32/Win64,控件包含 VCL 和 FMX 两个框架版本的,可以同时安装  ? 增加 FSM (Finite State Machine) 控件,包括 TVictorFSM 控件和 TVictorFsmStateT 模板,用于结构化处理跳转多而复杂的程序  ? 重新整理和编写例子程序,包括接收和发送二进制数据.收发字符串或文本.收发文件.通过调制解调器拨号和收发数据.枚举串口  ? 新版