Práctica 7

Anuncio
UNIVERSIDAD DEL ISTMO
Ingeniería en computación
Compiladores
PROFESOR
M. en C. J. Jesús Arellano Pimentel
NÚMERO DE PRÁCTICA
7
NOMBRE DE LA PRÁCTICA
Un simple editor de texto.
OBJETIVO GENERAL
Crear un simple editor de texto Win32 con funcionalidades
básicas.
OBJETIVOS ESPECÍFICOS
EQUIPO REQUERIDO
SOFTWARE REQUERIDO
-
Crear una aplicación para la edición de texto plano.
Abrir y guardar archivos de texto plano.
Formatear un par de palabras en el texto.
Computadora personal con 512 MB de RAM mínimo.
- Windows 7/8.
- Microsoft Visual Studio Express 2012 para escritorio
de Windows.
1.- Fundamentos.
1.1.- Los controles de edición Win32
Uno de los controles de edición más habituales en aplicaciones Win32 son los tipo clase edit.
Estos controles se pueden configurar para que sean de línea única o de múltiples líneas
[Petzold95]. Los controles de múltiples líneas permiten realizar operaciones básicas como:
mover el cursor de edición, seleccionar porciones de texto usando el ratón o teclado, mover el
texto seleccionado al portapapeles (Ctrl+x), copiar texto (Ctrl+c), e incluso insertar texto
desde el portapapeles (Ctrl+v).
También existe una versión mejorada de estos controles clase edit y son conocidos como
richedit (edición enriquecida). Este tipo de control es más potente y permite, entre otras
muchas cosas, formatear el texto utilizando diferentes fuentes y colores.
2.- Desarrollo
2.1 Crear un Proyecto Win32 con un control de edición RichEdit
Paso 1 Iniciar el MVS Express 2012.
Paso 2 Crear un nuevo proyecto Win32.
Seleccionar la opción del menú Archivo->Nuevo Proyecto. Del cuadro de diálogo
Nuevo proyecto en Plantillas seleccionar Visual C++ y Win32; en tipo de aplicación
Ingeniería en Computación
M. C. J. Jesús Arellano Pimentel
1
seleccionar Proyecto Win32 Visual C++ (ver Figura 1). El nombre del proyecto o
solución podría ser EdtWin32. Presionar el botón Aceptar.
Figura 1. Cuadro de diálogo Nuevo Proyecto para la aplicación EdtWin32.
Paso 3 Configurar el Proyecto Actual.
En el Asistente para aplicaciones Win32 presionar el botón siguiente; después
deshabilitar la casilla de verificación de Comprobación del ciclo de vida de desarrollo
de seguridad(SDL); finalmente oprimir el botón Finalizar.
Paso 4 Editar el código para crear una ventana con un control RichEdit.
En la función WndProc agregar las siguientes variables:
static HWND hWndEdit;
CHARFORMAT2 cf;
DWORD dwEVM;
HFONT hFont;
//Manejador de ventana
//Formato del texto
//Evento de captura
//Manejador de fuente
Después, agregar el procesamiento del mensaje WM_CREATE con el siguiente código:
case WM_CREATE:
LoadLibrary(L"riched20.dll");
hWndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, L"", WS_CHILD
| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL
| ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
0, 0, 0, 0,
hWnd, (HMENU) ID_EDITRICH, hInst, NULL);
hFont
= CreateFont( 18, 0, 0, 0, 0, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, L"Arial" );
SendMessage( hWndEdit, WM_SETFONT, ( WPARAM ) hFont, 0 );
SetFocus(hWndEdit);
break;
Ingeniería en Computación
M. C. J. Jesús Arellano Pimentel
2
Además de cargar la librería (LoadLibrary(L"riched20.dll")), también es necesario
incluir el archivo de encabezado correspondiente en el archivo stdafx.h, conjuntamente
con las librerías commdlg.h y stdio.h, de la siguiente forma:
// TODO:
#include
#include
#include
mencionar aquí los encabezados adicionales que el programa necesita
<richedit.h>
<commdlg.h>
<stdio.h>
Aparte, habrá que definir la constante simbólica asociada a este control, el cuál es el
antepenúltimo parámetro de la función CreateWindowEx. Esta debería estar en el
archivo Resource.h de la siguiente forma:
// Valores predeterminados siguientes para nuevos objetos
//
#define ID_EDITRICH
200
Ya por último, es necesario redimensionar el control de edición para que tome todo el
tamaño del área cliente de la ventana principal, esto se logra procesando el mensaje
WM_SIZE, el cual se debe agregar después del WM_CREATE con el siguiente código:
case WM_SIZE:
MoveWindow(hWndEdit, 0, 0, LOWORD (lParam), HIWORD(lParam), TRUE);
break;
Hecho lo anterior esta todo listo para realizar una primera prueba.
Paso 5 Guardar todo, compilar y probar.
Para cerciorarse que todo va bien, se deben guardar todos los cambios, compilar y
ejecutar la aplicación, el resultado deberá ser el de la Figura 2. Esta aplicación ya
puede procesar mensajes de forma predefinida para seleccionar, copiar/cortar y pegar
texto, así como la opción de deshacer.
Ingeniería en Computación
M. C. J. Jesús Arellano Pimentel
3
Figura 2. Ejecución de la aplicación EdtWin32.
Paso 6 Agregar las opciones del menú para Abrir y Guardar un archivo de texto plano.
Las funcionalidades de Abrir y Guardar archivo estarán asociadas a dos nuevos
elementos del menú principal, por lo cual será necesario agregar sus constantes
simbólicas en el archivo Resource.h y sus elementos de menú en el archivo
EdtWin32.rc. El código para las constantes simbólicas en Resource.h es el siguiente:
#define IDM_ABRIR
#define IDM_GUARDAR
201
202
El código para los elementos del menú en el archivo EdtWin32.rc es el siguiente:
MENUITEM "&Abrir",
MENUITEM "&Guardar",
IDM_ABRIR
IDM_GUARDAR
Recuérdese que el código anterior va dentro del menú archivo correspondiente al menú
principal, el cuál inicia aproximadamente en la línea 38 del archivo EdtWin32.rc.
Paso 7 Procesar los mensajes (comandos) para abrir y guardar un archivo de texto plano.
El procesamiento de los mensajes IDM_ABRIR e IDM_GUARDAR debe hacerse dentro del
switch correspondiente al procesamiento del mensaje WM_COMMAND de la función
WndProc, previo al caso default de la siguiente manera:
case IDM_ABRIR:
{
TCHAR szFile[MAX_PATH], szCaption[64 + _MAX_FNAME + _MAX_EXT];
ZeroMemory(szFile, MAX_PATH);
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize
= sizeof(OPENFILENAME);
ofn.Flags
= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
OFN_HIDEREADONLY | OFN_CREATEPROMPT;
ofn.hwndOwner = hWnd;
ofn.lpstrFilter
= _T("Tipos de formatos
soportados(*.txt)\0*.txt\0Texto (*.txt)\0\0");
ofn.lpstrTitle
= _T("Abrir archivo de texto");
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
if (IDOK == GetOpenFileName(&ofn)){
wsprintf(szCaption,_T("%s - %s"),szTitle, szFile[0] ? szFile :
_T("Sin archivo abierto"));
SetWindowText(hWnd, szCaption);
FILE *file ;
int
iLength ;
PSTR
pstrBuffer ;
char
cFile[MAX_PATH];
TCHAR *ptchBuffer;
wcstombs(cFile,szFile,MAX_PATH);
if (NULL == (file = fopen (cFile, "rb"))){
MessageBox(hWnd,L"Error al leer el archivo", L"Error",
MB_OK | MB_ICONERROR);
Ingeniería en Computación
M. C. J. Jesús Arellano Pimentel
4
}else{
iLength = PopFileLength (file) ;
if (NULL == (pstrBuffer = (PSTR) malloc
(sizeof(char)*(iLength+1))) ||
NULL == (ptchBuffer = (TCHAR*) malloc
(sizeof(TCHAR)*(iLength+1)))){
fclose (file) ;
MessageBox(hWnd,L"Error al reservar memoria",
L"Error", MB_OK | MB_ICONERROR);
}else{
fread (pstrBuffer, 1, iLength, file) ;
fclose (file) ;
pstrBuffer[iLength] = '\0' ;
mbstowcs(ptchBuffer,pstrBuffer,iLength+1);
SetWindowText (hWndEdit, ptchBuffer) ;
free (pstrBuffer) ;
free (ptchBuffer) ;
}
}
}
//El siguiente segmento de código da formato reemplazando texto
//normal por texto con formato
memset( &cf, 0, sizeof cf );
//Se limpia la estructura del formato
cf.cbSize = sizeof (CHARFORMAT2); //Se fija el tamaño de la estructura
// Se establece la mascara para que sea posible aplicar color al texto
cf.dwMask = CFM_COLOR; //| CFM_BACKCOLOR ;
cf.crTextColor = RGB(255,0,0);
//Se establece el color del texto
//cf.crBackColor = RGB(0,0,255);
//Se establece un rango de texto a seleccionar
SendMessage( hWndEdit, EM_SETSEL, (WPARAM)5, (LPARAM)9);
//Se aplica el formato al rango seleccionado
SendMessage( hWndEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
//Se reemplaza el rango seleccionado con el nuevo texto y formato
SendMessage( hWndEdit, EM_REPLACESEL, FALSE, (LPARAM) L"cara");
}
break;
case IDM_GUARDAR:
{
TCHAR szFile[MAX_PATH];
ZeroMemory(szFile, MAX_PATH);
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize
= sizeof(OPENFILENAME);
ofn.Flags
= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
OFN_OVERWRITEPROMPT ;
ofn.hwndOwner = hWnd;
ofn.lpstrFilter
= _T("Tipos de formatos
soportados(*.txt)\0*.txt\0Texto (*.txt)\0\0");
ofn.lpstrTitle
= _T("Guardar archivo de texto");
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
if (IDOK == GetSaveFileName(&ofn)){
FILE *file ;
int
iLength ;
PSTR
pstrBuffer ;
char
cFile[MAX_PATH];
TCHAR *ptchBuffer;
Ingeniería en Computación
M. C. J. Jesús Arellano Pimentel
5
wcstombs(cFile,szFile,MAX_PATH);
if (NULL == (file = fopen (cFile, "wb"))){
MessageBox(hWnd,L"Error al crear el archivo", L"Error",
MB_OK | MB_ICONERROR);
}else{
iLength = GetWindowTextLength (hWndEdit) ;
if (NULL == (pstrBuffer = (PSTR) malloc (sizeof(char) *
(iLength+1))) ||
NULL == (ptchBuffer = (TCHAR*) malloc(sizeof(TCHAR)*
(iLength+1))))
{
MessageBox(hWnd,L"Error al reservar memoria",
L"Error", MB_OK | MB_ICONERROR);
fclose (file) ;
}
GetWindowText (hWndEdit, ptchBuffer, iLength+1) ;
wcstombs(pstrBuffer, ptchBuffer, iLength+1);
fwrite (pstrBuffer, 1, iLength+1, file);
fclose (file) ;
free (pstrBuffer) ;
free (ptchBuffer);
}
}
}
break;
El procesamiento del mensaje IDM_ABRIR utiliza una función PopFileLength
función debe definirse previo a la función WndProc con el siguiente código:
(file),
esta
long PopFileLength (FILE *file)
{
int iCurrentPos, iFileLength ;
iCurrentPos = ftell (file) ;
fseek (file, 0, SEEK_END) ;
iFileLength = ftell (file) ;
fseek (file, iCurrentPos, SEEK_SET) ;
return iFileLength ;
}
Paso 8 Guardar todo, compilar y probar.
Guardar todos los cambios, compilar y probar. El resultado deberá ser que cada que se
abra un archivo el texto de la posición 5 a la posición 9 será remplazado por la palabra
cara en color rojo.
4.- Referencias
[Petzold96]
Petzold Charles, et al. Programación en Windows 95. Mc Graw Hill –
Microsoft Press. 1996.
Ingeniería en Computación
M. C. J. Jesús Arellano Pimentel
6
Descargar