Win32 API. Урок 34. RichEdit Control: больше об операциях над текстом

Дата публикации 4 июн 2002

Win32 API. Урок 34. RichEdit Control: больше об операциях над текстом — Архив WASM.RU

  В этом туториале вы узнаете больше о операциях над текстом, доступных в RichEdit, например о том, как искать/заменять текст и переходить к опрееленной строке.

  Скачайте пример.

ТЕОРИЯ

  Поиск текста

  В RichEdit есть несколько текстовых операций. Поиск определенного текста - одна из них. Поиск текста осуществляется с помощью сообщений EM_FINDTEXT или EM_FINDTEXTEX. Эти сообщения мало отличаются друг от друга.

Код (Text):
  1.  
  2. EM_FINDTEXT
  3.  

  wParam == опции поиска.

  Может быть комбинацией значений, приведенных ниже. Эти опции идентичны как для EM_FINDTEXT, так и для EM_FINDTEXTEX.

  • FR_DOWN - если этот флаг указан, поиск начинается с конца текущего выделенного текста и до самого конца (вперед). Этот флаг действует только в RichEdit 2.0 или выше: этот способ применяется по умолчанию в RichEdit 1.0. В RichEdit 2.0 по умолчанию поиск осуществляется от конца выделенного текста до начала (назад). Кратко говоря, если вы используете RichEdit 1.0, вы ничего не можете сделать, чтобы изменить направление поиска: он всегда ищет вперед. Если вы используете RichEdit 2.0 и хотите искать вперед, вам нужно указать этот флаг, иначе поиск будет производиться назад.
  • FR_MATCHCASE - если этот флаг указан, будет учитываться регистр.
  • FR_WHOLEWORD - если этот флаг указан, поиск будет искать место в тексте, которое будет удовлетворять указанной поисковой строке.

  Вообще-то, есть еще несколько флагов, но они относятся к языкам, отличным от английского.

  lParam == указатель на структуру FINDTEXT.

Код (Text):
  1.  
  2. FINDTEXT STRUCT
  3.   chrg      CHARRANGE  <>
  4.   lpstrText DWORD      ?
  5. FINDTEXT ENDS
  6.  

  chrg - это структура CHARRANGE, которая определена следующим образом:

Код (Text):
  1.  
  2. CHARRANGE STRUCT
  3.   cpMin  DWORD  ?
  4.   cpMax  DWORD  ?
  5. CHARRANGE ENDS
  6.  

  cpMin содержит индекс первого символа в массиве символов (диапазон).

  cpMax содержит индекс символа, который следует непосредственно за последним символов в массиве символов.

  Фактически, чтобы найти строку текста, вам нужно указать диапазон символом, в котором нужно искать. Значение cpMin и cpMax будут зависить от того, проводится ли поиск назад или вперед. Если поиск идет вперед, cpMin задает начальный индекс, а cpMax - конечный. Если поиск идет назад, тогда cpMin содержит конечное значение индекса, в то время как cpMax задает начальный индекс.

  lpstrText - это указатель на текстовую строку, которую нужно искать.

  EM_FINDTEXT возвращает индес первого символа в заданной текстовой строке в RichEdit. Оно возвращает -1, если указанный текст не был найден.

  EM_FINDTEXTEX

  wParam == опции поиска. То же самое, что и EM_FINDTEXT. lParam == указатель на структуру FINDTEXTEX.

Код (Text):
  1.  
  2. FINDTEXTEX STRUCT
  3.   chrg          CHARRANGE  <>
  4.   lpstrText     DWORD      ?
  5.   chrgText   CHARRANGE <>
  6. FINDTEXTEX ENDS
  7.  

  Первые два члена FINDTEXTEX идентичны соответствующим полям в структуре FINDTEXT. chrgText - это структура CHARRANGE, которая будет заполнена начальным и конечным индексами, если будут найдены какие-либо совпадения.

  Возвращаемое значение EM_FINDTEXTEX - то же самое, что и у EM_FINDTEXT.

  Разница между EM_FINDTEXT и EM_FINDTEXTEXT - это то, что у структуры FINDTEXTEX есть дополнительное поле, chrgText, которое будет заполненено начальным и конечным индексами, если будут найдены совпадения. Это удобно, если мы хотим иметьвозможность осуществлять больше текстовых операций над строкой.

  Замещение/вставка текста

  Контрол RichEdit предоставляет EM_SETTEXTEX для замещения/вставки текста. Это сообщение комбинирует функциональность WM_SETTEXT и WM_REPLACESEL. У него следующий синтасис:

  EM_SETTEXTEXT wParam == указатель на структуру SETTEXTEX.

