![]() |
Wyjście Spis treści Poprzedni Następny
Autor:
©Iczelion |
©2008 mgr Jerzy Wałaszek I LO w Tarnowie
|
Na tej lekcji dowiesz się więcej o operacjach tekstowych wykonywanych w kontrolce RichEdit. Zajmiemy się szczególnie wyszukiwaniem i zamianą tekstu oraz przechodzeniem do wybranego numeru wiersza.

Załaduj {ten przykład}
Istnieje kilka operacji tekstowych, które może wykonywać kontrolka RichEdit. Wyszukiwanie tekstu jest jedną z nich. Wykonuje się je wysyłając wiadomości EM_FINDTEXT lub EM_FINDTEXTEX. Te wiadomości nieco się różnią między sobą.
| Wiadomość EM_FINDTEXT | |
|---|---|
| wParam | Opcje poszukiwań. Może to być dowolna kombinacja
poniższych znaczników, które są identyczne zarówno dla
EM_FINDTEXT jak i dla
EM_FINDTEXTEX:
Istnieje jeszcze kilka innych znaczników, lecz mają one znaczenie jedynie dla języków innych niż angielski. |
| lParam | Wskazuje strukturę FINDTEXT
FINDTEXT STRUCT chrg CHARRANGE <> lpstrText DWORD ?FINDTEXT ENDS
CHARRANGE STRUCT cpMin DWORD ? cpMax DWORD ?CHARRANGE ENDS
|
| Wiadomość EM_FINDTEXT zwraca indeks pozycji pierwszego znaku poszukiwanego tekstu w kontrolce RichEdit. Jeśli tekst nie został odnaleziony, zwracana jest wartość -1. | |
| Wiadomość EM_FINDTEXTEX | |
|---|---|
| wParam | Opcje poszukiwań takie same jak w EM_FINDTEXT. |
| lParam | Wskazuje strukturę FINDTEXTEX
FINDTEXTEX STRUCT
chrg CHARRANGE <>
lpstrText DWORD ?
chrgText CHARRANGE <>
FINDTEXTEX ENDS
Pierwsze dwa pola struktury FINDTEXTEX są identyczne z FINDTEXT. Pole chrgText jest strukturą CHARRANGE, która zostanie wypełniona początkowym i końcowym indeksem, jeśli zostanie znaleziony w kontrolce poszukiwany łańcuch znaków. |
| Wartość zwrotna EM_FINDTEXTEX jest identyczna z wartością zwrotną EM_FINDTEXT. | |
Różnica pomiędzy wiadomościami EM_FINDTEXT a EM_FINDTEXTEX jest taka, iż struktura FINDTEXTEX posiada dodatkowe pole. chrgText, które zostanie wypełnione w razie odszukania tekstu jego początkowym i końcowym indeksem w kontrolce RichEdit. Jest to wygodne, gdy chcemy przeprowadzić na tym łańcuchu tekstu więcej operacji tekstowych.
Kontrolka RichEdit udostępnia wiadomość EM_SETTEXTEX do zamiany lub wstawiania tekstu. Wiadomość ta łączy w sobie operacje wykonywane przez wiadomości WM_SETTEXT i EM_REPLACESEL. Posiada ona następującą składnię:
| Wiadomość EM_SETTEXTEX | |
|---|---|
| wParam | Wskazanie struktury SETTEXTEX
SETTEXTEX STRUCT
flags DWORD ?
codepage DWORD ?
SETTEXTEX ENDS
|
| lParam | Wskazuje tekst zakończony zerem, który ma zostać wstawiony. Tekst jest łańcuchem ANSI o ile strona kodowa nie ma numeru 1200 (Unicode). W takim przypadku jest to łańcuch Unicode. |
| Jeśli operacja ustawia cały tekst i się powiodła, zwracana jest wartość 1.Jeśli operacja ustawia zaznaczenie i się powiodła, wartość zwrotna jest liczbą skopiowanych znaków.Jeśli operacja się nie powiedzie, zwracana jest wartość 0 | |
Można programowo zaznaczać tekst za pomocą wiadomości EM_SETSEL lub EM_EXSETSEL. Każda z nich nadaje się doskonale do tego celu. Wybór zależy od dostępnego formatu indeksów znakowych. Jeśli są one już umieszczone w strukturze CHARRANGE, to łatwiej będzie zastosować wiadomość EM_EXSETSEL.
| Wiadomość EM_EXSETSEL | |
|---|---|
| wParam | Nie używane. Musi mieć wartość 0. |
| lParam | Wskazanie struktury CHARRANGE, która zawiera zakres znaków do zaznaczenia. |
W przypadku wielowierszowej kontrolki edycyjnej należy przejąć jej procedurę okna, aby odbierać wiadomości o zdarzeniach myszki czy klawiatury. Kontrolka RichEdit posiada lepszą konstrukcję, która umożliwia jej powiadamianie okna nadrzędnego o takich zdarzeniach. Aby zarejestrować się do pobierania powiadomień, okno nadrzędne wysyła do kontrolki RichEdit wiadomość EM_SETEVENTMASK, która określa interesujące je zdarzenia. Wiadomość ta ma następującą składnię:
| Wiadomość EM_SETEVENTMASK | |
|---|---|
| wParam | Nie używane. Musi mieć wartość 0. |
| lParam | Wartość maski dla filtrowania zdarzeń. Może być
dowolną kombinacją wymienionych poniżej znaczników:
|
Wszystkie powyższe powiadomienia zostaną wysłane jako wiadomość WM_NOTIFY: należy sprawdzić pole code struktury NMHDR w celu pobrania wiadomości powiadomienia. Na przykład, jeśli chcesz rejestrować zdarzenia myszki (np. chcesz udostępnić wyskakujące menu kontekstowe), musisz wykonać coś w tym rodzaju:
INVOKE SendMessage, 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
...
[ tutaj sobie coś robisz ]
...
.ENDIF
ASSUME esi: NOTHING
pop esi
...
Poniższy przykład programu jest uaktualnieniem edytora IczEdit z lekcji XXXIII. Dodaje on operacje wyszukiwania i zastępowania tekstu oraz klawisze skrótów. Przetwarza również zdarzenia myszki i udostępnia wyskakujące menu kontekstowe po kliknięciu prawym przyciskiem myszki w obrębie kontrolki RichEdit.
Plik ICZEDIT.ASM
.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\kernel32.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
IDD_OPTIONDLG EQU 101
IDD_FINDDLG EQU 102
IDD_GOTODLG EQU 103
IDD_REPLACEDLG EQU 104
IDR_MAINACCEL EQU 105
RichEditID EQU 300
IDC_BACKCOLORBOX EQU 1000
IDC_TEXTCOLORBOX EQU 1001
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 1005
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
IDM_FIND EQU 40014
IDM_FINDNEXT EQU 40015
IDM_REPLACE EQU 40016
IDM_GOTOLINE EQU 40017
IDM_FINDPREV EQU 40018
.DATA
ClassName DB "IczEditClass", 0
AppName DB "IczEdit Wersja 2.1", 0
RichEditDLL DB "riched20.dll", 0
RichEditClass DB "RichEdit20A", 0
NoRichEdit DB "Nie można odnaleźć biblioteki riched20.dll", 0
ASMFilterString DB "Kod źródłowy ASM (*.asm)", 0, "*.asm", 0,
"Wszystkie pliki (*.*)", 0, "*.*", 0, 0
OpenFileFail DB "Nie można otworzyć pliku", 0
WannaSave DB "Dane w edytorze zostały zmodyfikowane. Zapisać je?", 0
FileOpened DD FALSE
BackgroundColor DD 0FFFFFFh ; standardowy kolor tła - biały
TextColor DD 0 ; standardowy kolor tekstu - czarny
hSearch DD ? ; uchwyt okna dialogowego wyszukiwania/zamiany
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
.ELSE
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_VREDRAW
mov 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 LoadAccelerators, 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,
pBytesWritten: 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 RtlZeroMemory, 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 ax, WORD PTR wParam + 2
.IF ax==BN_CLICKED
mov eax, wParam
.IF ax==IDCANCEL
INVOKE SendMessage, hWnd, WM_CLOSE, 0, 0
.ELSEIF ax==IDC_BACKCOLORBOX
INVOKE RtlZeroMemory, 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 InvalidateRect, eax, 0, TRUE
.ENDIF
.ELSEIF ax==IDC_TEXTCOLORBOX
INVOKE RtlZeroMemory, 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 InvalidateRect, eax, 0, TRUE
.ENDIF
.ELSEIF ax==IDOK
; Zachowujemy znacznik modyfikacji kontrolki RichEdit, ponieważ
; zmiana tekstu powoduje również zmianę tego znacznika
INVOKE SendMessage, hwndRichEdit, EM_GETMODIFY, 0, 0
push eax
INVOKE SetColor
pop eax
INVOKE SendMessage, hwndRichEdit, EM_SETMODIFY, eax, 0
INVOKE EndDialog, hWnd, 0
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_CTLCOLORSTATIC
INVOKE GetDlgItem, hWnd, IDC_BACKCOLORBOX
.IF eax==lParam
INVOKE CreateSolidBrush, BackgroundColor
ret
.ELSE
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
.ELSE
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
; Wybierama standardowo opcję szukania w dół
INVOKE CheckRadioButton, hWnd, IDC_DOWN, IDC_UP, IDC_DOWN
INVOKE SendDlgItemMessage, hWnd, IDC_FINDEDIT, WM_SETTEXT,
0, ADDR FindBuffer
.ELSEIF uMsg==WM_COMMAND
mov ax, WORD PTR wParam + 2
.IF ax==BN_CLICKED
mov eax, wParam
.IF ax==IDOK
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
.ELSE
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
.ELSE
mov eax, FALSE
ret
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_CLOSE
mov hSearch, 0
INVOKE EndDialog, hWnd, 0
.ELSE
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 ax, WORD PTR wParam + 1
.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 findtext
.BREAK .IF eax==-1
INVOKE SendMessage, hwndRichEdit, EM_EXSETSEL,
0, ADDR findtext.chrgText
INVOKE SendMessage, hwndRichEdit, EM_SETTEXTEX,
ADDR settext, ADDR ReplaceBuffer
.ENDW
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_CLOSE
mov hSearch, 0
INVOKE EndDialog, hWnd, 0
.ELSE
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_COMMAND
mov ax, WORD PTR wParam + 2
.IF ax==BN_CLICKED
.IF WORD PTR wParam==IDCANCEL
INVOKE SendMessage, hWnd, WM_CLOSE, 0, 0
.ELSEIF WORD PTR wParam==IDOK
INVOKE GetDlgItemInt, hWnd, IDC_LINENO, NULL, FALSE
mov LineNo, eax
INVOKE SendMessage, hwndRichEdit, EM_GETLINECOUNT, 0, 0
.IF eax>LineNo
INVOKE SendMessage, hwndRichEdit, EM_LINEINDEX, LineNo, 0
INVOKE SendMessage, hwndRichEdit, EM_SETSEL, eax, eax
INVOKE SetFocus, hwndRichEdit
.ENDIF
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_CLOSE
xor eax, eax
mov hSearch, eax
INVOKE EndDialog, hWnd, eax
.ELSE
mov eax, FALSE
ret
.ENDIF
mov eax, TRUE
ret
GoToProc ENDP
PrepareEditMenu PROC hSubMenu:DWORD
LOCAL chrg: CHARRANGE
; Sprawdzamy, czy w schowku znajduje się jakiś tekst.
; Jeśli tak, to włączamy element menu Wklej
INVOKE SendMessage, hwndRichEdit, EM_CANPASTE, CF_TEXT, 0
.IF eax==0 ; w schowku nie ma tekstu
INVOKE EnableMenuItem, hSubMenu, IDM_PASTE, MF_GRAYED
.ELSE
INVOKE EnableMenuItem, hSubMenu, IDM_PASTE, MF_ENABLED
.ENDIF
; Sprawdzamy, czy kolejka cofnięć jest pusta
INVOKE SendMessage, hwndRichEdit, EM_CANUNDO, 0, 0
.IF eax==0
INVOKE EnableMenuItem, hSubMenu, IDM_UNDO, MF_GRAYED
.ELSE
INVOKE EnableMenuItem, hSubMenu, IDM_UNDO, MF_ENABLED
.ENDIF
; Sprawdzamy, czy kolejka powtórzeń jest pusta
INVOKE SendMessage, hwndRichEdit, EM_CANREDO, 0, 0
.IF eax==0
INVOKE EnableMenuItem, hSubMenu, IDM_REDO, MF_GRAYED
.ELSE
INVOKE EnableMenuItem, hSubMenu, IDM_REDO, MF_ENABLED
.ENDIF
; Sprawdzamy, czy w kontrolce zaznaczono jakiś tekst.
; Jeśli tak, to uaktywniamy opcje Wytnij/Kopiuj/Usuń
INVOKE SendMessage, hwndRichEdit, EM_EXGETSEL, 0, ADDR chrg
mov eax, chrg.cpMin
.IF eax==chrg.cpMax ; brak zaznaczenia tekstu
INVOKE EnableMenuItem, hSubMenu, IDM_COPY, MF_GRAYED
INVOKE EnableMenuItem, hSubMenu, IDM_CUT, MF_GRAYED
INVOKE EnableMenuItem, hSubMenu, IDM_DELETE, MF_GRAYED
.ELSE
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_SETLANGOPTIONS, 0, 0
; Ustawiamy limit tekstu - standardowo jest 64KB.
INVOKE SendMessage, hwndRichEdit, EM_LIMITTEXT, -1, 0
; Ustawiamy standardowy kolor tła i tekstu
INVOKE SetColor
INVOKE SendMessage, hwndRichEdit, EM_SETMODIFY, FALSE, 0
; Ustawiamy maskę zdarzeń
INVOKE SendMessage, hwndRichEdit, EM_SETEVENTMASK, 0,
ENM_MOUSEEVENTS
INVOKE SendMessage, hwndRichEdit, EM_EMPTYUNDOBUFFER, 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
xor ecx, ecx
mov cx, WORD PTR [esi].lParam
mov pt.x, ecx
mov cx, WORD PTR [esi].lParam + 2
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 ; menu Plik
.IF FileOpened==TRUE ; otwarto już jakiś plik
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
.ELSE
INVOKE EnableMenuItem, wParam, IDM_OPEN, MF_ENABLED
INVOKE EnableMenuItem, wParam, IDM_CLOSE, MF_GRAYED
INVOKE EnableMenuItem, wParam, IDM_SAVE, MF_GRAYED
INVOKE EnableMenuItem, wParam, IDM_SAVEAS, MF_GRAYED
.ENDIF
.ELSEIF ax==1 ; menu Edycja
INVOKE PrepareEditMenu, wParam
.ELSEIF ax==2 ; menu Znajdź
.IF FileOpened==TRUE
INVOKE EnableMenuItem, wParam, IDM_FIND, MF_ENABLED
INVOKE EnableMenuItem, wParam, IDM_FINDNEXT, MF_ENABLED
INVOKE EnableMenuItem, wParam, IDM_FINDPREV, MF_ENABLED
INVOKE EnableMenuItem, wParam, IDM_REPLACE, MF_ENABLED
INVOKE EnableMenuItem, wParam, IDM_GOTOLINE, MF_ENABLED
.ELSE
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 ; polecenia menu
mov eax, wParam
.IF ax==IDM_OPEN
INVOKE RtlZeroMemory, ADDR ofn, SIZEOF ofn
mov ofn.lStructSize, SIZEOF ofn
push hWnd
pop ofn.hwndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET ASMFilterString
mov ofn.lpstrFile, OFFSET FileName
mov BYTE PTR [FileName], 0
mov ofn.nMaxFile, SIZEOF FileName
mov ofn.Flags, OFN_FILEMUSTEXIST OR \
OFN_HIDEREADONLY 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
; Przesyłamy strumień tekstu do kontrolki RichEdit
mov editstream.dwCookie, eax
mov editstream.pfnCallback, OFFSET StreamInProc
INVOKE SendMessage, hwndRichEdit, EM_STREAMIN,
SF_TEXT, ADDR editstream
; Inicjujemy znacznik modyfikacji na FALSE
INVOKE SendMessage, hwndRichEdit, EM_SETMODIFY,
FALSE, 0
INVOKE CloseHandle, hFile
mov FileOpened, TRUE
.ELSE
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, 0
mov FileOpened, FALSE
.ENDIF
.ELSEIF ax==IDM_SAVE
INVOKE CreateFile, ADDR FileName, GENERIC_WRITE,
FILE_SHARE_READ, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0
.IF eax!=INVALID_HANDLE_VALUE
@@:
mov hFile, eax
; Przesyłamy strumień tekstu do pliku
mov editstream.dwCookie, eax
mov editstream.pfnCallback, OFFSET StreamOutProc
INVOKE SendMessage, hwndRichEdit, EM_STREAMOUT,
SF_TEXT, ADDR editstream
; Inicjujemy znacznik modyfikacji na FALSE
INVOKE SendMessage, hwndRichEdit, EM_SETMODIFY, FALSE, 0
INVOKE CloseHandle, hFile
.ELSE
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 RtlZeroMemory, ADDR ofn, SIZEOF ofn
mov ofn.lStructSize, SIZEOF ofn
push hWnd
pop ofn.hwndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET ASMFilterString
mov ofn.lpstrFile, OFFSET AlternateFileName
mov BYTE PTR [AlternateFileName], 0
mov ofn.nMaxFile, SIZEOF AlternateFileName
mov ofn.Flags, OFN_FILEMUSTEXIST OR\
OFN_HIDEREADONLY 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_FINDDLG,
hWnd, ADDR SearchProc, 0
.ENDIF
.ELSEIF ax==IDM_REPLACE
.IF hSearch==0
INVOKE CreateDialogParam, hInstance, IDD_REPLACEDLG,
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 findtext
.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
movzx eax, WORD PTR lParam
movzx edx, WORD PTR lParam + 2
INVOKE MoveWindow, hwndRichEdit, 0, 0, eax, edx, TRUE
.ELSEIF uMsg==WM_DESTROY
INVOKE PostQuitMessage, NULL
.ELSE
INVOKE DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.ENDIF
xor eax, eax
ret
WndProc ENDP
END start
Plik ICZEDIT.RC
#include "resource.h"
#define IDC_NEXT 1003
#define IDR_MAINMENU 101
#define IDD_OPTIONDLG 101
#define IDD_FINDDLG 102
#define IDD_GOTODLG 103
#define IDD_REPLACEDLG 104
#define IDR_MAINACCEL 105
#define IDC_BACKCOLORBOX 1000
#define IDC_FINDEDIT 1000
#define IDC_TEXTCOLORBOX 1001
#define IDC_MATCHCASE 1001
#define IDC_REPLACEEDIT 1001
#define IDC_WHOLEWORD 1002
#define IDC_DOWN 1003
#define IDC_UP 1004
#define IDC_LINENO 1005
#define IDM_OPEN 40001
#define IDM_SAVE 40002
#define IDM_CLOSE 40003
#define IDM_SAVEAS 40004
#define IDM_EXIT 40005
#define IDM_COPY 40006
#define IDM_CUT 40007
#define IDM_PASTE 40008
#define IDM_DELETE 40009
#define IDM_SELECTALL 40010
#define IDM_OPTION 40011
#define IDM_UNDO 40012
#define IDM_REDO 40013
#define IDM_FIND 40014
#define IDM_FINDNEXT 40015
#define IDM_REPLACE 40016
#define IDM_GOTOLINE 40017
#define IDM_FINDPREV 40018
IDR_MAINMENU MENU DISCARDABLE
{
POPUP "&Plik"
{
MENUITEM "&Otwórz", IDM_OPEN
MENUITEM "Za&mknij", IDM_CLOSE
MENUITEM "&Zapisz", DM_SAVE
MENUITEM "Z&apisz Jako", IDM_SAVEAS
MENUITEM SEPARATOR
MENUITEM "Za&kończ", IDM_EXIT
}
POPUP "&Edycja"
{
MENUITEM "&Cofnij",IDM_UNDO
MENUITEM "&Ponów", IDM_REDO
MENUITEM "&Kopiuj", IDM_COPY
MENUITEM "Wyt&nij", IDM_CUT
MENUITEM "Wkl&ej", IDM_PASTE
MENUITEM SEPARATOR
MENUITEM "&Usuń", IDM_DELETE
MENUITEM SEPARATOR
MENUITEM "Z&aznacz Wszystko", IDM_SELECTALL
}
POPUP "&Znajdź"
{
MENUITEM "&Znajdź...\tCtrl+F", IDM_FIND
MENUITEM "Znajdź &Następny\tF3", IDM_FINDNEXT
MENUITEM "Znajdź &Poprzedni\tCtrl+F3", IDM_FINDPREV
MENUITEM "Za&mień..\tCtrl+R", IDM_REPLACE
MENUITEM SEPARATOR
MENUITEM "&Idź do wiersza\tCtrl+G", IDM_GOTOLINE
}
MENUITEM "&Opcje", IDM_OPTION
}
IDD_OPTIONDLG DIALOG DISCARDABLE 0, 0, 183, 54
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU
CAPTION "Opcje"
FONT 8, "MS Sans Serif"
{
DEFPUSHBUTTON "OK", IDOK, 137, 7, 39, 14
PUSHBUTTON "Anuluj", IDCANCEL, 137, 25, 39, 14
GROUPBOX "", IDC_STATIC, 5, 0, 124, 49
LTEXT "Kolor Tła:", IDC_STATIC, 20, 14, 60, 8
LTEXT "", IDC_BACKCOLORBOX, 85, 11, 28, 14, SS_NOTIFY | WS_BORDER
LTEXT "Kolor Tekstu:", IDC_STATIC, 20, 33, 60, 8
LTEXT "", IDC_TEXTCOLORBOX, 85, 29, 28, 14, SS_NOTIFY | WS_BORDER
}
IDD_FINDDLG DIALOG DISCARDABLE 0, 0, 216, 53
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Znajdź..."
FONT 8, "MS Sans Serif"
{
EDITTEXT IDC_FINDEDIT, 34, 3, 132, 13, ES_AUTOHSCROLL
CONTROL "Uwzględnij wielkość liter", IDC_MATCHCASE, "Button",
BS_AUTOCHECKBOX | WS_TABSTOP, 6, 24, 90, 11
CONTROL "Znajdź tylko całe wyrazy", IDC_WHOLEWORD, "Button",
BS_AUTOCHECKBOX | WS_TABSTOP, 6, 36, 90, 11
CONTROL "W dół", IDC_DOWN, "Button",
BS_AUTORADIOBUTTON | WS_TABSTOP, 108, 25, 36, 11
CONTROL "W górę", IDC_UP, "Button",
BS_AUTORADIOBUTTON | WS_TABSTOP, 108, 36, 42, 11
DEFPUSHBUTTON "OK", IDOK, 172, 3, 40, 13
PUSHBUTTON "Anuluj", IDCANCEL, 172, 18, 40, 13
LTEXT "Znajdź:", IDC_STATIC, 2, 5, 26, 9
GROUPBOX "Kierunek", IDC_STATIC, 100, 18, 64, 33
}
IDD_GOTODLG DIALOGEX 0, 0, 106, 30
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Idź do wiersza"
FONT 8, "MS Sans Serif", 0, 0, 0x1
{
EDITTEXT IDC_LINENO, 28, 3, 36, 11, ES_AUTOHSCROLL | ES_NUMBER, WS_EX_CLIENTEDGE
DEFPUSHBUTTON "OK", IDOK, 70, 3, 32, 11
PUSHBUTTON "Anuluj", IDCANCEL, 70, 16, 32, 11
LTEXT "Wiersz :", IDC_STATIC, 2, 5, 26, 9
}
IDD_REPLACEDLG DIALOG DISCARDABLE 0, 0, 186, 33
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Zamień"
FONT 8, "MS Sans Serif"
{
EDITTEXT IDC_FINDEDIT, 51, 3, 84, 12, ES_AUTOHSCROLL
EDITTEXT IDC_REPLACEEDIT, 51, 17, 84, 11, ES_AUTOHSCROLL
DEFPUSHBUTTON "OK", IDOK, 142, 3, 39, 11
PUSHBUTTON "Anuluj", IDCANCEL, 142, 17, 39, 11
LTEXT "Znajdź:", IDC_STATIC, 3, 4, 34, 8
LTEXT "Zamień z", IDC_STATIC, 3, 18, 42, 8
}
IDR_MAINACCEL ACCELERATORS DISCARDABLE
{
"F", IDM_FIND, VIRTKEY, CONTROL, NOINVERT
"G", IDM_GOTOLINE, VIRTKEY, CONTROL, NOINVERT
"R", IDM_REPLACE, VIRTKEY, CONTROL, NOINVERT
VK_F3, IDM_FINDNEXT, VIRTKEY, NOINVERT
VK_F3, IDM_FINDPREV, VIRTKEY, CONTROL, NOINVERT
}
Operacja wyszukiwania tekstu została zaimplementowana za pomocą wiadomości EM_FINDTEXTEX. Gdy użytkownik kliknie myszką na elemencie menu Znajdź, wysłana zostaje wiadomość IDM_FIND i pojawia się okno dialogowe wyszukiwania tekstu.

