You are on page 1of 11

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 1 de 11

Tutorial 33: Control RichEdit : Lo bsico


Hay muchas peticiones de tutoriales sobre controles RichEdit. Finalmente creo que puedo escribir algo sobre ellos. As que au est el: primer tutorial sobre el control RichEdit, que describe aproximadamente todo lo que se conoce sobre l al menos lo que yo conozco. La cantidad de informacin es bastante grande as que lo he dividido en varias partes, este tutorial es la primera parte. En este tutorial, aprenders que es un control RichEdit, como crearlo y como cargar/salvar datos a/de l. Baja el ejemplo.

Teora
Se puede pensar en un control richedit como en un control edit ms potete. Nos provee de muchas caractersticas de las que nos gustara disfrutar y que estn ausentes en un control edit simple; por ejemplo, la habilidad de usar mltiples tamaos y tipos de fuentes, asi como niveles mltiplesS de Deshacer/rehacer, operaciones de busqueda de texto, objetos OLE incrustados [OLE-embedded], soporte arrastrar-y-soltar [drag-and-drop] de edicion, etc. En definitiva, el control richedit tiene muchas caractersticas interesantes, almacenadas en una DLL aparte. Esto tambin significa que para usarla no basta slo con llamar a InitCommonControls como otros controles comunes. Tienes que llamar a LoadLibrary para cargar la DLL de richedit. El problema es que hasta ahora hay tres versiones del control richedit. La versin 1, la 2, y la 3. La tabla de abajo muestra el nombre de la DLL para cada versin. Nombre de la DLL Riched32.dll RichEd20.dll RichEd20.dll Versin de RichEdit 1.0 2.0 3.0 Nombre de clase del control Richedit RICHEDIT RICHEDIT20A RICHEDIT20A

Puedes notar que la versines 2 y 3 usan el mismo nombre de DLL. Tambin usan el mismo nombre de clase! Esto puede suponer un problema, si quieres usar caractersticas especificas del richedit 3.0. Hasta ahora no he encontrado ningn mtodo oficial para diferenciar entre la versin 2.0 y la 3.0. Sin embargo, hay uno posible que te mostrare despus. .data RichEditDLL db "RichEd20.dll",0 ..... .data? hRichEditDLL dd ? .code invoke LoadLibrary,addr RichEditDLL mov hRichEditDLL,eax ...... invoke FreeLibrary,hRichEditDLL Cuando es cargada la DLL del control richedit, registra su clase de ventana RichEdit. As que es imperativo que cargues la DLL antes de crear el control. Los nombres de clase del control richedit tambin son diferentes. En este momento puedes hacerte una pregunta: Cmo puedo saber qu versin de richedit debo usar? Usar la ltima versin no siempre es lo mas apropiado si no requieres las caractersticas extras. La tabla de abajo muestra las caractersticas provistas con cada versin del control richedit. Cracteristica Barra de seleccin Edicin 'unicode' Formato caracter/pargrafo Bsqueda de texto OLE embedding Edicin Arrastrar y Soltar [Drag and drop] Deshacer/Rehacer Reconocimiento automtico de URL Soporte para teclas aceleradoras Operacin Windowless Salto de Lnea Aumento [Zoom] Numeracin de Pargrafos Tabla simple Estilos normal y cabeceras Subrayado coloreado Texto oculto Fuente de encuadernacion CRLF x Hacia adelante x x nivel-simple Versin 1.0 x Versin 2.0 x x x adelante/atras x x multi-nivel x x x CR only Versin 3.0 x x x adelante/atras x x multi-nivel x x x CR only (can emulate versin 1.0) x x x x x x x

La tabla de arriba puede no ser del todo comprensible: slo he incluido una lista de las caractersticas importantes.

Creando el control richedit


Tras cargar la DLL del richedit, puedes llmar a CreateWindowEx para crear el control. Puedes usar estilos del control edit y estilos comunes de ventanas en CreateWindowEx excepto ES_LOWERCASE, ES_UPPERCASE y ES_OEMCONVERT. .const RichEditID equ 300 .data RichEditDLL db "RichEd20.dll",0 RichEditClass db "RichEdit20A",0 ... .data? .code ..... invoke LoadLibrary,addr RichEditDLL hRichEditDLL dd ? hwndRichEdit dd ?

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 2 de 11

mov hRichEditDLL,eax invoke CreateWindowEx,0,addr RichEditClass,WS_VISIBLE or ES_MULTILINE or WS_CHILD or WS_VSCROLL or WS_HSCROLL, \ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDE mov hwndRichEdit,eax

Poniendo texto y color de fondo por defecto