Код (Text):
  1.  
  2. SETTEXTEX STRUCT
  3.   flags     DWORD  ?
  4.   codepage  DWORD  ?
  5. SETTEXTEX ENDS
  6.  

  Поле 'flags' может быть комбинацией следующих значений:

  • ST_DEFAULT - удаляет стек совершенных операций, сбрасывает форматирование RichEdit.
  • ST_KEEPUNDO - сохраняет стек совершенных операций.
  • ST_SELECTION - замещает выделенный текст и сохраняет форматирование.

  Поле 'codepage' - это константа, которая указывает кодовую страницу. Обычно мы указываем CP_ACP.

  Выделение текста

  Мы можем выделить текст программно с помощью сообщений EM_SETSEL или EM_EXSETSEL. Обе прекрасно работают. Выбирать, какое из сообщений необходимо использовать, зависит от доступного формата индексов символов. Если они уже сохранены в структуры CHARRANGE, проще использовать EM_EXSETSEL.

  EM_EXSETSEL

  wParam == не используется. Должен быть равен 0. lParam == указатель на структуру CHARRANGE, который содержит диапазон символов, который необходимо выделить.

  Уведомительные события

  В случае с многолинейным edit control'ом вам необходимо сабклассировать его, чтобы получить входные сообщения, такие как события мыши/клавиатуры. RichEdit предоставляет лучший способ: он будет уведомлять родительское окно о таких событиях. Чтобы указать RichEdit, какие события нужно посылать, родительское окно посылает сообщение EM_SETEVENTMASK контролу RichEdit, указывая, в каких событиях он заинтересован. У EM_SETEVENTMASK следующий синтаксис:

  EM_SETEVENTMASK

  wParam == не используется. Должен быть равен нулю. lParam == маска событий. Это должна быть комбинация флагов, указанных ниже.

  • ENM_CHANGE - прием уведомлений EN_CHANGE.
  • ENM_CORRECTTEXT - прием уведомлений EN_CORRECTTEXT.
  • ENM_DRAGDROPDONE - прием уведомлений EN_DRAGDROPDONE.
  • ENM_DROPFILES - прием уведомлений EN_DROPFILES.
  • ENM_KEYEVENTS - прием уведомлений EN_MSGFILTER, относящихся к событиям от клавиатуры.
  • ENM_LINK - RichEdit 2.0 и выше: прием уведомлений EN_LINK, когда курсор мыши находится над текстом, который принимает CFE_LINK и/или другие события от мыши.
  • ENM_MOUSEEVENTS - прием уведомлений EN_MSGFILTER, относящихся к событиям от мыши.
  • ENM_OBJECTPOSITIONS - прием уведомлений EN_OBJECTPOSITIONS.
  • ENM_PROTECTED - прием уведомлений EN_PROTECTED.
  • ENM_REQUESTRESIZE - прием уведомлений EN_REQUESTRESIZE.
  • ENM_SCROLL - прием уведомлений EN_HSCROLL и EN_VSCROLL.
  • ENM_SCROLLEVENTS - прием уведомлений EN_MSGFILTER от колесика мыши.
  • ENM_SELCHANGE - прием уведомлений EN_SELCHANGE.
  • ENM_UPDATE - прием уведомлений EN_UPDATE. RichEdit 2.0 и выше: этот флаг игнорирует, а сообщения EN_UPDATE отсылаются всегда. Тем не менее, если Rich Edit 3.0 эмулирует Rich Edit 1.0, вы должны указать этот флаг для того, чтобы родительское окно принимало уведомления EN_UPDATE.

  Все вышеуказанные уведомления будут отсылаться через сообщение WM_NOTIFY: вы должны проверить поле 'code' структуры NMHDR, чтобы узнать, какое уведомление вы получили. Например, если вы хотите зарегистрировать сообщения от мыши (скажем, чтобы отображать контекстное меню по нажатию на правую кнопку мыши), вы дожны сдлеать что-то вроде следующего:

Код (Text):
  1.  
  2. invoke SendMessage,hwndRichEdit,EM_SETEVENTMASK,
  3.                    0,ENM_MOUSEEVENTS
  4. .....
  5. .....
  6. WndProc proc hWnd:DWORD, uMsg:DWORD,
  7.              wParam:DWORD, lParam:DWORD
  8. .....
  9. ....
  10.  .elseif uMsg==WM_NOTIFY
  11.        push esi
  12.        mov esi,lParam
  13.        assume esi:ptr NMHDR
  14. .if [esi].code==EN_MSGFILTER
  15.           ....
  16.           [ do something here]
  17.           ....
  18.        .endif
  19.        pop esi
  20.  

ПРИМЕР

  Следующий пример является обновлением IczEdit, шедшего вместе с туториалом 33. Были добавлены возможности поиска/замещения и акселераторы. Также обрабатываются события от мыши и отображается контекстное меню.