INVOKE GetDlgItemText, hWnd, IDC_FINDEDIT,
ADDR FindBuffer, SIZEOF FindBuffer
.IF eax!=0
Gdy użytkownik wpisze tekst do wyszukania i kliknie przycisk OK, odczytujemy ten tekst do bufora FindBuffer.
mov uFlags, 0
INVOKE SendMessage, hwndRichEdit, EM_EXGETSEL, 0, ADDR findtext.chrg
Jeśli tekst nie jest pusty, kontynuujemy inicjując zmienną uFlags na 0. Zmienna ta jest używana do przechowywania znaczników poszukiwań wykorzystywanych przez wiadomość EM_FINDTEXTEX. Po tej czynności pobieramy bieżące zaznaczenie za pomocą wiadomości EM_EXGETSEL, ponieważ jest nam potrzebny punkt startowy, od którego rozpoczniemy nasze poszukiwania.
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
.ELSE
mov findtext.chrg.cpMax, 0
.ENDIF
Następny fragment kodu jest troszeczkę zagmatwany. Sprawdzamy kontrolkę kierunku poszukiwań, aby upewnić się w którą stronę prowadzić poszukiwania. Jeśli zostało zaznaczone poszukiwanie w dół, w zmiennej uFlags ustawiamy znacznik FR_DOWN. Następnie sprawdzamy, czy użytkownik dokonał zaznaczenia bloku tekstu w kontrolce porównując ze sobą wartości pól cpMin i cpMax. Jeśli nie są sobie równe, to mamy potwierdzenie istnienia zaznaczenia bloku tekstu i musimy kontynuować poszukiwania od końca tego zaznaczenia do końca tekstu w kontrolce. Zatem musimy zastąpić wartość cpMin zawartością cpMax, a do cpMax wprowadzić -1 (0FFFFFFFFh). Jeśli nie został zaznaczony żaden obszar tekstu w kontrolce, to poszukujemy od bieżącej pozycji kursora do końca tekstu.
Jeśli użytkownik wybrał poszukiwanie w górę, korzystamy z zakresu od początku zaznaczenia do początku tekstu w kontrolce. Dlatego modyfikujemy jedynie wartość cpMax na 0. W przypadku poszukiwania w górę cpMin zawiera indeks ostatniego znaku w zakresie poszukiwań, a cpMax zawiera indeks pierwszego znaku tego zakresu. Jest to odwrotność poszukiwania w dół.
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
Kontynuujemy sprawdzanie wyboru opcji w okienku dialogowym ustawiając w zmiennej uFlags odpowiednie znaczniki poszukiwań, tj. FR_MATCHCASE i FR_WHOLEWORD. Na koniec w polu lpstrText umieszczamy adres tekstu do wyszukania.
INVOKE SendMessage, hwndRichEdit, EM_FINDTEXTEX,
uFlags, ADDR findtext
.IF eax!=-1
INVOKE SendMessage, hwndRichEdit, EM_EXSETSEL,
0, ADDR findtext.chrgText
.ENDIF
.ENDIF
Jesteśmy już gotowi do wysłania wiadomości EM_FINDTEXTEX. Po tej operacji sprawdzamy wynik poszukiwania zwrócony przez funkcję SendMessage. Jeśli wartość zwrotna wynosi -1, tekst nie został znaleziony w zakresie poszukiwań. W przeciwnym razie pole chrgText struktury FINDTEXTEX zostało wypełnione indeksami znakowymi poszukiwanego tekstu w obrębie kontrolki RichEdit. Zaznaczamy ten obszar przy pomocy wiadomości EM_EXSETSEL.Operacja zastępowania tekstu wykonywana jest w większości w ten sam sposób.

