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