Код (Text):
  1.  
  2.   .386
  3.   .model flat,stdcall
  4.   option casemap:none
  5.   include \masm32\include\windows.inc
  6.   include \masm32\include\user32.inc
  7.   include \masm32\include\comdlg32.inc
  8.   include \masm32\include\gdi32.inc
  9.   include \masm32\include\kernel32.inc
  10.   includelib \masm32\lib\gdi32.lib
  11.   includelib \masm32\lib\comdlg32.lib
  12.   includelib \masm32\lib\user32.lib
  13.   includelib \masm32\lib\kernel32.lib
  14.  
  15.   WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
  16.  
  17.   .const
  18.   IDR_MAINMENU                   equ 101
  19.   IDM_OPEN                      equ  40001
  20.   IDM_SAVE                       equ 40002
  21.   IDM_CLOSE                      equ 40003
  22.   IDM_SAVEAS                     equ 40004
  23.   IDM_EXIT                       equ 40005
  24.   IDM_COPY                      equ  40006
  25.   IDM_CUT                       equ  40007
  26.   IDM_PASTE                      equ 40008
  27.   IDM_DELETE                     equ 40009
  28.   IDM_SELECTALL                  equ 40010
  29.   IDM_OPTION          equ 40011
  30.   IDM_UNDO        equ 40012
  31.   IDM_REDO        equ 40013
  32.   IDD_OPTIONDLG                  equ 101
  33.   IDC_BACKCOLORBOX               equ 1000
  34.   IDC_TEXTCOLORBOX               equ 1001
  35.   IDR_MAINACCEL                 equ  105
  36.   IDD_FINDDLG                    equ 102
  37.   IDD_GOTODLG                    equ 103
  38.   IDD_REPLACEDLG                 equ 104
  39.   IDC_FINDEDIT                  equ  1000
  40.   IDC_MATCHCASE                  equ 1001
  41.   IDC_REPLACEEDIT                 equ 1001
  42.   IDC_WHOLEWORD                  equ 1002
  43.   IDC_DOWN                       equ 1003
  44.   IDC_UP                       equ   1004
  45.   IDC_LINENO                   equ   1005
  46.   IDM_FIND                       equ 40014
  47.   IDM_FINDNEXT                  equ  40015
  48.   IDM_REPLACE                     equ 40016
  49.   IDM_GOTOLINE                   equ 40017
  50.   IDM_FINDPREV                  equ  40018
  51.   RichEditID          equ 300
  52.  
  53.   .data
  54.   ClassName db "IczEditClass",0
  55.   AppName  db "IczEdit version 2.0",0
  56.   RichEditDLL db "riched20.dll",0
  57.   RichEditClass db "RichEdit20A",0
  58.   NoRichEdit db "Cannot find riched20.dll",0
  59.   ASMFilterString     db "ASM Source code (*.asm)",0,"*.asm",0
  60.                db "All Files (*.*)",0,"*.*",0,0
  61.   OpenFileFail db "Cannot open the file",0
  62.   WannaSave db "The data in the control is modified. Want to save it?",0
  63.   FileOpened dd FALSE
  64.   BackgroundColor dd 0FFFFFFh      ; default to white
  65.   TextColor dd 0      ; default to black
  66.   hSearch dd ?    ; handle to the search/replace dialog box
  67.   hAccel dd ?
  68.  
  69.   .data?
  70.   hInstance dd ?
  71.   hRichEdit dd ?
  72.   hwndRichEdit dd ?
  73.   FileName db 256 dup(?)
  74.   AlternateFileName db 256 dup(?)
  75.   CustomColors dd 16 dup(?)
  76.   FindBuffer db 256 dup(?)
  77.   ReplaceBuffer db 256 dup(?)
  78.   uFlags dd ?
  79.   findtext FINDTEXTEX
  80.  
  81.   .code
  82.   start:
  83.      mov byte ptr [FindBuffer],0
  84.      mov byte ptr [ReplaceBuffer],0
  85.      invoke GetModuleHandle, NULL
  86.      mov    hInstance,eax
  87.      invoke LoadLibrary,addr RichEditDLL
  88.      .if eax!=0
  89.         mov hRichEdit,eax
  90.         invoke WinMain, hInstance,0,0, SW_SHOWDEFAULT
  91.         invoke FreeLibrary,hRichEdit
  92.      .else
  93.         invoke MessageBox,0,addr NoRichEdit,addr AppName,MB_OK or MB_ICONERROR
  94.      .endif
  95.      invoke ExitProcess,eax
  96.  
  97.   WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
  98.      LOCAL wc:WNDCLASSEX
  99.      LOCAL msg:MSG
  100.      LOCAL hwnd:DWORD
  101.      mov   wc.cbSize,SIZEOF WNDCLASSEX
  102.      mov   wc.style, CS_HREDRAW or CS_VREDRAW
  103.      mov   wc.lpfnWndProc, OFFSET WndProc
  104.      mov   wc.cbClsExtra,NULL
  105.      mov   wc.cbWndExtra,NULL
  106.      push  hInst
  107.      pop   wc.hInstance
  108.      mov   wc.hbrBackground,COLOR_WINDOW+1
  109.      mov   wc.lpszMenuName,IDR_MAINMENU
  110.      mov   wc.lpszClassName,OFFSET ClassName
  111.      invoke LoadIcon,NULL,IDI_APPLICATION
  112.      mov   wc.hIcon,eax
  113.      mov   wc.hIconSm,eax
  114.      invoke LoadCursor,NULL,IDC_ARROW
  115.      mov   wc.hCursor,eax
  116.      invoke RegisterClassEx, addr wc
  117.      INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
  118.              WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
  119.              CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
  120.              hInst,NULL
  121.      mov   hwnd,eax
  122.      invoke ShowWindow, hwnd,SW_SHOWNORMAL
  123.      invoke UpdateWindow, hwnd
  124.      invoke LoadAccelerators,hInstance,IDR_MAINACCEL
  125.      mov hAccel,eax
  126.      .while TRUE
  127.         invoke GetMessage, ADDR msg,0,0,0
  128.         .break .if (!eax)
  129.         invoke IsDialogMessage,hSearch,addr msg
  130.         .if eax==FALSE
  131.             invoke TranslateAccelerator,hwnd,hAccel,addr msg
  132.             .if eax==0
  133.                invoke TranslateMessage, ADDR msg
  134.                invoke DispatchMessage, ADDR msg
  135.             .endif
  136.         .endif
  137.      .endw
  138.      mov   eax,msg.wParam
  139.      ret
  140.   WinMain endp
  141.  
  142.   StreamInProc proc hFile:DWORD,pBuffer:DWORD,
  143.                     NumBytes:DWORD, pBytesRead:DWORD
  144.      invoke ReadFile,hFile,pBuffer,NumBytes,pBytesRead,0
  145.      xor eax,1
  146.      ret
  147.   StreamInProc endp
  148.  
  149.   StreamOutProc proc hFile:DWORD,pBuffer:DWORD, NumBytes:DWORD,
  150.                      pBytesWritten:DWORD
  151.      invoke WriteFile,hFile,pBuffer,NumBytes,pBytesWritten,0
  152.      xor eax,1
  153.      ret
  154.   StreamOutProc endp
  155.  
  156.   CheckModifyState proc hWnd:DWORD
  157.      invoke SendMessage,hwndRichEdit,EM_GETMODIFY,0,0
  158.      .if eax!=0
  159.         invoke MessageBox,hWnd,addr WannaSave,addr AppName,MB_YESNOCANCEL
  160.         .if eax==IDYES
  161.             invoke SendMessage,hWnd,WM_COMMAND,IDM_SAVE,0
  162.         .elseif eax==IDCANCEL
  163.             mov eax,FALSE
  164.             ret
  165.         .endif
  166.      .endif
  167.      mov eax,TRUE
  168.      ret
  169.   CheckModifyState endp
  170.  
  171.   SetColor proc
  172.      LOCAL cfm:CHARFORMAT
  173.      invoke SendMessage,hwndRichEdit,EM_SETBKGNDCOLOR,0,BackgroundColor
  174.      invoke RtlZeroMemory,addr cfm,sizeof cfm
  175.      mov cfm.cbSize,sizeof cfm
  176.      mov cfm.dwMask,CFM_COLOR
  177.      push TextColor
  178.      pop cfm.crTextColor
  179.      invoke SendMessage,hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,addr cfm
  180.      ret
  181.   SetColor endp
  182.  
  183.   OptionProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
  184.      LOCAL clr:CHOOSECOLOR
  185.      .if uMsg==WM_INITDIALOG
  186.      .elseif uMsg==WM_COMMAND
  187.         mov eax,wParam
  188.         shr eax,16
  189.         .if ax==BN_CLICKED
  190.             mov eax,wParam
  191.             .if ax==IDCANCEL
  192.                invoke SendMessage,hWnd,WM_CLOSE,0,0
  193.             .elseif ax==IDC_BACKCOLORBOX
  194.                invoke RtlZeroMemory,addr clr,sizeof clr
  195.                mov clr.lStructSize,sizeof clr
  196.                push hWnd
  197.                pop clr.hwndOwner
  198.                push hInstance
  199.                pop clr.hInstance
  200.                push BackgroundColor
  201.                pop clr.rgbResult
  202.                mov clr.lpCustColors,offset CustomColors
  203.                mov clr.Flags,CC_ANYCOLOR or CC_RGBINIT
  204.                invoke ChooseColor,addr clr
  205.                .if eax!=0
  206.                   push clr.rgbResult
  207.                   pop BackgroundColor
  208.                   invoke GetDlgItem,hWnd,IDC_BACKCOLORBOX
  209.                   invoke InvalidateRect,eax,0,TRUE
  210.                .endif
  211.             .elseif ax==IDC_TEXTCOLORBOX
  212.                invoke RtlZeroMemory,addr clr,sizeof clr
  213.                mov clr.lStructSize,sizeof clr
  214.                push hWnd
  215.                pop clr.hwndOwner
  216.                push hInstance
  217.                pop clr.hInstance
  218.                push TextColor
  219.                pop clr.rgbResult
  220.                mov clr.lpCustColors,offset CustomColors
  221.                mov clr.Flags,CC_ANYCOLOR or CC_RGBINIT
  222.                invoke ChooseColor,addr clr
  223.                .if eax!=0
  224.                   push clr.rgbResult
  225.                   pop TextColor
  226.                   invoke GetDlgItem,hWnd,IDC_TEXTCOLORBOX
  227.                   invoke InvalidateRect,eax,0,TRUE
  228.                .endif
  229.             .elseif ax==IDOK
  230.                invoke SendMessage,hwndRichEdit,EM_GETMODIFY,0,0
  231.                push eax
  232.                invoke SetColor
  233.                pop eax
  234.                invoke SendMessage,hwndRichEdit,EM_SETMODIFY,eax,0
  235.                invoke EndDialog,hWnd,0
  236.             .endif
  237.         .endif
  238.      .elseif uMsg==WM_CTLCOLORSTATIC
  239.         invoke GetDlgItem,hWnd,IDC_BACKCOLORBOX
  240.         .if eax==lParam
  241.             invoke CreateSolidBrush,BackgroundColor
  242.             ret
  243.         .else
  244.             invoke GetDlgItem,hWnd,IDC_TEXTCOLORBOX
  245.             .if eax==lParam
  246.                invoke CreateSolidBrush,TextColor
  247.                ret
  248.   .endif
  249.         .endif
  250.         mov eax,FALSE
  251.         ret
  252.      .elseif uMsg==WM_CLOSE
  253.         invoke EndDialog,hWnd,0
  254.      .else
  255.         mov eax,FALSE
  256.         ret
  257.      .endif
  258.      mov eax,TRUE
  259.      ret
  260.   OptionProc endp
  261.  
  262.   SearchProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
  263.      .if uMsg==WM_INITDIALOG
  264.         push hWnd
  265.         pop hSearch
  266.         invoke CheckRadioButton,hWnd,IDC_DOWN,IDC_UP,IDC_DOWN
  267.         invoke SendDlgItemMessage,hWnd,IDC_FINDEDIT,
  268.                WM_SETTEXT,0,addr FindBuffer
  269.      .elseif uMsg==WM_COMMAND
  270.         mov eax,wParam
  271.         shr eax,16
  272.         .if ax==BN_CLICKED
  273.             mov eax,wParam
  274.             .if ax==IDOK
  275.                mov uFlags,0
  276.                invoke SendMessage,hwndRichEdit,
  277.                       EM_EXGETSEL,0,addr findtext.chrg
  278.                invoke GetDlgItemText,hWnd,IDC_FINDEDIT,
  279.                       addr FindBuffer,sizeof FindBuffer
  280.                .if eax!=0
  281.                   invoke IsDlgButtonChecked,hWnd,IDC_DOWN
  282.                   .if eax==BST_CHECKED
  283.                       or uFlags,FR_DOWN
  284.                       mov eax,findtext.chrg.cpMin
  285.                       .if eax!=findtext.chrg.cpMax
  286.                          push findtext.chrg.cpMax
  287.                          pop findtext.chrg.cpMin
  288.                       .endif
  289.                       mov findtext.chrg.cpMax,-1
  290.                   .else
  291.                       mov findtext.chrg.cpMax,0
  292.                   .endif
  293.                   invoke IsDlgButtonChecked,hWnd,IDC_MATCHCASE
  294.                   .if eax==BST_CHECKED
  295.                       or uFlags,FR_MATCHCASE
  296.                   .endif
  297.                   invoke IsDlgButtonChecked,hWnd,IDC_WHOLEWORD
  298.                   .if eax==BST_CHECKED
  299.                       or uFlags,FR_WHOLEWORD
  300.                   .endif
  301.                   mov findtext.lpstrText,offset FindBuffer
  302.                   invoke SendMessage,hwndRichEdit,EM_FINDTEXTEX,
  303.                          uFlags,addr findtext
  304.                   .if eax!=-1
  305.                       invoke SendMessage,hwndRichEdit,EM_EXSETSEL,0,
  306.                              addr findtext.chrgText
  307.                   .endif
  308.                .endif
  309.             .elseif ax==IDCANCEL
  310.                invoke SendMessage,hWnd,WM_CLOSE,0,0
  311.             .else
  312.                mov eax,FALSE
  313.                ret
  314.             .endif
  315.         .endif
  316.      .elseif uMsg==WM_CLOSE
  317.         mov hSearch,0
  318.         invoke EndDialog,hWnd,0
  319.      .else
  320.         mov eax,FALSE
  321.         ret
  322.      .endif
  323.      mov eax,TRUE
  324.      ret
  325.   SearchProc endp
  326.  
  327.   ReplaceProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
  328.      LOCAL settext:SETTEXTEX
  329.      .if uMsg==WM_INITDIALOG
  330.         push hWnd
  331.         pop hSearch
  332.         invoke SetDlgItemText,hWnd,IDC_FINDEDIT,addr FindBuffer
  333.         invoke SetDlgItemText,hWnd,IDC_REPLACEEDIT,addr ReplaceBuffer
  334.      .elseif uMsg==WM_COMMAND
  335.         mov eax,wParam
  336.         shr eax,16
  337.         .if ax==BN_CLICKED
  338.             mov eax,wParam
  339.             .if ax==IDCANCEL
  340.                invoke SendMessage,hWnd,WM_CLOSE,0,0
  341.             .elseif ax==IDOK
  342.                invoke GetDlgItemText,hWnd,IDC_FINDEDIT,
  343.                       addr FindBuffer,sizeof FindBuffer
  344.                invoke GetDlgItemText,hWnd,IDC_REPLACEEDIT,
  345.                       addr ReplaceBuffer,sizeof ReplaceBuffer
  346.                mov findtext.chrg.cpMin,0
  347.                mov findtext.chrg.cpMax,-1
  348.                mov findtext.lpstrText,offset FindBuffer
  349.                mov settext.flags,ST_SELECTION
  350.                mov settext.codepage,CP_ACP
  351.                .while TRUE
  352.                   invoke SendMessage,hwndRichEdit,EM_FINDTEXTEX,
  353.                          FR_DOWN,addr findtext
  354.                   .if eax==-1
  355.                       .break
  356.                   .else
  357.                       invoke SendMessage,hwndRichEdit,EM_EXSETSEL,0,
  358.                          addr findtext.chrgText
  359.                       invoke SendMessage,hwndRichEdit,EM_SETTEXTEX,
  360.                       addr settext,addr ReplaceBuffer
  361.                   .endif
  362.                .endw
  363.             .endif
  364.         .endif
  365.      .elseif uMsg==WM_CLOSE
  366.         mov hSearch,0
  367.         invoke EndDialog,hWnd,0
  368.      .else
  369.         mov eax,FALSE
  370.         ret
  371.      .endif
  372.      mov eax,TRUE
  373.      ret
  374.   ReplaceProc endp
  375.  
  376.   GoToProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
  377.      LOCAL LineNo:DWORD
  378.      LOCAL chrg:CHARRANGE
  379.      .if uMsg==WM_INITDIALOG
  380.         push hWnd
  381.         pop hSearch
  382.      .elseif uMsg==WM_COMMAND
  383.         mov eax,wParam
  384.         shr eax,16
  385.         .if ax==BN_CLICKED
  386.             mov eax,wParam
  387.             .if ax==IDCANCEL
  388.                invoke SendMessage,hWnd,WM_CLOSE,0,0
  389.             .elseif ax==IDOK
  390.                invoke GetDlgItemInt,hWnd,IDC_LINENO,NULL,FALSE
  391.                mov LineNo,eax
  392.                invoke SendMessage,hwndRichEdit,EM_GETLINECOUNT,0,0
  393.                .if eax>LineNo
  394.                   invoke SendMessage,hwndRichEdit,EM_LINEINDEX,LineNo,0
  395.                   mov chrg.cpMin,eax
  396.                   mov chrg.cpMax,eax
  397.                   invoke SendMessage,hwndRichEdit,EM_EXSETSEL,0,addr chrg
  398.                   invoke SetFocus,hwndRichEdit
  399.                .endif
  400.             .endif
  401.         .endif
  402.      .elseif uMsg==WM_CLOSE
  403.         mov hSearch,0
  404.         invoke EndDialog,hWnd,0
  405.      .else
  406.         mov eax,FALSE
  407.         ret
  408.      .endif
  409.      mov eax,TRUE
  410.      ret
  411.   GoToProc endp
  412.  
  413.   PrepareEditMenu proc hSubMenu:DWORD
  414.      LOCAL chrg:CHARRANGE
  415.      invoke SendMessage,hwndRichEdit,EM_CANPASTE,CF_TEXT,0
  416.      .if eax==0       ; no text in the clipboard
  417.         invoke EnableMenuItem,hSubMenu,IDM_PASTE,MF_GRAYED
  418.      .else
  419.         invoke EnableMenuItem,hSubMenu,IDM_PASTE,MF_ENABLED
  420.      .endif
  421.      invoke SendMessage,hwndRichEdit,EM_CANUNDO,0,0
  422.      .if eax==0
  423.         invoke EnableMenuItem,hSubMenu,IDM_UNDO,MF_GRAYED
  424.      .else
  425.         invoke EnableMenuItem,hSubMenu,IDM_UNDO,MF_ENABLED
  426.      .endif
  427.      invoke SendMessage,hwndRichEdit,EM_CANREDO,0,0
  428.      .if eax==0
  429.         invoke EnableMenuItem,hSubMenu,IDM_REDO,MF_GRAYED
  430.      .else
  431.         invoke EnableMenuItem,hSubMenu,IDM_REDO,MF_ENABLED
  432.      .endif
  433.      invoke SendMessage,hwndRichEdit,EM_EXGETSEL,0,addr chrg
  434.      mov eax,chrg.cpMin
  435.      .if eax==chrg.cpMax    ; no current selection
  436.         invoke EnableMenuItem,hSubMenu,IDM_COPY,MF_GRAYED
  437.         invoke EnableMenuItem,hSubMenu,IDM_CUT,MF_GRAYED
  438.         invoke EnableMenuItem,hSubMenu,IDM_DELETE,MF_GRAYED
  439.      .else
  440.         invoke EnableMenuItem,hSubMenu,IDM_COPY,MF_ENABLED
  441.         invoke EnableMenuItem,hSubMenu,IDM_CUT,MF_ENABLED
  442.         invoke EnableMenuItem,hSubMenu,IDM_DELETE,MF_ENABLED
  443.      .endif
  444.      ret
  445.   PrepareEditMenu endp
  446.  
  447.   WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
  448.      LOCAL ofn:OPENFILENAME
  449.      LOCAL buffer[256]:BYTE
  450.      LOCAL editstream:EDITSTREAM
  451.      LOCAL hFile:DWORD
  452.      LOCAL hPopup:DWORD
  453.      LOCAL pt:POINT
  454.      LOCAL chrg:CHARRANGE
  455.      .if uMsg==WM_CREATE
  456.         invoke CreateWindowEx,WS_EX_CLIENTEDGE,addr RichEditClass,0, \
  457.                WS_CHILD or WS_VISIBLE or ES_MULTILINE or
  458.                WS_VSCROLL or WS_HSCROLL or ES_NOHIDESEL,\
  459.                CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
  460.                CW_USEDEFAULT,hWnd,RichEditID,hInstance,0
  461.         mov hwndRichEdit,eax
  462.         invoke SendMessage,hwndRichEdit,EM_LIMITTEXT,-1,0
  463.         invoke SetColor
  464.         invoke SendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0
  465.         invoke SendMessage,hwndRichEdit,EM_SETEVENTMASK,0,ENM_MOUSEEVENTS
  466.         invoke SendMessage,hwndRichEdit,EM_EMPTYUNDOBUFFER,0,0
  467.      .elseif uMsg==WM_NOTIFY
  468.         push esi
  469.         mov esi,lParam
  470.         assume esi:ptr NMHDR
  471.         .if [esi].code==EN_MSGFILTER
  472.             assume esi:ptr MSGFILTER
  473.             .if [esi].msg==WM_RBUTTONDOWN
  474.                invoke GetMenu,hWnd
  475.                invoke GetSubMenu,eax,1
  476.                mov hPopup,eax
  477.                invoke PrepareEditMenu,hPopup
  478.                mov edx,[esi].lParam
  479.                mov ecx,edx
  480.                and edx,0FFFFh
  481.                shr ecx,16
  482.                mov pt.x,edx
  483.                mov pt.y,ecx
  484.                invoke ClientToScreen,hWnd,addr pt
  485.                invoke TrackPopupMenu,hPopup,TPM_LEFTALIGN or TPM_BOTTOMALIGN,
  486.                       pt.x,pt.y,NULL,hWnd,NULL
  487.             .endif
  488.         .endif
  489.         pop esi
  490.      .elseif uMsg==WM_INITMENUPOPUP
  491.         mov eax,lParam
  492.         .if ax==0     ; file menu
  493.             .if FileOpened==TRUE   ; a file is already opened
  494.                invoke EnableMenuItem,wParam,IDM_OPEN,MF_GRAYED
  495.                invoke EnableMenuItem,wParam,IDM_CLOSE,MF_ENABLED
  496.                invoke EnableMenuItem,wParam,IDM_SAVE,MF_ENABLED
  497.                invoke EnableMenuItem,wParam,IDM_SAVEAS,MF_ENABLED
  498.             .else
  499.                invoke EnableMenuItem,wParam,IDM_OPEN,MF_ENABLED
  500.                invoke EnableMenuItem,wParam,IDM_CLOSE,MF_GRAYED
  501.                invoke EnableMenuItem,wParam,IDM_SAVE,MF_GRAYED
  502.                invoke EnableMenuItem,wParam,IDM_SAVEAS,MF_GRAYED
  503.             .endif
  504.         .elseif ax==1 ; edit menu
  505.             invoke PrepareEditMenu,wParam
  506.         .elseif ax==2    ; search menu bar
  507.             .if FileOpened==TRUE
  508.                invoke EnableMenuItem,wParam,IDM_FIND,MF_ENABLED
  509.                invoke EnableMenuItem,wParam,IDM_FINDNEXT,MF_ENABLED
  510.                invoke EnableMenuItem,wParam,IDM_FINDPREV,MF_ENABLED
  511.                invoke EnableMenuItem,wParam,IDM_REPLACE,MF_ENABLED
  512.                invoke EnableMenuItem,wParam,IDM_GOTOLINE,MF_ENABLED
  513.             .else
  514.                invoke EnableMenuItem,wParam,IDM_FIND,MF_GRAYED
  515.                invoke EnableMenuItem,wParam,IDM_FINDNEXT,MF_GRAYED
  516.                invoke EnableMenuItem,wParam,IDM_FINDPREV,MF_GRAYED
  517.                invoke EnableMenuItem,wParam,IDM_REPLACE,MF_GRAYED
  518.                invoke EnableMenuItem,wParam,IDM_GOTOLINE,MF_GRAYED
  519.             .endif
  520.         .endif
  521.      .elseif uMsg==WM_COMMAND
  522.         .if lParam==0    ; menu commands
  523.             mov eax,wParam
  524.             .if ax==IDM_OPEN
  525.                invoke RtlZeroMemory,addr ofn,sizeof ofn
  526.                mov ofn.lStructSize,sizeof ofn
  527.                push hWnd
  528.                pop ofn.hwndOwner
  529.                push hInstance
  530.                pop ofn.hInstance
  531.                mov ofn.lpstrFilter,offset ASMFilterString
  532.                mov ofn.lpstrFile,offset FileName
  533.                mov byte ptr [FileName],0
  534.                mov ofn.nMaxFile,sizeof FileName
  535.                mov ofn.Flags,OFN_FILEMUSTEXIST or OFN_HIDEREADONLY
  536.                              or OFN_PATHMUSTEXIST
  537.                invoke GetOpenFileName,addr ofn
  538.                .if eax!=0
  539.                    invoke CreateFile,addr FileName,GENERIC_READ,
  540.                    FILE_SHARE_READ,NULL,OPEN_EXISTING, \
  541.                    FILE_ATTRIBUTE_NORMAL,0
  542.                   .if eax!=INVALID_HANDLE_VALUE
  543.                       mov hFile,eax
  544.                       ;==========================================
  545.                       ; записываем текст в контрол richedit
  546.                       ;==========================================
  547.                       mov editstream.dwCookie,eax
  548.                       mov editstream.pfnCallback,offset StreamInProc
  549.                       invoke SendMessage,hwndRichEdit,EM_STREAMIN,
  550.                              SF_TEXT,addr editstream
  551.                       ;==========================================
  552.                       ; Устанавливаем флаг модификации в false
  553.                       ;==========================================
  554.                       invoke SendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0
  555.                       invoke CloseHandle,hFile
  556.                       mov FileOpened,TRUE
  557.                   .else
  558.                       invoke MessageBox,hWnd,addr OpenFileFail,
  559.                              addr AppName,MB_OK or MB_ICONERROR
  560.                   .endif
  561.                .endif
  562.             .elseif ax==IDM_CLOSE
  563.                invoke CheckModifyState,hWnd
  564.                .if eax==TRUE
  565.                   invoke SetWindowText,hwndRichEdit,0
  566.                   mov FileOpened,FALSE
  567.                .endif
  568.             .elseif ax==IDM_SAVE
  569.                invoke CreateFile,addr FileName,GENERIC_WRITE,
  570.                       FILE_SHARE_READ,NULL,CREATE_ALWAYS, \
  571.                FILE_ATTRIBUTE_NORMAL,0
  572.                .if eax!=INVALID_HANDLE_VALUE
  573.   @@:
  574.                   mov hFile,eax
  575.                   ;=======================================================
  576.                   ; записываем текст в файл
  577.                   ;=======================================================
  578.                   mov editstream.dwCookie,eax
  579.                   mov editstream.pfnCallback,offset StreamOutProc
  580.                   invoke SendMessage,hwndRichEdit,EM_STREAMOUT,SF_TEXT,
  581.                          addr editstream
  582.                   ;==========================================================
  583.                   ; Initialize the modify state to false
  584.                   ; Устанавливаем флаг модификации в false                  
  585.                   ;==========================================================
  586.                   invoke SendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0
  587.                   invoke CloseHandle,hFile
  588.                .else
  589.                   invoke MessageBox,hWnd,addr OpenFileFail,
  590.                   addr AppName,MB_OK or MB_ICONERROR
  591.                .endif
  592.             .elseif ax==IDM_COPY
  593.                invoke SendMessage,hwndRichEdit,WM_COPY,0,0
  594.             .elseif ax==IDM_CUT
  595.                invoke SendMessage,hwndRichEdit,WM_CUT,0,0
  596.             .elseif ax==IDM_PASTE
  597.                invoke SendMessage,hwndRichEdit,WM_PASTE,0,0
  598.             .elseif ax==IDM_DELETE
  599.                invoke SendMessage,hwndRichEdit,EM_REPLACESEL,TRUE,0
  600.             .elseif ax==IDM_SELECTALL
  601.                mov chrg.cpMin,0
  602.                mov chrg.cpMax,-1
  603.                invoke SendMessage,hwndRichEdit,EM_EXSETSEL,0,addr chrg
  604.             .elseif ax==IDM_UNDO
  605.                invoke SendMessage,hwndRichEdit,EM_UNDO,0,0
  606.             .elseif ax==IDM_REDO
  607.                invoke SendMessage,hwndRichEdit,EM_REDO,0,0
  608.             .elseif ax==IDM_OPTION
  609.                invoke DialogBoxParam,hInstance,IDD_OPTIONDLG,
  610.                       hWnd,addr OptionProc,0
  611.             .elseif ax==IDM_SAVEAS
  612.                invoke RtlZeroMemory,addr ofn,sizeof ofn
  613.                mov ofn.lStructSize,sizeof ofn
  614.                push hWnd
  615.                pop ofn.hwndOwner
  616.                push hInstance
  617.                pop ofn.hInstance
  618.                mov ofn.lpstrFilter,offset ASMFilterString
  619.                mov ofn.lpstrFile,offset AlternateFileName
  620.                mov byte ptr [AlternateFileName],0
  621.                mov ofn.nMaxFile,sizeof AlternateFileName
  622.                mov ofn.Flags,OFN_FILEMUSTEXIST or OFN_HIDEREADONLY
  623.                    or OFN_PATHMUSTEXIST
  624.                invoke GetSaveFileName,addr ofn
  625.                .if eax!=0
  626.                   invoke CreateFile,addr AlternateFileName,
  627.                   GENERIC_WRITE,FILE_SHARE_READ, \
  628.                   NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
  629.                   .if eax!=INVALID_HANDLE_VALUE
  630.                       jmp @B
  631.                   .endif
  632.                .endif
  633.             .elseif ax==IDM_FIND
  634.                .if hSearch==0
  635.                   invoke CreateDialogParam,hInstance,IDD_FINDDLG,
  636.                          hWnd,addr SearchProc,0
  637.                .endif
  638.             .elseif ax==IDM_REPLACE
  639.                .if hSearch==0
  640.                   invoke CreateDialogParam,hInstance,IDD_REPLACEDLG,
  641.                          hWnd,addr ReplaceProc,0
  642.                .endif
  643.             .elseif ax==IDM_GOTOLINE
  644.                .if hSearch==0
  645.                   invoke CreateDialogParam,hInstance,IDD_GOTODLG,
  646.                          hWnd,addr GoToProc,0
  647.                .endif
  648.             .elseif ax==IDM_FINDNEXT
  649.                invoke lstrlen,addr FindBuffer
  650.                .if eax!=0
  651.                   invoke SendMessage,hwndRichEdit,EM_EXGETSEL,
  652.                          0,addr findtext.chrg
  653.                   mov eax,findtext.chrg.cpMin
  654.                   .if eax!=findtext.chrg.cpMax
  655.                       push findtext.chrg.cpMax
  656.                       pop findtext.chrg.cpMin
  657.                   .endif
  658.                   mov findtext.chrg.cpMax,-1
  659.                   mov findtext.lpstrText,offset FindBuffer
  660.                   invoke SendMessage,hwndRichEdit,EM_FINDTEXTEX,
  661.                          FR_DOWN,addr findtext
  662.                   .if eax!=-1
  663.                       invoke SendMessage,hwndRichEdit,EM_EXSETSEL,
  664.                              0,addr findtext.chrgText
  665.                   .endif
  666.                .endif
  667.             .elseif ax==IDM_FINDPREV
  668.                invoke lstrlen,addr FindBuffer
  669.                .if eax!=0
  670.                   invoke SendMessage,hwndRichEdit,EM_EXGETSEL,0,
  671.                   addr findtext.chrg
  672.                   mov findtext.chrg.cpMax,0
  673.                   mov findtext.lpstrText,offset FindBuffer
  674.                   invoke SendMessage,hwndRichEdit,EM_FINDTEXTEX,
  675.                          0,addr findtext
  676.                   .if eax!=-1
  677.                       invoke SendMessage,hwndRichEdit,
  678.                       EM_EXSETSEL,0,addr findtext.chrgText
  679.                   .endif
  680.                .endif
  681.             .elseif ax==IDM_EXIT
  682.                invoke SendMessage,hWnd,WM_CLOSE,0,0
  683.             .endif
  684.         .endif
  685.      .elseif uMsg==WM_CLOSE
  686.         invoke CheckModifyState,hWnd
  687.         .if eax==TRUE
  688.             invoke DestroyWindow,hWnd
  689.         .endif
  690.      .elseif uMsg==WM_SIZE
  691.         mov eax,lParam
  692.         mov edx,eax
  693.         and eax,0FFFFh
  694.         shr edx,16
  695.         invoke MoveWindow,hwndRichEdit,0,0,eax,edx,TRUE
  696.      .elseif uMsg==WM_DESTROY
  697.         invoke PostQuitMessage,NULL
  698.      .else
  699.         invoke DefWindowProc,hWnd,uMsg,wParam,lParam
  700.         ret
  701.      .endif
  702.      xor eax,eax
  703.      ret
  704.   WndProc endp
  705.   end start
  706.  

АНАЛИЗ

  Поиск текста реализуется с помощью EM_FINDTEXTEX. Когда пользователь кликает на пункте меню 'Find', отсылается сообщение IDM_FIND и отображается соответствующее диалоговое окно.

Код (Text):
  1.  
  2. invoke GetDlgItemText,hWnd,IDC_FINDEDIT,addr FindBuffer,sizeof FindBuffer
  3. .if eax!=0
  4.  

  Когда пользователь задает текст, который нужно найти, а затем нажимает кнопку 'OK', текст, который мы собираемся искать, оказывается в FindBuffer.

Код (Text):
  1.  
  2. mov uFlags,0
  3. invoke SendMessage,hwndRichEdit,EM_EXGETSEL,0,addr findtext.chrg
  4.  

  Если текстовая строка не равняется NULL, мы устанавливаем значение переменной uFlags равной 0. Эта переменная используется для хранения флагов поиска, отсылаемых вместе с сообщением EM_FINDTEXTEX. После этого мы получаем текущий выделенный текст с помощью EM_EXGETSEL, потому что нам нужно знать, откуда будет производиться поиск.

Код (Text):
  1.  
  2.   invoke IsDlgButtonChecked,hWnd,IDC_DOWN
  3.         .if eax==BST_CHECKED
  4.             or uFlags,FR_DOWN
  5.             mov eax,findtext.chrg.cpMin
  6.             .if eax!=findtext.chrg.cpMax
  7.                push findtext.chrg.cpMax
  8.                pop findtext.chrg.cpMin
  9.             .endif
  10.             mov findtext.chrg.cpMax,-1
  11.         .else
  12.             mov findtext.chrg.cpMax,0
  13.         .endif
  14.  

  Следующая часть несколько сложнее. Мы проверяем значение кнопки, задающей направление поиска. Если указан поиск вперед, мы задаем флаг FR_DOWN в uFlags. После этого мы проверяем, выделен ли сейчас какой-нибудь текст, проверяя значения cpMin и cpMax. Если оба значения не равны, это означает, что выделение существует, и мы должны продолжать поиск от конца текущего выделения до конца текста в контроле. Поэтому нам требуется заменить значение cpMax на значение cpMin, а cpMax приравнять к -1 (0FFFFFFFFh). если выделения нет, поиск будет производиться от текущей позиции курсора до конца текста.

  Если пользователь выберет поиск назад, мы используем диапазон от начала выделения до начала текста в контроле. Поэтому на нужно только изменить значение cpMax на 0. В случае с поиском назад cpMin содержит индекс последнего символа в диапазоне поиска, а cpMax - индекс первого символа. Это инверсия поиска вперед.