Puedes tener problemas poniendo color al texto y al fondo en un control edit, pero este problema ha sido remediado con el control richedit. Para poner el color de fondo de un richedit, enva EM_SETBKGNDCOLOR al richedit. Este mensaje tiene la sintaxis siguiente. wParam == opcin de color. Un valor de cero en este parmetro especifica que Windows usa el valor del color en lParam como color de fondo. Si este valor es distinto de cero, Windows usa el color de fondo del sistema. Una vez que enviamos este mensaje para cambiar el color de fondo, debemos pasar cero en wParam. lParam == especifica la estructura COLORREF del color que quieres poner si wParam es cero. Por ejemplo, si queremos poner el color de fondo azul puro, debo emitir la lnea siguiente: invoke SendMessage, hwndRichEdit, EM_SETBKGNDCOLOR, 0, 0FF0000h Para poner el color del texto, el control richedit provee otro nuevo mensaje para esta tarea, EM_SETCHARFORMAT. Este mensaje controla el formato del texto de un rango de caracteres seleccionados o todo el texto del control. Este mensaje tiene la siguiente sintaxis: wParam == opciones de formateo: SCF_ALL SCF_SELECTION SCF_WORD or SCF_SELECTION La operacin afecta a todo el texto en el control. La operacin afecta slo al texto seleccionado Afecta a las palabras seleccionadas. Si la seleccin est vaca, por ejemplo, el cursor est junto a la palabra, la operacin afecta a esa palabra, debe usarse la bandera [flag] SCF_WORD con SCF_SELECTION.

lParam == Puntero a una estructura CHARFORMAT o CHARFORMAT2 que especifica el formato de texto que sera aplicado CHARFORMAT2 esta disponible slo para el richedit 2.0 y superior. Esto no significa que debas usar CHARFORMAT2 obligatoriamente con RichEdit 2.0 o superior.Todava puedes usar CHARFORMAT si las caractersticas aadidas de CHARFORMAT2 no te son necesarias. CHARFORMATA STRUCT cbSize DWORD ? dwMask DWORD ? dwEffects DWORD ? yHeight DWORD ? yOffset DWORD ? crTextColor COLORREF ? bCharSet BYTE ? bPitchAndFamily BYTE ? szFaceName BYTE LF_FACESIZE dup(?) _wPad2 WORD ? CHARFORMATA ENDS Nombre de campo cbSize Descripcion El tamao de la estructura. RichEdit usa este campo para determinar la versin de la estructura si es CHARFORMAT o CHARFORMAT2 Bit indicadores [bit flags] que determinan cules miembros son vlidos. CFM_BOLD CFM_CHARSET CFM_COLOR CFM_FACE dwMask CFM_ITALIC CFM_OFFSET El valor CFE_BOLD valor del miembro dwEffects es vlido El miembro CharSet es vlido. El miembro crTextColor y el valor CFE_AUTOCOLOR del miembro dwEffects son vlidos El miembro szFaceName es vlido. El valor CFE_ITALIC del miembro dwEffects es vlido El miembro yOffset es vlido

CFM_PROTECTED El valor CFE_PROTECTED del miembro dwEffects es vlido CFM_SIZE CFM_STRIKEOUT CFM_UNDERLINE El miembro yHeight es vlido El valor CFE_STRIKEOUT del miembro dwEffects es vlido. El valor CFE_UNDERLINE del miembro dwEffects es vlido

Los efectos de caracteres. Pueden ser una combinacin de los valores siguientes CFE_AUTOCOLOR Usa el color de texto del sistema CFE_BOLD dwEffects CFE_ITALIC CFE_STRIKEOUT CFE_UNDERLINE CFE_PROTECTED yHeight yOffset crTextColor bCharSet bPitchAndFamily szFaceName _wPad2 Caracteres de tipo negrita Caracteres de tipo itlica Caracteres de tipo struck. Caracteres de tipo subrayado Caracteres protegidos; el intento de modificarlos har que se despliegue un mensaje de notificacin EN_PROTECTED

Altura de los caracteres, en twips (1/1440 de pulgada o 1/20 de puntos de impresora). Desplazamiento de los caracteres, en twips, desde la linea base. Si el valor de este miembro es positivo, el caracter es un superscript; si es negativo es un subscript. Color del Texto. Este miembro es ignorado si se ha especificado el efecto de caracter CFE_AUTOCOLOR . Valor del Caracter 'set' Fuente "family and pitch". Caracter terminado en NULL, array de caracteres especificando el nombre de la fuente Relleno

Examinando la estructura, vers que podemos cambiar los efectos del texto (negrita, itlica, tachado, subrayado), el color de texto (crTextColor), el tamao de la fuente tamao, etc.. Una bandera [flag] notable es CFE_RPOTECTED. El texto con esta bandera est marcado como protegido, lo cual significa que cuando el usuario intente modificarlo, se enviar el mensaje de notificacin EN_PROTECTED a la ventana padre. Y aqu, puedes permitirlo o no. CHARFORMAT2 aade mas estilos de texto tales como fuente, altura, espaciado, color de texto y de fondo, etc. Si no necesitas estas caracterrsticas extras simplemente usa CHARFORMAT.

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 3 de 11

Para poner texto formateado, has de pensar en el rango del texto que quieres aplicarle. El Richedit introduce la nocin de Rango de caracter del texto. El Richedit da a cada caracter un nmero comenzando desde cero: El primer caracter en el control tiene el ID nmero cero, el segundo el uno y as sucesivamente. Para especificar el rango de un texto, debes dar al richedit dos nmeros, el ID del primero caracter del rango y el del ltimo. Para aplicar el formato de texto con EM_SETCHARFORMAT, tienes al menos tres opciones:

1. Aplicarlo a todo el texto en el control (SCF_ALL) 2. Aplicarlo al texto actualmente seleccionado (SCF_SELECTION) 3. Aplicarlo a la palabra completa actualmente seleccionada (SCF_WORD or SCF_SELECTION)
La primera y segunda opcin son "straightforward" (Directas). La ltima opcin requiere una aclaratoria. Si la seleccin actual slo cubre uno o mas de los caracteres en la palabra pero no la palabra completa, especificando la bandera SCF_WORD+SCF_SELECTION se aplicar el formato de texto a la palabra completa, incluso si no hay una seleccin en ese momento, por ej. Slo el cursor est colocado en la palabra. La tercera opcin tambin aplica el formato de texto a la palabra completa. Para usar EM_SETCHARFORMAT, necesitas rellenar varios miembros de la estructura CHARFORMAT (o CHARFORMAT2) . Por ejemplo si queremos poner el color del texto, llenaremos la estructura CHARFORMAT como sigue:

.data? cf CHARFORMAT <> .... .code mov cf.cbSize,sizeof cf mov cf.dwMask,CFM_COLOR mov cf.crTextColor,0FF0000h invoke SendMessage,hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,addr cf
El recorte de cdigo de arriba pone el color de texto del control richedit en azul puro. Nota que si no hay texto en el control richedit cuando EM_SETCHARFORMAT sea emitido, el texto introducido en el control richedit seguir al mensaje que usar el formato de texto especificado por el mensaje EM_SETCHARFORMAT.

Poniendo texto/salvando texto


Aquellos que han usado el control edit seguramente estarn familiarizados con los mensajes WM_GETTEXT/WM_SETTEXT, que significan obtener texto/poner texto del control. Este mtodo an funciona con el control richedit pero puede no ser eficiente si el archivo es muy grande. El control Edit limita el texto que puede ser introducido a 64KB, pero el control richedit puede aceptar una cantidad de texto mucho mayor. Sera muy engorroso localizar un bloque de memoria muy grande (tal como 10 MB) para recibir el texto usando el mensaje WM_GETTEXT. El control richedit ofrece una nueva aproximacin a este mtodo, por ej. tratamiento del texto como un stream (flujo continuo) de datos [text streamming]. (NOTA: la palabra 'stream', que se puede traducir como "flujo", designa aqu una cadena continua de datos, con un tamao determinado). Para ponerlo simplemente, provees la direccin de una funcin callback para el control richedit, y ste la llamar pasndole la direccin del buffer cuando est listo. La funcin callback llenar el buffer con los datos deseados para enviar al control o leer los datos desde el buffer y entonces espera la siguiente llamada hasta que la operacin termina. Este paradigma es usado por ambos streams: introducir el stream [streaming in] y sacando el stream [streaming out]. Vers que estos mtodos son mas eficientes: el buffer es provisto por el control richedit as que los datos son divididos en pedazos. Las operaciones involucran dos mensajes: EM_STREAMIN y EM_STREAMOUT Ambos EM_STREAMIN y EM_STREAMOUT usan la misma sintaxis: wParam == opciones de formateo. SF_RTF SF_TEXT SFF_PLAINRTF Los datos en el texto enriquecido estn en formato RTF Los datos estn en formato de texto plano Slo las palabras claves comunes a todos los lenguajes son introducidas [streamed in].

Si es especificada, el objetivo de la operacin es el texto actualmente seleccionado. Si tu vuelcas el texto en el control richeedit (stream in), el texto reemplazar SFF_SELECTION la seleccin actual. Si sacas ( stream out ) el texto, slo el texto seleccionado actualmente es sacado (streamed out). Si esta bandera no est especificado la operacin afectar a todo el texto del control. SF_UNICODE ( Disponible en el RichEdit 2.0 o posterior ) Especifica el texto unicode.

lParam == Puntero a una estructura EDITSTREAM la cual tiene la definicin siguiente:

EDITSTREAM STRUCT dwCookie DWORD ? dwError DWORD ? pfnCallback DWORD ? EDITSTREAM ENDS Valor definido por la aplicacin que ser pasado a la funcin callback y que est especificado en el miembro pfnCallback de abajo. Normalmente pasamos algn valor importante a la funcin callback tal como el manejador [handle] del archivo para que sea usado en el procedimiento stream-in/out (lectura /escritura de stream). Indica el resultado de las operaciones de stream-in (lectura) o stream-out (escritura). Un valor de cero indica que no hay error. Un valor que no sea cero puede ser el valor de retorno de la funcin EditStreamCallback o un cdigo indicando que el control ha encontrado un error. Puntero a una funcin EditStreamCallback la cual es una funcin definida por la aplicacion que controla las llamadas para transferir datos . El control llama a la funcin callback repetidamente transfiriendo una porcin de los datos en cada llamada

dwCookie dwError pfnCallback

La funcin callback del editor de streams tiene la siguiente definicin: EditStreamCallback proto dwCookie:DWORD, pBuffer:DWORD, NumBytes:DWORD, pBytesTransferred:DWORD Puedes crear una funcin en tu programa con el prototipo de arriba y pasarle la direccin de EM_STREAMIN o EM_STREAMOUT a travs de la estructura EDITSTREAM. Para operaciones stream-in (Poner el texto en el control richedit): dwCookie: El valor definido por la aplicacin que pasas a EM_STREAMIN a travs de la estructura EDITSTREAM. Casi siempre pasamos aqu el handle del archivo que queremos poner su contenido al control. pBuffer: puntero al buffer provisto por el control richedit que recibir el texto desde tu funcin callback. NumBytes: El nmero maximo de bytes que puedes escribir al buffer (pBuffer) en esta llamada. Siempre DEBES obedecer este lmite, por ej. se pueden enviar menos datos que el valor en NumBytes pero nunca mas. Puedes pensar en este valor como el tamao del buffer en pBuffer. pBytesTransferred: Puntero al dword en el que debes poner el valor indicando el nmero de bytes realmente transferidos al buffer. Este valor es usualmente idntico al valor en NumBytes. La excepcin es cuando los datos enviados son menores que el tamao del buffer provisto, como cuando se halla el final del archivo .

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 4 de 11

Para operaciones stream-out (obteniendo el texto del control richedit): dwCookie: Igual que en la operacin stream-in. Usualmente pasamos el handle del archivo al que queremos escribir los datos en este parmetro. pBuffer: puntero al buffer provisto por el control richedit que es llenado con los datos del control richedit. Para obtener este tamao debes examinar el valor de NumBytes. NumBytes: El tamao de los datos en el buffer apuntado por pBuffer. pBytesTransferred: Puntero a un dword en el que debes poner el valor indicando el nmero de bytes actualmente ledos del buffer. La funcin callback devuelve 0 para indicar xito y el control richedit continuara llamando a la funcin callback si todava hay datos para leer/escribir. Si ocurre algn error durante el proceso y quieres parar la operacin, devuelve un valor distinto de cero al control richedit y descartar el dato apuntado por pBuffer. El valor de error/xito ser puesto en el campo dwError de EDITSTREAM, as puedes examinar el estado de error/xito de la operacin con el stream, despus que regresa la llamada a SendMessage .

Ejemplo:
Este ejemplo es un simple editor, con l puedes abrir un archivo de cdigo fuente en asm, editarlo y guardarlo. He usado control richedit versin 2.0 o superior. .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 IDM_OPEN equ 40001 IDM_SAVE equ 40002 IDM_CLOSE equ 40003 IDM_SAVEAS equ 40004 IDM_EXIT equ 40005 IDM_COPY equ 40006 IDM_CUT equ 40007 IDM_PASTE equ 40008 IDM_DELETE equ 40009 IDM_SELECTALL equ 40010 IDM_OPTION equ 40011 IDM_UNDO equ 40012 IDM_REDO equ 40013 IDD_OPTIONDLG equ 101 IDC_BACKCOLORBOX equ 1000 IDC_TEXTCOLORBOX equ 1001 RichEditID equ 300

.data ClassName db "IczEditClass",0 AppName db "IczEdit version 1.0",0 RichEditDLL db "riched20.dll",0 RichEditClass db "RichEdit20A",0 NoRichEdit db "Cannot find riched20.dll",0 ASMFilterString db "ASM Source code (*.asm)",0,"*.asm",0 db "All Files (*.*)",0,"*.*",0,0 OpenFileFail db "Cannot open the file",0 WannaSave db "The data in the control is modified. Want to save it?",0 FileOpened dd FALSE BackgroundColor dd 0FFFFFFh ; blanco por defecto TextColor dd 0 ; negro por defecto .data? hInstance dd ? hRichEdit dd ? hwndRichEdit dd ? FileName db 256 dup(?) AlternateFileName db 256 dup(?) CustomColors dd 16 dup(?) .code start: 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

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 5 de 11

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 .while TRUE invoke GetMessage, ADDR msg,0,0,0 .break .if (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .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 eax,wParam shr eax,16 .if ax==BN_CLICKED mov eax,wParam .if ax==IDCANCEL invoke SendMessage,hWnd,WM_CLOSE,0,0 .elseif ax==IDC_BACKCOLORBOX invoke 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

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 6 de 11

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 ;============================================================================ ; Guardar el estado del control richedit porque al cambiar el color del texto se cambia el ; estado de modificacin del control richedit. ;============================================================================ 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 WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD LOCAL chrg:CHARRANGE LOCAL ofn:OPENFILENAME LOCAL buffer[256]:BYTE LOCAL editstream:EDITSTREAM LOCAL hFile:DWORD .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_HSC CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,hWnd,RichEditID,hInstance,0 mov hwndRichEdit,eax ;============================================================= ; Se establece el lmite del texto. El valor por defecto es 64K ;============================================================= invoke SendMessage,hwndRichEdit,EM_LIMITTEXT,-1,0 ;============================================================= ; Se establece el color del fondo del texto por defecto ;============================================================= invoke SetColor invoke SendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0 invoke SendMessage,hwndRichEdit,EM_EMPTYUNDOBUFFER,0,0 .elseif uMsg==WM_INITMENUPOPUP mov eax,lParam .if ax==0 ; file menu .if FileOpened==TRUE ; a file is already opened invoke EnableMenuItem,wParam,IDM_OPEN,MF_GRAYED invoke EnableMenuItem,wParam,IDM_CLOSE,MF_ENABLED invoke EnableMenuItem,wParam,IDM_SAVE,MF_ENABLED invoke EnableMenuItem,wParam,IDM_SAVEAS,MF_ENABLED .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 ; edit menu ;============================================================================= ; Chequear si hay algn texto en el clipboard. Si es as, habilitamos pegar [paste] en el tem del men ;============================================================================= invoke SendMessage,hwndRichEdit,EM_CANPASTE,CF_TEXT,0 .if eax==0 ; no text in the clipboard invoke EnableMenuItem,wParam,IDM_PASTE,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_PASTE,MF_ENABLED .endif ;========================================================== ; Chequear si la solicitud de deshacer [undo] est vaca ;========================================================== invoke SendMessage,hwndRichEdit,EM_CANUNDO,0,0 .if eax==0

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 7 de 11

invoke EnableMenuItem,wParam,IDM_UNDO,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_UNDO,MF_ENABLED .endif ;========================================================= ; check whether the redo queue is empty ;========================================================= invoke SendMessage,hwndRichEdit,EM_CANREDO,0,0 .if eax==0 invoke EnableMenuItem,wParam,IDM_REDO,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_REDO,MF_ENABLED .endif ;========================================================= ; Chequear si hay una seleccin actual en el control richedit. ; Si lo hay, habilitamos los tems de men cut/copy/delete [cortar/copiar/suprimir] ;========================================================= invoke SendMessage,hwndRichEdit,EM_EXGETSEL,0,addr chrg mov eax,chrg.cpMin .if eax==chrg.cpMax ; no current selection invoke EnableMenuItem,wParam,IDM_COPY,MF_GRAYED invoke EnableMenuItem,wParam,IDM_CUT,MF_GRAYED invoke EnableMenuItem,wParam,IDM_DELETE,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_COPY,MF_ENABLED invoke EnableMenuItem,wParam,IDM_CUT,MF_ENABLED invoke EnableMenuItem,wParam,IDM_DELETE,MF_ENABLED .endif .endif .elseif uMsg==WM_COMMAND .if lParam==0 ; rdenes de 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_NO .if eax!=INVALID_HANDLE_VALUE mov hFile,eax ;================================================================ ; introducir el stream de texto en el control richedit ;================================================================ mov editstream.dwCookie,eax mov editstream.pfnCallback,offset StreamInProc invoke SendMessage,hwndRichEdit,EM_STREAMIN,SF_TEXT,addr editstream ;========================================================== ; Inicializar el estado de modificacin como falso ;========================================================== 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 ;================================================================ ; llevar el stream de texto al archivo ;================================================================ mov editstream.dwCookie,eax mov editstream.pfnCallback,offset StreamOutProc invoke SendMessage,hwndRichEdit,EM_STREAMOUT,SF_TEXT,addr editstream ;========================================================== ; Inicializar el estado de modificacin como falso ;========================================================== 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

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 8 de 11

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_ATT .if eax!=INVALID_HANDLE_VALUE jmp @B .endif .endif .elseif ax==IDM_EXIT invoke SendMessage,hWnd,WM_CLOSE,0,0 .endif .endif .elseif uMsg==WM_CLOSE invoke CheckModifyState,hWnd .if eax==TRUE invoke DestroyWindow,hWnd .endif .elseif uMsg==WM_SIZE mov eax,lParam mov edx,eax and eax,0FFFFh shr edx,16 invoke MoveWindow,hwndRichEdit,0,0,eax,edx,TRUE .elseif uMsg==WM_DESTROY invoke PostQuitMessage,NULL .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .endif xor eax,eax ret WndProc endp end start ;=================================================================== ; El archivo de recursos ;=================================================================== #include "resource.h" #define IDR_MAINMENU 101 #define IDD_OPTIONDLG 101 #define IDC_BACKCOLORBOX 1000 #define IDC_TEXTCOLORBOX 1001 #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 IDR_MAINMENU MENU DISCARDABLE BEGIN POPUP "&File" BEGIN MENUITEM "&Open", IDM_OPEN MENUITEM "&Close", IDM_CLOSE MENUITEM "&Save", IDM_SAVE MENUITEM "Save &As", IDM_SAVEAS MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT END POPUP "&Edit" BEGIN MENUITEM "&Undo", IDM_UNDO MENUITEM "&Redo", IDM_REDO MENUITEM "&Copy", IDM_COPY MENUITEM "C&ut", IDM_CUT MENUITEM "&Paste", IDM_PASTE MENUITEM SEPARATOR MENUITEM "&Delete", IDM_DELETE MENUITEM SEPARATOR MENUITEM "Select &All", IDM_SELECTALL END MENUITEM "Options", IDM_OPTION END

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 9 de 11

IDD_OPTIONDLG DIALOG DISCARDABLE 0, 0, 183, 54 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_CENTER CAPTION "Options" FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",IDOK,137,7,39,14 PUSHBUTTON "Cancel",IDCANCEL,137,25,39,14 GROUPBOX "",IDC_STATIC,5,0,124,49 LTEXT "Background Color:",IDC_STATIC,20,14,60,8 LTEXT "",IDC_BACKCOLORBOX,85,11,28,14,SS_NOTIFY | WS_BORDER LTEXT "Text Color:",IDC_STATIC,20,33,35,8 LTEXT "",IDC_TEXTCOLORBOX,85,29,28,14,SS_NOTIFY | WS_BORDER END

Anlisis:
El programa primero carga la dll correspondiente al control richedit, que en este caso es riched20.dll. Si no puede ser cargada la dll saldr a Windows. 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 Despus que la dll es cargada con xito procedemos a crear una ventana normal que ser la ventana padre del control richedit. Dentro del manejador del mensaje WM_CREATE, creamos el control richedit: invoke CreateWindowEx,WS_EX_CLIENTEDGE,addr RichEditClass,0,WS_CHILD or WS_VISIBLE or ES_MULTILINE or WS_VSCROLL or WS_HSC CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,hWnd,RichEditID,hInstance,0 mov hwndRichEdit,eax Nota que especificamos el estilo ES_MULTILINE sino sera un control de slo una linea [single-lined]. invoke SendMessage,hwndRichEdit,EM_LIMITTEXT,-1,0 Despus que el control richedit es creado, debemos ponerle el nuevo lmite de texto. por defecto, el control richedit tiene 64KB de lmite de texto lo mismo que un simple control Edit multilnea. Debemos extender este lmite para permitir operaciones con archivos grandes. En la lnea de arriba he puesto -1 el cual recoge la cantidad de 0FFFFFFFFh, un valor bien grande. invoke SetColor A continuacin ponemos el color del texto/fondo. Luego puede ser performateado en otra perte del programa. He puesto el cdigo en una funcin llamada SetColor. SetColor proc LOCAL cfm:CHARFORMAT invoke SendMessage,hwndRichEdit,EM_SETBKGNDCOLOR,0,BackgroundColor Poner el color de fondo del control richedit es una operacin directa: solo envia el mensaje EM_SETBKGNDCOLOR al control richedit. (si usas un control Edit multilnea, debes procesar WM_CTLCOLOREDIT). El color por defecto es el blanco. invoke RtlZeroMemory,addr cfm,sizeof cfm mov cfm.cbSize,sizeof cfm mov cfm.dwMask,CFM_COLOR push TextColor pop cfm.crTextColor Tras haber puesto el color de fondo, llenamos los miembros de CHARFORMAT con el fin de poner el color del texto. Nota que llenamos cbSize con el tamao de la estructura, as el control richedit sabe que estamos envindole CHARFORMAT, no CHARFORMAT2. dwMask slo tiene una bandera, CFM_COLOR, y que indica slo queremos poner el color del texto y crTextColor es llenado con el valor del color deseado para el texto. invoke SendMessage,hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,addr cfm ret SetColor endp Despus de esto tienes vaco el buffer 'undo', simplemente porque el acto de cambiar el color del texto/fondo est habilitado para deshacer [undo]. Enviamos el mensaje EM_EMPTYUNDOBUFFER para lograr esto. invoke SendMessage,hwndRichEdit,EM_EMPTYUNDOBUFFER,0,0 Tras rellenar la estructura CHARFORMAT enviamos EM_SETCHARFORMAT al control richedit, especificando la bandera [flag] SCF_ALL en wParam para indicar que queremos que el texto formateado sea aplicado a todo el texto en el control. Nota que cuando creamos elprimero control richedit, no especificamos su tamao/posicin en ese momento. esto es porque queremos cubrir todo el rea cliente de la ventana padre. La redimensionamos cuando cambia el tamao de la ventana padre. .elseif uMsg==WM_SIZE mov eax,lParam mov edx,eax and eax,0FFFFh shr edx,16 invoke MoveWindow,hwndRichEdit,0,0,eax,edx,TRUE En el cdigo de arriba, usamos la nueva dimensin del area cliente pasada en lParam para redimensionar el control richedit con MoveWindow. Cuando el usuario hace click sobre el men File/Edit, procesamos WM_INITPOPUPMENU as que podemos preparar los estados de los items del men en el submen antes de mostrarlos al usuario. Por ejemplo, si un archivo ya est abierto en el control richedit, queremos desactivar el item del men open y activar el resto de items del men. En el caso del men File, usamos la variable FileOpened como la bandera [flag] para determinar si ya hay un archivo abierto. Si el valor de esta variable es TRUE, sabremos que ya hay un archivo abierto. .elseif uMsg==WM_INITMENUPOPUP

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 10 de 11

mov eax,lParam .if ax==0 ; file menu .if FileOpened==TRUE ; a file is already opened invoke EnableMenuItem,wParam,IDM_OPEN,MF_GRAYED invoke EnableMenuItem,wParam,IDM_CLOSE,MF_ENABLED invoke EnableMenuItem,wParam,IDM_SAVE,MF_ENABLED invoke EnableMenuItem,wParam,IDM_SAVEAS,MF_ENABLED .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 Como puedes ver, si un archivo ya est abierto, difuminamos [grayed] el men open y activamos el resto de tems del men. Ocurre lo contrario si FileOpened es false. En el caso del men edit, necesitamos mirar primero el estado del control richedit/clipboard.

invoke SendMessage,hwndRichEdit,EM_CANPASTE,CF_TEXT,0 .if eax==0 ; no text in the clipboard invoke EnableMenuItem,wParam,IDM_PASTE,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_PASTE,MF_ENABLED .endif Primero revisamos si hay algun texto en el clipboard enviando el mensaje EM_CANPASTE. Si lo hay, SendMessage devuelve TRUE y activamos el men paste, sino, lo difuminamos [grayed]. invoke SendMessage,hwndRichEdit,EM_CANUNDO,0,0 .if eax==0 invoke EnableMenuItem,wParam,IDM_UNDO,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_UNDO,MF_ENABLED .endif A continuacion miramos si el buffer 'undo' est vaco enviando el mensaje EM_CANUNDO, si no est vaco, SendMessage devuelve TRUE y activamos el men undo.

invoke SendMessage,hwndRichEdit,EM_CANREDO,0,0 .if eax==0 invoke EnableMenuItem,wParam,IDM_REDO,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_REDO,MF_ENABLED .endif Revisiramos el buffer 'redo' enviando el mensaje EM_CANREDO al control richedit. si no est vaco, SendMessage devuelve TRUE y activamos el men 'redo'.

invoke SendMessage,hwndRichEdit,EM_EXGETSEL,0,addr chrg mov eax,chrg.cpMin .if eax==chrg.cpMax ; no current selection invoke EnableMenuItem,wParam,IDM_COPY,MF_GRAYED invoke EnableMenuItem,wParam,IDM_CUT,MF_GRAYED invoke EnableMenuItem,wParam,IDM_DELETE,MF_GRAYED .else invoke EnableMenuItem,wParam,IDM_COPY,MF_ENABLED invoke EnableMenuItem,wParam,IDM_CUT,MF_ENABLED invoke EnableMenuItem,wParam,IDM_DELETE,MF_ENABLED .endif por ltimo miramos si existe una seleccin enviando el mensaje EM_EXGETSEL. Este mensaje usa una estructura CHARRANGE la cual se define como sigue: CHARRANGE STRUCT cpMin DWORD ? cpMax DWORD ? CHARRANGE ENDS cpMin contiene el ndice de posicin del caracter immediatamente precedente al primer caracter en el rango. cpMax contiene la posicin del caracter inmediatamente posterior al ltimo caracter en el rango. Despus que EM_EXGETSEL retorna, la estructura CHARRANGE es llenada con con el ndice de la posicin (starting-ending) principio/final del rango de seleccin. Si no hay seleccin, cpMin y cpMax son idnticos y ponemos en gris los mens cut/copy/delete. Cuando el usuario hace clcik en el men Open, mostramos el cuadro de dialogo "open file" y si el usuario selecciona un archivo abrimos el archivo y volcamos el contenido al control richedit. invoke CreateFile,addr FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if eax!=INVALID_HANDLE_VALUE mov hFile,eax mov editstream.dwCookie,eax mov editstream.pfnCallback,offset StreamInProc invoke SendMessage,hwndRichEdit,EM_STREAMIN,SF_TEXT,addr editstream Una vez que el archivo ha sido abierto exitosamente con CreateFile, rellenamos la estructura EDITSTREAM en preparacin para el mensaje EM_STREAMIN. Escogemos enviar el manejador [handle] del archivo abierto a travs del miembro dwCookie y pasamos la direccin de la funcin callback del stream en pfnCallback. El procedimiento callback del stream es la esencia de la simplicidad. StreamInProc proc hFile:DWORD,pBuffer:DWORD, NumBytes:DWORD, pBytesRead:DWORD invoke ReadFile,hFile,pBuffer,NumBytes,pBytesRead,0 xor eax,1 ret StreamInProc endp Puedes ver todos los parmetros del procedimiento callback del stream perfectamente adaptado a ReadFile. Y el valor de retorno de ReadFile es "xoredado" con 1 asi que si devuelve 1 (xito), el valor actual devuelto en eax es 0 y viceversa.

invoke SendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0 invoke CloseHandle,hFile mov FileOpened,TRUE

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

Tutorial de Iczelion sobre Win32 asm: Control RichEdit Control: Lo bsico

Pgina 11 de 11

Despus que EM_STREAMIN retorna, significa que la operacin stream se ha completado. En realidad, debemos mirar el valor del miembro dwError de la estructura EDITSTREAM. El Richedit (y edit) control soportan una bandera para indicar que el contenido ha cambiado. Podemos obtener el valor de esta bandera enviando el mensaje EM_GETMODIFY al control. SendMessage devuelve TRUE si este ha cambiado. Al volcar el texto al control, es una clase de modificacin. Debemos poner la bandera de modificacin a FALSE enviando EM_SETMODIFY con wParam==FALSE para comenzar de nuevo despus que termine. la operacin 'stream-in'. Inmediatamente cerramos el archivo y ponemos FileOpened a TRUE para indicar que el archivo fue abierto. Cuando el usuario hace click sobre los mens Guardar/Guardar, usamos el mensaje EM_STREAMOUT para sacar el contenido del control richedit a un archivo. Como con la funcin stream-in callback, la funcin stream-out callback es simple. Se adapta perfectamente a WriteFile. Las operaciones tales como cut/copy/paste/redo/undo son faciles de implementar enviando un simple mensaje al control richedit, WM_CUT/WM_COPY/WM_PASTE/WM_REDO/WM_UNDO respectivamente. Las operaciones 'delete/select all', son como sigue:

.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 La operacin 'delete' afecta a la actual seleccin. Envio el mensaje EM_REPLACESEL con la direccin de la cadena igual a cero o NULL, as el control richedit reemplazar el texto actualmente seleccionado con una cadena nula. La operacin 'select-all', se hace enviando el mensaje EM_EXSETSEL, especificando cpMin==0 y cpMax==-1 lo cual recoge todo el texto seleccionndolo. Cuando el usuario selecciona la barra de men 'Option', mostramos un cuadro de dilogo presentando el actual color de fondo/texto.

Cuando el usuario hace click sobre una de las cajas de color, se muestra el dilogo de 'elegir color' ['choose-color']. La caja de colores es de hecho un control esttico con la bandera SS_NOTIFY y WS_BORDER. Un control esttico con la bandera SS_NOTIFY notificar a su ventana padre con las acciones del ratn, tales como, BN_CLICKED (STN_CLICKED). Ese es el truco.

.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 Cuando el usuario hace click sobre un color, rellenamos el miembro de la estructura CHOOSECOLOR y llamamos a ChooseColor para mostrar el dilogo "choose-color". Si el usuario selecciona un color, el valor 'colorref' es devuelto en el miembro rgbResult y guardamos el valor en la variable BackgroundColor. Despus de esto, forzamos que se vuelva a pintar sobre la caja de color llamando a InvalidateRect sobre el manejador [handle] de la caja de color. La caja de color enva el mensaje WM_CTLCOLORSTATIC a su ventana padre. invoke GetDlgItem,hWnd,IDC_BACKCOLORBOX .if eax==lParam invoke CreateSolidBrush,BackgroundColor ret Dentro del manejador [handle] WM_CTLCOLORSTATIC comparamos el manejador [handle] del control esttico pasado en lParam para ambas cajas de color. Si el valor coincide creamos una nueva brocha usando el color de la variable e inmediatamente regresamos. Usaremos la nueva brocha para pintar el fondo.

ndice Next [Iczelion's Win32 Assembly Homepage] n u M I T_o r's Programming Page Este tutorial, original de Iczelion, ha sido traducido por mnemox, y revisado por n u M I T_o r Pgina personal de mnemox

http://mipagina.cantv.net/numetorl869/tut33_es.html

30/08/2008

You might also like