INVOKE GetDlgItemText, hWnd, IDC_FINDEDIT,
ADDR FindBuffer, SIZEOF FindBuffer
INVOKE GetDlgItemText, hWnd, IDC_REPLACEEDIT,
ADDR ReplaceBuffer, SIZEOF ReplaceBuffer
Odczytujemy tekst do wyszukania oraz tekst, który ma go zastąpić.
mov findtext.chrg.cpMin, 0
mov findtext.chrg.cpMax, -1
mov findtext.lpstrText, OFFSET FindBuffer
Aby ułatwić zadanie, operacja zastępowania tekstu jest globalna dla całego tekstu w kontrolce. Stąd indeks startowy wynosi 0 a indeks końcowy -1.
mov settext.flags, ST_SELECTION
mov settext.codepage, CP_ACP
Inicjujemy strukturę SETTEXTEX, aby zaznaczyć, iż chcemy zastąpić bieżący wybór i stosować standardową stronę kodową systemu.
.WHILE TRUE
INVOKE SendMessage, hwndRichEdit, EM_FINDTEXTEX,
FR_DOWN, ADDR findtext
.BREAK .IF eax==-1
INVOKE SendMessage, hwndRichEdit, EM_EXSETSEL,
0, ADDR findtext.chrgText
INVOKE SendMessage, hwndRichEdit, EM_SETTEXTEX,
ADDR settext, ADDR ReplaceBuffer
.ENDW
Wchodzimy w nieskończoną pętlę szukając wystąpień poszukiwanego tekstu w zawartości kontrolki RichEdit. Jeśli znajdziemy go, zaznaczamy ten obszar przy pomocy wiadomości EM_EXSETSEL i zastępujemy za pomocą EM_SETTEXTEX. Gdy brak już wystąpień poszukiwanego tekstu, przerywamy pętlę.
Opcje Znajdź Następny i Znajdź Poprzedni wykorzystują wiadomość EM_FINDTEXTEX w podobny sposób do operacji wyszukiwania.
W następnej kolejności przeanalizujemy operację przejścia do wskazanego wiersza. Gdy użytkownik wybierze z menu opcję Idź Do Wiersza, wyświetlamy odpowiednie okno dialogowe.