Код (Text):
  1.  
  2. invoke IsDlgButtonChecked,hWnd,IDC_MATCHCASE
  3. .if eax==BST_CHECKED
  4. or uFlags,FR_MATCHCASE
  5. .endif
  6. invoke IsDlgButtonChecked,hWnd,IDC_WHOLEWORD
  7. .if eax==BST_CHECKED
  8. or uFlags,FR_WHOLEWORD
  9. .endif
  10. mov findtext.lpstrText,offset FindBuffer
  11.  

  Мы продолжаем проверку checkbox'ов, чтобы задать значения FR_MATCHCASE и FR_WHOLEWORD. Наконец, мы помещаем смещение текста, который нужно найти в поле lpstrText.

Код (Text):
  1.  
  2. invoke SendMessage,hwndRichEdit,EM_FINDTEXTEX,uFlags,addr findtext
  3. .if eax!=-1
  4.   invoke SendMessage,hwndRichEdit,EM_EXSETSEL,0,addr findtext.chrgText
  5. .endif
  6.  

  Мы сейчас готовы послать сообщение EM_FINDTEXTEX. После этого мы проверяем результаты поиска, возвращенные SendMessage. Если возвращаемое значение равно -1, значит никаких совпадений не было найдено. В противном случае поле chrgText структуры FINDTEXTEX заполняется индексами совпавшего текста. Мы выделяем найденный текст с помощью EM_EXSETSEL.

  Операция замещения делается подобным же образом.

Код (Text):
  1.  
  2.      invoke GetDlgItemText,hWnd,IDC_FINDEDIT,
  3.             addr FindBuffer,sizeof FindBuffer
  4.      invoke GetDlgItemText,hWnd,IDC_REPLACEEDIT,
  5.             addr ReplaceBuffer,sizeof ReplaceBuffer
  6.  

  Мы получаем текст, который нужно найти, и текст, который нужно заменить.

Код (Text):
  1.  
  2.      mov findtext.chrg.cpMin,0
  3.      mov findtext.chrg.cpMax,-1
  4.      mov findtext.lpstrText,offset FindBuffer
  5.  

  Чтобы сделать проще, операция замещения действует на весь текст в контроле. Поэтому начальный индекс равен 0, а конечный - -1.

Код (Text):
  1.  
  2.      mov settext.flags,ST_SELECTION
  3.      mov settext.codepage,CP_ACP
  4.  

  Мы инициализируем структуру SETTEXTEX, чтобы задать то, что мы хотим заменить текущее выделение и использовать системную страницу кодировки по умолчанию.

Код (Text):
  1.  
  2.      .while TRUE
  3.         invoke SendMessage,hwndRichEdit,EM_FINDTEXTEX,
  4.                FR_DOWN,addr findtext
  5.         .if eax==-1
  6.             .break
  7.         .else
  8.             invoke SendMessage,hwndRichEdit,EM_EXSETSEL,
  9.                    0,addr findtext.chrgText
  10.             invoke SendMessage,hwndRichEdit,EM_SETTEXTEX,
  11.                    addr settext,addr ReplaceBuffer
  12.         .endif
  13.      .endw
  14.  

  Мы входим в бесконечный цикл и ищем совпадающий текст. Если он был найден, мы выбираем его с помощью EM_EXSETSEL и заменяем его EM_SETTEXTEX. Если больше совпадений не было найдено, мы выходим из цикла.

  'Find Next' и 'Find Prev.' используют сообщение EM_FINDTEXTEX похожим образом.

  Теперь мы рассмотрим 'Go to Line'. Когда пользователь кликает по этому пункту меню, мы отображаем диалоговое окно.

  Когда пользователь набирает номер линии и нажимет кнопку 'Ok', мы начинаем операцию.

Код (Text):
  1.  
  2.      invoke GetDlgItemInt,hWnd,IDC_LINENO,NULL,FALSE
  3.      mov LineNo,eax
  4.  

  Получаем номер линии из edit control'а.

Код (Text):
  1.  
  2.      invoke SendMessage,hwndRichEdit,EM_GETLINECOUNT,0,0
  3.      .if eax>LineNo
  4.  

  Получаем количество линий в контроле. Проверяем, не указал ли пользователь номер линии, который выходит за рамки допустимых значений.

Код (Text):
  1.  
  2. invoke SendMessage,hwndRichEdit,EM_LINEINDEX,LineNo,0
  3.  

  Если номер линии верен, мы передвигает курсор к первому символу в этой строке. Поэтому мы посылаем сообщение EM_LINEINDEX контролу richedit. Это сообщение возвращает индекс первого символа в заданной строке. Мы посылаем номер строки через wParam, а получаем индекс символа.

Код (Text):
  1.  
  2. invoke SendMessage,hwndRichEdit,EM_SETSEL,eax,eax
  3.  

  Чтобы установить текущее выделение, в этот раз мы используем EM_SETSEL, потому что индексы символов уже не находятся в структуре CHARRANGE, что сохраняет нам две инструкции (помещение этих индексов в структуру CHARRANGE).

Код (Text):
  1.  
  2.         invoke SetFocus,hwndRichEdit
  3.      .endif
  4.  

  Курсор не будет отображен, пока контрол RichEdit не получит фокус. Поэтому мы вызываем SetFocus. © Iczelion, пер. Aquila


0 2.124
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532