Gdy użytkownik wpisze numer wiersza i kliknie przycisk OK, rozpoczynamy operację.
INVOKE GetDlgItemInt, hWnd, IDC_LINENO, NULL, FALSE
mov LineNo, eax
Odczytujemy z kontrolki edycyjnej numer wiersza.
INVOKE SendMessage, hwndRichEdit, EM_GETLINECOUNT, 0, 0
.IF eax>LineNo
Odczytujemy liczbę wierszy w kontrolce. Sprawdzamy, czy wartość podana przez użytkownika leży w zakresie.
INVOKE SendMessage, hwndRichEdit, EM_LINEINDEX, LineNo, 0
Jeśli numer wiersza jest poprawny, to chcemy umieścić na początku tego wiersza kursor. Zatem wysyłamy do kontrolki RichEdit wiadomość EM_LINEINDEX. Wiadomość ta zwraca pozycję znakową pierwszego znaku w podanym wierszu. Numer wiersza wysyłamy w parametrze wParam, a w zamian dostajemy pozycję znakową w rejestrze eax.
INVOKE SendMessage, hwndRichEdit, EM_SETSEL, eax, eax
Do ustawienia bieżącego zaznaczenia wykorzystujemy tym razem wiadomość EM_SETSEL, ponieważ indeksy znaków nie znajdują się w strukturze CHARRANGE i w ten sposób zaoszczędzamy dwie instrukcje na umieszczenie ich tam.
INVOKE SetFocus, hwndRichEdit
.ENDIF
Kursor nie zostanie wyświetlony, dopóki kontrolka RichEdit nie otrzyma skupienia. Zatem wywołujemy dla niej funkcję SetFocus.
|
Autorem
kursu jest
Iczelion. Kurs
programowania Windows znalazł się na serwerze I LO w Tarnowie za pisemną
zgodą autora. |
![]() | I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe