27.03.2013 Views

Programación en Windows y MFCs

Programación en Windows y MFCs

Programación en Windows y MFCs

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Programación</strong> <strong>en</strong> <strong>Windows</strong><br />

y <strong>MFCs</strong><br />

Tema 6<br />

Grupo 46<br />

TACC II<br />

Curso 2008/09<br />

1


Indice<br />

<strong>Programación</strong> bajo <strong>Windows</strong>.<br />

Introducción<br />

Introducción.<br />

Hola mundo!.<br />

El API de <strong>Windows</strong>.<br />

Introducción a las <strong>MFCs</strong> <strong>MFCs</strong>.<br />

Arquitectura Docum<strong>en</strong>to/Vista.<br />

Aspectos avanzados de las <strong>MFCs</strong>.<br />

Bibliografía. g<br />

2


<strong>Programación</strong> Bajo <strong>Windows</strong><br />

Proramación ori<strong>en</strong>tada a ev<strong>en</strong>tos ev<strong>en</strong>tos, <strong>en</strong> contraste con la programación<br />

para MS-DOS, que es secu<strong>en</strong>cial.<br />

Ev<strong>en</strong>to: Algo que sucede <strong>en</strong> el sistema (click de ratón ratón, movimi<strong>en</strong>to<br />

de ratón, pulsación de una tecla, etc.)<br />

<strong>Windows</strong> convierte estos ev<strong>en</strong>tos <strong>en</strong> m<strong>en</strong>sajes (añad<strong>en</strong> información<br />

a los ev<strong>en</strong>tos). P.ej.: cuando se hace click con el ratón, el m<strong>en</strong>saje<br />

incluye las coord<strong>en</strong>adas, la v<strong>en</strong>tana sobre la que se pulsó, etc.<br />

<strong>Windows</strong> pasa el m<strong>en</strong>saje a la parte interesada (ej. la v<strong>en</strong>tana sobre<br />

la que se hizo click).<br />

La aplicación puede obviar el m<strong>en</strong>saje, o puede t<strong>en</strong>er código que la<br />

haga reaccionar.<br />

3


<strong>Programación</strong> Bajo <strong>Windows</strong><br />

Estructura g<strong>en</strong>érica de una aplicación windows:<br />

1. Iniciar la aplicación. p<br />

Iniciar la aplicación y la instancia.<br />

En las versiones de 32 bits se inicializa la aplicación cada vez que<br />

se inicializa la instancia.<br />

En las versiones de 16 bits sólo con la 1ª instancia (compartir<br />

información, ahorro memoria).<br />

Todas las aplicaciones ti<strong>en</strong><strong>en</strong> una o más v<strong>en</strong>tanas (hay<br />

excepciones excepciones, como los controladores de dispositivo)<br />

dispositivo).<br />

Clases (tipos) de v<strong>en</strong>tanas definidas mediante parámetros. Registro<br />

de la clase de v<strong>en</strong>tana. Esto se hace al inicializar la aplicación.<br />

Al inicializar la instancia, se crea una v<strong>en</strong>tana de la clase definida.<br />

HHay que ddar el l nombre b dde lla v<strong>en</strong>tana, t sus coord<strong>en</strong>adas, d d<br />

dim<strong>en</strong>siones, m<strong>en</strong>ú, etc.<br />

2. Esperar que llegue algún m<strong>en</strong>saje.<br />

33. Reaccionar ante el m<strong>en</strong>saje recibido recibido.<br />

4. Volver a 2.<br />

4


<strong>Programación</strong> Bajo <strong>Windows</strong><br />

Estructura g<strong>en</strong>érica de una aplicación windows:<br />

1. Iniciar la aplicación.<br />

2. Esperar que llegue algún m<strong>en</strong>saje.<br />

Bucle de captura de m<strong>en</strong>sajes.<br />

Filtrar los m<strong>en</strong>sajes que van a la aplicación, adaptarlos y<br />

hhacerlos l ll llegar a lla v<strong>en</strong>tana t correspondi<strong>en</strong>te. di t<br />

Procedimi<strong>en</strong>to de v<strong>en</strong>tana, recibe m<strong>en</strong>saje y adopta uno u<br />

otro comportami<strong>en</strong>to.<br />

3. Reaccionar ante el m<strong>en</strong>saje recibido.<br />

4. Volver a 2.<br />

5


#include "stdafx.h"<br />

#include <br />

// Crear un proyecto win32 application vacío (o “Hello World” <strong>en</strong> VC 6.0)<br />

LRESULT CALLBACK GGestorM<strong>en</strong>sajes( M j (<br />

{<br />

HANDLE hW hWnd, d<br />

UINT m<strong>en</strong>saje,<br />

WPARAM wParam,<br />

LPARAM lParam)<br />

HDC hDc; // Device context<br />

PAINTSTRUCT ps; // Estructura de dibujado<br />

RECT rect; // Rectángulo cli<strong>en</strong>te<br />

switch (m<strong>en</strong>saje)<br />

{<br />

case WM_PAINT:<br />

hD hDc = BBeginPaint((HWND)hWnd, i P i t((HWND)hW d &ps); & )<br />

Hola Mundo!<br />

GetCli<strong>en</strong>tRect((HWND)hWnd,&rect);<br />

DrawText(hDc, TEXT("¡Hola Mundo!“), -1, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);<br />

EndPaint((HWND)hWnd, &ps);<br />

bbreak; k<br />

case WM_DESTROY:<br />

PostQuitMessage(0);<br />

break;<br />

ddefault: f lt return t DefWindowProc((HWND)hWnd,m<strong>en</strong>saje,wParam,lParam);<br />

D fWi d P ((HWND)hW d j P lP )<br />

}<br />

return (NULL);<br />

}<br />

6


BOOL IniciaAplicacion (HINSTANCE hInstance)<br />

{<br />

WNDCLASS C SS wc;<br />

}<br />

Hola Mundo!<br />

wc.style = CS_HREDRAW | CS_VREDRAW; //Estilo de la clase<br />

wc wc.lpfnWndProc lpfnWndProc = (WNDPROC)GestorM<strong>en</strong>sajes; // Procedimi<strong>en</strong>to gestor<br />

wc.cbClsExtra = 0;<br />

wc.cbWndExtra = 0;<br />

wc.hInstance hI t = hInstance; hI t // Instancia I t i<br />

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Icono de la v<strong>en</strong>tana<br />

wc.hCursor = LoadCursor(NULL, IDC_ARROW); // cursor de la v<strong>en</strong>tana<br />

wc.hbrBackground = (HBRUSH)GetStockObject(WHITE (HBRUSH)GetStockObject(WHITE_BRUSH); BRUSH); // Color de fondo<br />

wc.lpszM<strong>en</strong>uName = NULL; // Nombre del m<strong>en</strong>ú asociado<br />

wc.lpszClassName = TEXT("ClaseV<strong>en</strong>tana“); // Nombre de la clase de la v<strong>en</strong>tana<br />

return (RegisterClass(&wc));<br />

7


BOOL IniciaInstancia(HINSTANCE hInstance, int nCmdShow)<br />

{<br />

HWND hWnd;<br />

Hola Mundo!<br />

hWnd = CreateWindow(<br />

TEXT("ClaseV<strong>en</strong>tana“), // Clase de v<strong>en</strong>tana a la que pert<strong>en</strong>ece (caract. UNICODE)<br />

TEXT("TACC II, grupo 46, curso 2008/09“),// Título de la v<strong>en</strong>tana<br />

WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL, _ | _ | _<br />

// Estilo<br />

CW_USEDEFAULT, // Posicion X por defecto<br />

CW_USEDEFAULT, // Posicion Y por defecto<br />

CW_USEDEFAULT, // Anchura por defecto<br />

CW_USEDEFAULT, // Altura por defecto<br />

NULL, // Sin v<strong>en</strong>tana padre<br />

NULL, // Sin m<strong>en</strong>u<br />

hInstance, // Instancia<br />

NULL);<br />

if (!hWnd) return FALSE;<br />

// Parametros<br />

ShowWindow(hWnd, nCmdShow); // dice cómo mostrar la v<strong>en</strong>tana<br />

UpdateWindow(hWnd);<br />

return TRUE;<br />

// actualiza la v<strong>en</strong>tana: g<strong>en</strong>era un ev<strong>en</strong>to WM_PAINT<br />

}<br />

8


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,<br />

LPSTR lpCmdLine, int nCmdShow)<br />

{<br />

MSG M<strong>en</strong>saje;<br />

BOOL bret;<br />

}<br />

if (!hPrevInstance){<br />

if (!IniciaAplicacion(hInstance)) return FALSE;<br />

}<br />

if (!IniciaInstancia(hInstance, nCmdShow)) return FALSE;<br />

Hola Mundo!<br />

while ((bret = GetMessage(&M<strong>en</strong>saje, NULL, NULL, NULL)) != 0)<br />

{<br />

TranslateMessage(&M<strong>en</strong>saje); // traduce de teclas conv<strong>en</strong>cionales a WM_CHAR<br />

DispatchMessage(&M<strong>en</strong>saje); // hace llegar el m<strong>en</strong>saje al proc. de v<strong>en</strong>tana<br />

}<br />

return (M<strong>en</strong>saje.wParam);<br />

9


La clase de V<strong>en</strong>tana<br />

typedef struct {<br />

UINT style; // combinación de estilos de clase<br />

WNDPROC lpfnWndProc; // Puntero al procedimi<strong>en</strong>to de v<strong>en</strong>tana<br />

int cbClsExtra; // num. bytes extra a asignar seguidos a esta estructura<br />

int cbWndExtra; // num. bytes extra a asignar seguidos a la instancia<br />

HINSTANCE hInstance; // handle a la instancia que conti<strong>en</strong>e el proc. v<strong>en</strong>tana<br />

HICON hIcon; // handle al icono de la clase (si NULL se da uno por def).<br />

HCURSOR hCursor; // handle al cursor de la clase<br />

HBRUSH hbrBackground; // handle a brocha para color de fondo, o un color<br />

LPCTSTR lpszM<strong>en</strong>uName; // nombre del m<strong>en</strong>ú asociado<br />

LPCTSTR lpszClassName; // nombre de la clase de v<strong>en</strong>tana<br />

} WNDCLASS, *PWNDCLASS;<br />

Tipos de clases de v<strong>en</strong>tana: del sistema (ej.: BUTTON, COMBOBOX,<br />

etc etc.), ) globales y locales de aplicación aplicación.<br />

Algunos estilos: CS_HREDRAW, CS_VREDRAW (redibuja la v<strong>en</strong>ta<br />

<strong>en</strong>tera si hay un cambio de tamaño horizontal), CS_NOCLOSE,.<br />

La estructura WNDCLASSEX permite asociar un icono pequeño a la<br />

v<strong>en</strong>tana (RegisterClassEx).<br />

10


Inicialización de la Instancia<br />

HWND CreateWindow(<br />

LPCTSTR lpClassName, // nombre registrado clase de v<strong>en</strong>tana<br />

LPCTSTR lpWindowName, // título de la v<strong>en</strong>tana<br />

DWORD dwStyle, // estilo de la v<strong>en</strong>tana<br />

iint t x, // posición i ió hhorizontal i t l dde lla v<strong>en</strong>tana t<br />

int y, // posición vertical de la v<strong>en</strong>tana<br />

int nWidth, // anchura de v<strong>en</strong>tana<br />

int nHeight nHeight, // altura de v<strong>en</strong>tana<br />

HWND hWndPar<strong>en</strong>t, // handle de la v<strong>en</strong>tana padre<br />

HMENU hM<strong>en</strong>u, // handle del m<strong>en</strong>ú de v<strong>en</strong>tana<br />

HINSTANCE hInstance hInstance, // handle a la instancia de la aplicación<br />

LPVOID lpParam ); // puntero a parámetros.<br />

CCreación ió dde una v<strong>en</strong>tana t dde una clase l registrada. i t d<br />

CreateWindowEx para estilos ext<strong>en</strong>didos (ej.: layered<br />

windows-> windows v<strong>en</strong>tanas no rectangulares o que cambian de<br />

forma)<br />

11


Estilos de V<strong>en</strong>tana<br />

WS_BORDER: v<strong>en</strong>tana con borde fino.<br />

WS_CAPTION: v<strong>en</strong>tana con barra de título (incluye WS_BORDER).<br />

WS WS_CHILD, CHILD WS WS_CHILDWINDOW CHILDWINDOW : v<strong>en</strong>tana t hij hija ( (no puede d tt<strong>en</strong>er m<strong>en</strong>ú ú ni i puede d usarse con<br />

WS_POPUP).<br />

WS_CLIPCHILDREN: Excluye el área ocupada por las v<strong>en</strong>tanas hijas cuando se dibuja e la padre.<br />

Se usa cuando se crea la v<strong>en</strong>tana padre.<br />

WS WS_CLIPSIBLINGS:<br />

CLIPSIBLINGS:<br />

WS_DISABLED: crea una v<strong>en</strong>tana deshabilitada.<br />

WS_DLGFRAME: v<strong>en</strong>tana con borde igual al de las cajas de diálogo.<br />

WS_GROUP: Primer control de un grupo.<br />

WS_HSCROLL: v<strong>en</strong>tana con scrooll horizonta.<br />

WS_ICONIC, WS_MINIMIZE: v<strong>en</strong>tana inicialm<strong>en</strong>te minimizada.<br />

WS_MAXIMIZE: v<strong>en</strong>tana inicialm<strong>en</strong>te maximizada.<br />

WS_MAXIMIZEBOX, _ , WS_MINIMIZEBOX _<br />

: v<strong>en</strong>tana con botón de maximizar/minimizar.<br />

WS_OVERLAPPED, WS_TILED; v<strong>en</strong>tana con título y borde.<br />

WS_OVERLAPPEDWINDOW, WS_TILEDWINDOW: v<strong>en</strong>tana con estilos: WS_OVERLAPPED,<br />

WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, y<br />

WS_MAXIMIZEBOX<br />

WS_POPUP: v<strong>en</strong>tana de pop-up.<br />

WS_POPUPWINDOW : v<strong>en</strong>tana de pop-up con WS_BORDER, WS_POPUP, y WS_SYSMENU<br />

WS_SIZEBOX, WS_THICKFRAME: v<strong>en</strong>tana con borde redim<strong>en</strong>sionable.<br />

WSS_S SYSMENU: S U v<strong>en</strong>tana e ta a co con m<strong>en</strong>ú e ú de sste sistema. a<br />

WS_TABSTOP: control que recibe el foco cuando se pulsa TAB.<br />

WS_VISIBLE: v<strong>en</strong>tana inicialm<strong>en</strong>te visible.<br />

12<br />

WS_VSCROLL: v<strong>en</strong>tana con barra de desplazami<strong>en</strong>to vertical.


Estilos de V<strong>en</strong>tana<br />

M<strong>en</strong>ú de sistema Barra de título Botones minimizar/<br />

maximizar/cerrar<br />

Area cli<strong>en</strong>te<br />

Scroll horizontal Scroll vertical<br />

borde<br />

13


M<strong>en</strong>sajes<br />

MM<strong>en</strong>sajes: j<br />

typedef struct<br />

{<br />

HWND hwnd; // handle a la v<strong>en</strong>tana que recibe el m<strong>en</strong>saje<br />

UINT message; // id<strong>en</strong>tificador del m<strong>en</strong>saje<br />

WPARAM wParam; // info adicional, dep<strong>en</strong>di<strong>en</strong>te del tipo de m<strong>en</strong>saje<br />

LPARAM lParam; // info adicional, dep<strong>en</strong>di<strong>en</strong>te del tipo de m<strong>en</strong>saje<br />

DWORD time; ; // instante <strong>en</strong> el que q el m<strong>en</strong>saje j fue <strong>en</strong>viado<br />

POINT pt; // posición del cursor <strong>en</strong> coord<strong>en</strong>adas de pantalla<br />

} MSG, *PMSG;<br />

Todos los m<strong>en</strong>sajes que <strong>en</strong>vía windows empiezan<br />

por WM WM_XXX XXX y están definidos <strong>en</strong> windows windows.h<br />

h<br />

14


GetMessage<br />

GetMessage: Espera a que llegue un m<strong>en</strong>saje m<strong>en</strong>saje.<br />

BOOL GetMessage( LPMSG lpMsg, HWND hWnd,<br />

UINT wMsgFilterMin, UINT wMsgFilterMax );<br />

lpMsg: Puntero a la estructura MSG que recibe el m<strong>en</strong>saje<br />

hWnd: Handle de la v<strong>en</strong>tana que recibe los m<strong>en</strong>sajes.<br />

wMsgFilterMin: M<strong>en</strong>or valor <strong>en</strong>tero del m<strong>en</strong>saje a recibir (ej.:<br />

WM_KEYFIRST, WM_MOUSEFIRST o WM_INPUT)<br />

wMsgFilterMax: Mayor valor <strong>en</strong>tero del m<strong>en</strong>saje a recibir (ej.:<br />

WM_KEYFIRST, WM_MOUSEFIRST o WM_INPUT)<br />

Retorno:<br />

Si se devuelve un m<strong>en</strong>saje distinto de WM_QUIT, el valor es distinto de cero.<br />

Si el m<strong>en</strong>saje es WM_QUIT, el valor es cero.<br />

Si hay un error el valor es -1. Por ejemplo, esto sucede si hWnd es un handle<br />

de v<strong>en</strong>tana inválida o lpWnd es un puntero inválido inválido.<br />

15


DispatchMessage<br />

MSG<br />

…<br />

hwnd=h<br />

…<br />

hinstance=h<br />

lpClassName = CN<br />

WNDCLASS<br />

…<br />

lpszClassName = CN<br />

…<br />

lpfnWndProc=proc<br />

DispatchMessage<br />

…<br />

hinstance=h1<br />

lpClassName = CN<br />

…<br />

hinstance=h2<br />

lpClassName = CN2<br />

…<br />

lpszClassName = CN2<br />

…<br />

lpfnWndProc=proc2<br />

instancias de v<strong>en</strong>tana<br />

…<br />

hinstance=h3<br />

lpClassName=CN3<br />

…<br />

lpszClassName = CN3<br />

…<br />

lpfnWndProc=proc3<br />

lpfnWndProc proc lpfnWndProc proc2 lpfnWndProc proc3<br />

clases de v<strong>en</strong>tana registradas<br />

LRESULT CALLBACK proc (HANDLE LRESULT CALLBACK proc2 LRESULT CALLBACK proc3<br />

hWnd, UINT m<strong>en</strong>saje, WPARAM (HANDLE hWnd, UINT (HANDLE hWnd, UINT<br />

wParam, LPARAM lParam){..}<br />

m<strong>en</strong>saje, WPARAM wParam, m<strong>en</strong>saje, WPARAM wParam, 16<br />

LPARAM lParam){..}<br />

LPARAM lParam){..}


Handles<br />

Un id<strong>en</strong>tificador para los distintos objetos: v<strong>en</strong>tanas v<strong>en</strong>tanas,<br />

controles (que son v<strong>en</strong>tanas), ficheros, imág<strong>en</strong>es,<br />

memoria, etc.<br />

Similar a punteros: se obti<strong>en</strong><strong>en</strong> y luego se destruy<strong>en</strong>.<br />

17


Gestionar un nuevo ev<strong>en</strong>to<br />

LRESULT CALLBACK GestorM<strong>en</strong>sajes( HANDLE hWnd, hWnd<br />

UINT m<strong>en</strong>saje,<br />

WPARAM wParam,<br />

LPARAM lParam)<br />

{<br />

HDC hDc; // Device context<br />

//…<br />

switch (m<strong>en</strong>saje)<br />

{<br />

case WM_LBUTTONDOWN:<br />

MessageBox((HWND)hWnd, TEXT("Button click"), TEXT("dialogo"), MB_ICONHAND);<br />

break;<br />

default: return DefWindowProc((HWND)hWnd,m<strong>en</strong>saje,wParam,lParam);<br />

}<br />

return (NULL);<br />

}<br />

18


Juegos de Caracteres<br />

~1890: 1890 BCDIC (6 bit bits->64 64 caracteres). t )<br />

~1950: ASCII (7 ( bits->128 caracteres). )<br />

ASCII ext<strong>en</strong>dido (8 bits->256 caracteres).<br />

páginas páginas de códigos regionales para los últimos<br />

128.<br />

DBCS: DBCS: los primeros 128 bytes igual que<br />

ASCII, los posteriores ocupan dos bytes.<br />

U Unicode: i d 16 bit bits (65536 caracteres). t )<br />

Sistema de doble anchura (wide char).<br />

19


Caracteres Unicode<br />

Tipo de datos wchar_t.<br />

Ej.: j wchar_t _ nombre[50]=L”Bjarne [ ] j Stroustrup”. p<br />

Mejor usar macros, que aseguran que el<br />

programa funciona <strong>en</strong> Unicode o ASCII:<br />

TCHAR * Nombre = TEXT(“Hola”);<br />

20


La Notación Húngara<br />

Conv<strong>en</strong>ción para los nombres de variables (uso de prefijos), de tal<br />

manera que al leerlos sepamos su tipo.<br />

Después del prefijo se empieza por mayúsculas.<br />

Ejemplo:<br />

hWnd es un handle (h) a una v<strong>en</strong>tana.<br />

lpfnWndProc es un puntero (p) largo (l) a una función (fn).<br />

Tipo de Dato Prefijo<br />

char c<br />

BYTE(unsigned char) by<br />

short n<br />

int i<br />

int cuando indica coord<strong>en</strong>adas x, y<br />

int cuando indica dim<strong>en</strong>siones cx, cyy<br />

WORD (unsigned int) w<br />

LONG (long) l<br />

Tipo de Dato Prefijo<br />

DWORD(unsigned long) dw<br />

BOOL(int) o Flag b ó f<br />

Handle h<br />

Puntero p<br />

Función fn<br />

Cad<strong>en</strong>a s<br />

Cad<strong>en</strong>a terminada <strong>en</strong> ‘\0’ sz


El API de <strong>Windows</strong><br />

Llamadas al sistema operativo operativo, almac<strong>en</strong>adas <strong>en</strong> DLLs DLLs.<br />

Win32, WinSock, WinInet, ODBC, etc.<br />

D<strong>en</strong>tro de Win32 se <strong>en</strong>globan como ext<strong>en</strong>siones el resto de las API<br />

que se puedan añadir a <strong>Windows</strong>.<br />

Win32 proprociona un <strong>en</strong>torno de programación común a la<br />

plataforma <strong>Windows</strong>: 3.1 (win32s), 95/98, NT4.0, 2000, CE, XP,<br />

Vista Vista.<br />

En algunas plataformas el win32 (p. ej. CE) no está implem<strong>en</strong>tada<br />

<strong>en</strong> su totalidad totalidad.<br />

Win32: CreateWindow(), RegisterClass(), ShowWindow(),<br />

UpdateWindow() UpdateWindow(), DrawText() DrawText(), etc etc.<br />

22


Win32<br />

Varias categorías de funciones:<br />

Administración de v<strong>en</strong>tanas (<strong>en</strong> user32.dll)<br />

Crear y administrar la GUI, despachar m<strong>en</strong>sajes, administrar<br />

v<strong>en</strong>tanas v<strong>en</strong>tanas, DDE. DDE<br />

Ej.: CreateWindow(), RegisterClass(), ShowWindow()<br />

Graphics Device Interface (GDI).<br />

GG<strong>en</strong>erar salidas lid <strong>en</strong> di distintos ti t di dispositivos: iti pantalla, t ll iimpresora. PP.ej.: j<br />

dibujar objetos.<br />

Ej.: BeginPaint(), GetCli<strong>en</strong>tRect(), DrawText(), EndPaint().<br />

MMedia di Control C t l Interface I t f (MCI) (MCI).<br />

Reproducir y Grabar Audio, uso de vídeo, control de dispositivos<br />

multimedia.<br />

SServicios i i ddel l Si Sistema. t<br />

Administración de memoria, archivos y procesos, funciones de trabajo<br />

<strong>en</strong> red, información del sistema, IPC.<br />

Remote Procedure Call (RPC).<br />

23


Bibliotecas de Ext<strong>en</strong>sión<br />

Proporcionan P i servicios i i a llas apliciones li i<br />

fuera del ámbito del Win32.<br />

Controles comunes.<br />

Cuadros de diálogo comunes.<br />

Descompresión de datos.<br />

Administración de intercambio dinámico de<br />

datos (DDE).<br />

Instalación de archivos.<br />

Intercambio dinámico de datos sobre redes.<br />

...<br />

24


Indice<br />

<strong>Programación</strong> bajo <strong>Windows</strong>.<br />

Introducción a las <strong>MFCs</strong> <strong>MFCs</strong>.<br />

Introducción.<br />

V<strong>en</strong>tana V<strong>en</strong>tana vacía sin el wizard wizard.<br />

Uso del wizard.<br />

Un Un vistazo a las clases de MFC MFC.<br />

Mapas de M<strong>en</strong>sajes.<br />

M<strong>en</strong>ús M<strong>en</strong>ús y Teclas Aceleradoras<br />

Aceleradoras.<br />

Diálogos Comunes.<br />

Controles.<br />

Controles.<br />

Clases de utilidad<br />

Arquitectura Docum<strong>en</strong>to/Vista.<br />

Aspectos avanzados de las <strong>MFCs</strong>.<br />

Bibliografía.<br />

25


Microsoft Foundation Classes<br />

El API para lla programación ió di directa dde aplicaciones li i Wi <strong>Windows</strong> d dda<br />

acceso total a la funcionalidad del sistema operativo, pero es de<br />

bajo nivel.<br />

MFC es un framework que ofrece una serie de funciones,<br />

constantes constantes, tipos de datos y clases que simplifica la creación de<br />

aplicaciones para las distintas plataformas <strong>Windows</strong>.<br />

Es la respuesta de Microsoft a frameworks de otras compañias<br />

como OWL de Borland.<br />

Visual C++ conti<strong>en</strong>e un asist<strong>en</strong>te (wizard) que facilita la creación de<br />

aplicaciones MFC (g<strong>en</strong>eración de código).<br />

26


Clases Básicas para la creación de v<strong>en</strong>tanas<br />

27


Secu<strong>en</strong>cia de Creación de una Aplicación<br />

28


Creación de una<br />

V<strong>en</strong>tana <strong>en</strong> Blanco sin<br />

el l wizard i d<br />

#include "stdafx.h"<br />

#i #include l d < f i h> // MFC core and d standard t d d compon<strong>en</strong>ts t Creación de una<br />

#include // MFC ext<strong>en</strong>sions<br />

// proyecto con Shared DLL<br />

#ifdef _DEBUG<br />

#define new DEBUG DEBUG_NEW NEW<br />

#<strong>en</strong>dif<br />

class CMainFrame : public CFrameWnd {<br />

public: p<br />

CMainFrame() { Create(NULL, _T("Hellow World Application")); } // suele ir <strong>en</strong> OnCreate()<br />

}; // se suele llamar a LoadFrame<br />

class HelloWorldApp : public CWinApp {<br />

public:<br />

virtual i t l BOOL IInitInstance(); itI t ()<br />

};<br />

HelloWorldApp theApp; // Declarar un unico objecto CWinApp<br />

BOOL HelloWorldApp::InitInstance()<br />

{<br />

CWinApp::InitInstance();<br />

SetRegistryKey(_T("Hello g y y(_ ( World Application"));<br />

pp ))<br />

CMainFrame* pFrame = new CMainFrame;<br />

if (!pFrame) return FALSE;<br />

m_pMainWnd = pFrame;<br />

pFrame->ShowWindow(SW_SHOW);<br />

pFrame->UpdateWindow();<br />

F U d t Wi d ()<br />

return TRUE;<br />

}<br />

//NOTA: El WinMain está d<strong>en</strong>tro del framework <strong>MFCs</strong><br />

29


Uso del Asist<strong>en</strong>te<br />

Configuración Inicial de la Aplicación<br />

File/new Project; seleccionar MFC Application<br />

30


Uso del Asist<strong>en</strong>te<br />

Configuración Inicial de la Aplicación<br />

Configurar el tipo de<br />

aplicación:<br />

•Single docum<strong>en</strong>t<br />

•Sin soporte de<br />

arquitectura<br />

Docum<strong>en</strong>to/Vista<br />

Docum<strong>en</strong>to/Vista.<br />

•MFC <strong>en</strong> librería estática<br />

(incluye <strong>en</strong> el exe las<br />

DLLs necesarias)<br />

31


Uso del Asist<strong>en</strong>te<br />

Configuración Inicial de la Aplicación<br />

Configurar el soporte para BBDD<br />

32


Uso del Asist<strong>en</strong>te<br />

Configuración Inicial de la Aplicación<br />

Configurar la interfaz de usuario<br />

33


Uso del Asist<strong>en</strong>te<br />

Configuración Inicial de la Aplicación<br />

Configurar nombre de las clases y de los ficheros que se van a g<strong>en</strong>erar<br />

34


Uso del Asist<strong>en</strong>te<br />

Aplicación G<strong>en</strong>erada<br />

35


Uso del Asist<strong>en</strong>te<br />

¿Qué ficheros se han g<strong>en</strong>erado?<br />

• DDefinición fi i ió dde nombres b dde llos<br />

recursos, para<br />

poder ser usados por la aplicación.<br />

Fichero de recursos (.rc ( y .rc2). )<br />

Clase de la v<strong>en</strong>tana de trabajo (hereda de CWnd),<br />

d<strong>en</strong>tro de la v<strong>en</strong>tana marco<br />

Clase Aplicación (hereda de CWinApp)<br />

Clase de la v<strong>en</strong>tana marco (hereda de CFrameWnd)<br />

• Cabeceras precompiladas. “stdafx.h” incluye las<br />

cabeceras comunes del sistema sistema. Se ha de incluir<br />

antes que cualquier otra<br />

36


Uso del Asist<strong>en</strong>te<br />

Recursos de la Aplicación<br />

Resource.h<br />

#define IDD_ABOUTBOX 100<br />

#define IDP_OLE_INIT_FAILED 100<br />

#define IDR_MAINFRAME IDR MAINFRAME 128<br />

#define IDR_Hello<strong>MFCs</strong>TYPE 129<br />

37


Uso del Asist<strong>en</strong>te<br />

Estructura de la Aplicación<br />

Wi WinMain(): M i ()<br />

D<strong>en</strong>tro del framework.<br />

Se llama a métodos miembros del único objeto de tipo CWinApp:<br />

InitApplication(): Normalm<strong>en</strong>te no hay que tocar este método.<br />

InitInstance(): Tareas g<strong>en</strong>erales de la aplicación, ej: inicializar OLE.<br />

Después se crean las v<strong>en</strong>tanas de la aplicación, y se hac<strong>en</strong> visibles<br />

(ShowWindow())<br />

Run(): Que implem<strong>en</strong>ta al bucle de m<strong>en</strong>sajes hasta que llega WM_QUIT.<br />

CWinApp:<br />

Clase que hay que subclasificar, se debe crear un objeto único global.<br />

Procesa m<strong>en</strong>sajes hasta que llega WM_QUIT, mom<strong>en</strong>to <strong>en</strong> el que<br />

ejecuta ExitInstance() por defecto defecto.<br />

Si no hay m<strong>en</strong>sajes, llama a onIdle(), vacía por defecto.<br />

38


Seccu<strong>en</strong>ccia<br />

dee<br />

Creaciónn<br />

de<br />

unaa<br />

Apliicacióón<br />

39


Uso del Asist<strong>en</strong>te<br />

Estructura de la Aplicación: La clase v<strong>en</strong>tana (CWnd)<br />

CCasi i ttodas d llas aplicaciones li i ti ti<strong>en</strong><strong>en</strong> una o más á v<strong>en</strong>tanas. t<br />

La clase base es CWnd.<br />

Conti<strong>en</strong>e un handle a la v<strong>en</strong>tana física de <strong>Windows</strong>.<br />

La v<strong>en</strong>tana física se crea mediante Create(), se destruye con el<br />

destructor de la subclase de CWnd. Parámetros de Create():<br />

lpszClassName: nombre de la clase registrada con<br />

AfxRegisterWindowClass() o NULL (atributos por defecto).<br />

lpszWindowName: nombre de la v<strong>en</strong>tana.<br />

dwStyle: Estilo de la v<strong>en</strong>tana a crear.<br />

rect: Refer<strong>en</strong>cia a un objeto constante de tipo RECT, para indicar<br />

posición y tamaño de la v<strong>en</strong>tana.<br />

pPar<strong>en</strong>tWindow: puntero al objecto CWnd padre de la v<strong>en</strong>tana. No<br />

puede d ser NULL NULL. Si lla v<strong>en</strong>tana es lla principal, i i l usar<br />

CreateWindowEx().<br />

nId: Id<strong>en</strong>tificador de la v<strong>en</strong>tana.<br />

pContext: C t t PPuntero t a un objeto bj t dde ti tipo CC CCreateContext, t C t t para<br />

asociar vistas y docum<strong>en</strong>tos a la v<strong>en</strong>tana, puede ser NULL.<br />

40


Uso del Asist<strong>en</strong>te<br />

Estructura de la Aplicación: La clase v<strong>en</strong>tana (CWnd)<br />

CW CWndd agrupa acciones i que se podían dí realizar li sobre b v<strong>en</strong>tanas. t<br />

Las hace más accesibles y seguras.<br />

Evita por p ejemplo j p t<strong>en</strong>er qque ppasar el handle como primer p parámtero p<br />

(almac<strong>en</strong>ado <strong>en</strong> el atributo m_hWnd).<br />

Ejemplo:<br />

los métodos de CWnd:<br />

void CWnd::MoveWindow( int x, int y,<br />

int nWidth, int nHeight,<br />

BOOL bRepaint = TRUE );<br />

void CWnd::MoveWindow( LPCRECT lpRect,<br />

BOOL bRepaint = TRUE );<br />

<strong>en</strong>capsulan la llamada a la API de <strong>Windows</strong>:<br />

BOOL MoveWindow( HWND hWnd, int X, int Y,<br />

int nWidth, int nHeight,<br />

BOOL bRepaint);<br />

41


Uso del Asist<strong>en</strong>te<br />

Estructura de la Aplicación: La clase CFrameWnd<br />

HHereda d dde CW CWnd, d es utilizado tili d <strong>en</strong> aplicaciones li i SDI SDI.<br />

Ti<strong>en</strong>e <strong>en</strong> su interior una v<strong>en</strong>tana hija que normalm<strong>en</strong>te será la v<strong>en</strong>tana<br />

principal de la aplicación.<br />

La v<strong>en</strong>tana <strong>en</strong>tana marco interacciona con el usuario s ario cambiando el tamaño tamaño,<br />

moviéndose, etc., y gestiona estos cambios provocando modificaciones <strong>en</strong><br />

la v<strong>en</strong>tana hija.<br />

Para crear una v<strong>en</strong>tana marco:<br />

Create(),<br />

LoadFrame(), que toma m<strong>en</strong>os parámetros. Toma valores por defecto<br />

de los recursos que se le pasan como parámetros: m<strong>en</strong>ú m<strong>en</strong>ú, título título, icono y<br />

tabla de teclas acelaradoras.<br />

virtual BOOL LoadFrame( UINT nIDResource,<br />

DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,<br />

CWnd* pPar<strong>en</strong>tWnd = NULL, CCreateContext* pContext = NULL );<br />

Se destruye llamando a DestroyWindow().<br />

Sus clases derivadas deb<strong>en</strong> declarar DECLARE DECLARE_DYNCREATE() DYNCREATE() (gestión<br />

dinámica de clases) si se usa la arquitectura docum<strong>en</strong>to/vista, y poner<br />

IMPLEMENT_DYNCREATE() <strong>en</strong> la implem<strong>en</strong>tación.<br />

42


Uso del Asist<strong>en</strong>te<br />

Handles<br />

Las clases de la MFC ocultan los handles (CWnd::m_hWnd), para facilitar<br />

su uso uso.<br />

Se pued<strong>en</strong> construir objetos a partir de elem<strong>en</strong>tos gráficos ya construidos:<br />

static CWnd* PASCAL FromHandle( HWND hWnd ) );<br />

El objeto devuelto es temporal (eliminado <strong>en</strong> próxima llamada a OnIdle()).<br />

Clases que <strong>en</strong>capsulan handles a objetos gráficos:<br />

Elem<strong>en</strong>to Gráfico Clase de Objeto<br />

HWND CWnd y derivadas<br />

HDC CDC y derivadas<br />

HMENU CM<strong>en</strong>u<br />

HPEN, HBRUSH, HFONT, HBITMAP,<br />

HPALETTE, HRGN<br />

CGdiObject<br />

HIMAGELIST CImageList<br />

SOCKET CSocket<br />

43


Uso del Asist<strong>en</strong>te<br />

¿Dónde está el bucle de ev<strong>en</strong>tos?<br />

Tabla con los elem<strong>en</strong>tos a manejar: el mapa de m<strong>en</strong>sajes.<br />

Mediante Macros, normalm<strong>en</strong>te insertadas por el asist<strong>en</strong>te.<br />

Declaración del mapa de m<strong>en</strong>sajes <strong>en</strong> la clase:<br />

DECLARE DECLARE_MESSAGE_MAP().<br />

MESSAGE MAP().<br />

Declaramos también los métodos que manejarán los m<strong>en</strong>sajes<br />

mediante afx_msg:<br />

class CMainFrame : public CFrameWnd {<br />

public: CMainFrame();<br />

protected:<br />

DECLARE DECLARE_DYNAMIC(CMainFrame)<br />

DYNAMIC(CM i F )<br />

// Funciones de asignación de m<strong>en</strong>sajes g<strong>en</strong>eradas<br />

protected:<br />

}; }<br />

afx afx_msg msg int OnCreate(LPCREATESTRUCT lpCreateStruct);<br />

afx_msg void OnSetFocus(CWnd *pOldWnd);<br />

DECLARE_MESSAGE_MAP()<br />

44


Uso del Asist<strong>en</strong>te<br />

¿Dónde está el bucle de ev<strong>en</strong>tos?<br />

Una vez declarado, , hay y que q definir el mapa p de m<strong>en</strong>sajes, j , y<br />

<strong>en</strong>lazar<br />

cada m<strong>en</strong>saje con la función que la va a procesar.<br />

En el fichero de implem<strong>en</strong>tación (.cpp) se añade:<br />

BEGIN_MESSAGE_MAP()<br />

//{{AFX_MSG_MAP(CMainFrame)<br />

ON_WM_CREATE() M<strong>en</strong>sajes que<br />

ON_WM_SETFOCUS() se van a tratar<br />

//}}AFX //}}AFX_MSG_MAP MSG MAP<br />

END_MESSAGE_MAP()<br />

Usado por versiones<br />

anteriores de Visual C++ C<br />

LLos m<strong>en</strong>sajes j no refer<strong>en</strong>ciados f i d <strong>en</strong> lla ttabla bl se pasan a lla clase l<br />

padre (o a la clase de la v<strong>en</strong>tana cont<strong>en</strong>edora), y así sucesivam<strong>en</strong>te<br />

hasta que se trate por algún ancestro.<br />

45


Uso del Asist<strong>en</strong>te<br />

Código G<strong>en</strong>erado: Hello<strong>MFCs</strong>.h<br />

// Hello<strong>MFCs</strong>.h: Hello<strong>MFCs</strong> h: archivo de <strong>en</strong>cabezado principal para la aplicación Hello<strong>MFCs</strong><br />

#pragma once<br />

#ifndef __AFXWIN_H__<br />

#error "incluir incluir 'stdafx stdafx.h h' antes de incluir este archivo para PCH" PCH<br />

#<strong>en</strong>dif<br />

#include "resource.h" // Símbolos principales<br />

class CHello<strong>MFCs</strong>App : public CWinApp {<br />

public: CHello<strong>MFCs</strong>App();<br />

// Reemplazos<br />

public:<br />

virtual BOOL InitInstance();<br />

// Implem<strong>en</strong>tación<br />

public:<br />

};<br />

afx_msg void OnAppAbout();<br />

DECLARE DECLARE_MESSAGE_MAP()<br />

MESSAGE MAP()<br />

extern CHello<strong>MFCs</strong>App theApp;<br />

46


#include "stdafx.h"<br />

#include "Hello<strong>MFCs</strong>.h"<br />

#include "MainFrm.h“<br />

#ifdef _DEBUG DEBUG Uso del Asist<strong>en</strong>te<br />

#define new DEBUG_NEW<br />

#<strong>en</strong>dif<br />

Código G<strong>en</strong>erado: Hello<strong>MFCs</strong>.cpp (i)<br />

BEGIN_MESSAGE_MAP(CHello<strong>MFCs</strong>App, CWinApp)<br />

ON_COMMAND(ID_APP_ABOUT, &CHello<strong>MFCs</strong>App::OnAppAbout)<br />

END_MESSAGE_MAP()<br />

CHello<strong>MFCs</strong>App::CHello<strong>MFCs</strong>App() {<br />

// TODO: agregar aquí el código de construcción, Colocar toda la inicialización importante <strong>en</strong> InitInstance }<br />

CHello<strong>MFCs</strong>App theApp; // El único objeto CHello<strong>MFCs</strong>App<br />

// Inicialización de CHello<strong>MFCs</strong>App<br />

BOOL CHello<strong>MFCs</strong>App::InitInstance() {<br />

}<br />

INITCOMMONCONTROLSEX InitCtrls;<br />

InitCtrls.dwSize = sizeof(InitCtrls);<br />

InitCtrls.dwICC = ICC_WIN95_CLASSES;<br />

InitCommonControlsEx(&InitCtrls);<br />

CWinApp::InitInstance();<br />

if (!AfxOleInit()) {// Inicializar bibliotecas OLE<br />

AfxMessageBox(IDP_OLE_INIT_FAILED);<br />

return FALSE; }<br />

AfxEnableControlContainer();<br />

SetRegistryKey( g y y(_ T("Aplicaciones ( p gg<strong>en</strong>eradas con el Asist<strong>en</strong>te ppara aplicaciones p local")); ));<br />

CMainFrame* pFrame = new CMainFrame;<br />

if (!pFrame) return FALSE;<br />

m_pMainWnd = pFrame;<br />

// Crear y cargar el marco con sus recursos<br />

pFrame pFrame->LoadFrame(IDR_MAINFRAME, >LoadFrame(IDR MAINFRAME WS WS_OVERLAPPEDWINDOW OVERLAPPEDWINDOW | FWS FWS_ADDTOTITLE, ADDTOTITLE NULL NULL,NULL); NULL);<br />

pFrame->ShowWindow(SW_SHOW); // Se ha inicializado la única v<strong>en</strong>tana; mostrarla y actualizarla<br />

pFrame->UpdateWindow();<br />

return TRUE;<br />

47


Cuadro de diálogo CAboutDlg utilizado<br />

// para el comando Acerca de<br />

class CAboutDlg : public Cdialog {<br />

public: CAboutDlg();<br />

// Datos del cuadro de diálogo<br />

<strong>en</strong>um { IDD = IDD_ABOUTBOX };<br />

protected:<br />

Uso del Asist<strong>en</strong>te<br />

Código G<strong>en</strong>erado: Hello<strong>MFCs</strong>.cpp (ii)<br />

virtual void DoDataExchange(CDataExchange* g ( g p pDX); ); // Compatibilidad p con DDX/DDV<br />

// Implem<strong>en</strong>tación<br />

protected:<br />

DECLARE_MESSAGE_MAP()<br />

};<br />

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) {}<br />

void CAboutDlg::DoDataExchange(CDataExchange* g g ( g p pDX) ) {<br />

CDialog::DoDataExchange(pDX);<br />

}<br />

BEGIN_MESSAGE_ MAP(CAboutDlg, ( g, CDialog) g)<br />

END_MESSAGE_MAP()<br />

// Comando de la aplicación para ejecutar el cuadro de diálogo<br />

void CHello<strong>MFCs</strong>App::OnAppAbout() pp pp () {<br />

CAboutDlg aboutDlg;<br />

aboutDlg.DoModal();<br />

}<br />

48


#pragma once<br />

#include "ChildView ChildView.h h"<br />

Uso del Asist<strong>en</strong>te<br />

Código G<strong>en</strong>erado: MainFrm.h (i)<br />

class CMainFrame : public CFrameWnd {<br />

Permite acceder a información <strong>en</strong> tiempo de<br />

public: CMainFrame();<br />

ejecución a la clase (puede usarse la macro<br />

protected: DECLARE_DYNAMIC(CMainFrame)<br />

DECLARE DYNAMIC(CMainFrame)<br />

RUNTIME RUNTIME_CLASS CLASS <strong>en</strong> lla arquitectura it t<br />

// Reemplazos<br />

docum<strong>en</strong>to/vista)<br />

public:<br />

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);<br />

virtual BOOL OnCmdMsg(UINT nID, nID int nCode, nCode void void* pExtra pExtra, AFX AFX_CMDHANDLERINFO CMDHANDLERINFO* pHandlerInfo);<br />

// Implem<strong>en</strong>tación<br />

public:<br />

virtual ~CMainFrame();<br />

#ifdef _DEBUG DEBUG<br />

virtual void AssertValid() const;<br />

virtual void Dump(CDumpContext& dc) const;<br />

#<strong>en</strong>dif<br />

protected: // Miembros incrustados de la barra de control<br />

CStatusBar m_wndStatusBar;<br />

CToolBar m_wndToolBar;<br />

CChildView mm_wndView; wndView;<br />

// Funciones de asignación de m<strong>en</strong>sajes g<strong>en</strong>eradas<br />

protected:<br />

afx afx_msg msg int OnCreate(LPCREATESTRUCT lpCreateStruct);<br />

afx_msg void OnSetFocus(CWnd *pOldWnd);<br />

DECLARE_MESSAGE_MAP()<br />

};<br />

49


#include "stdafx.h"<br />

#include "Hello<strong>MFCs</strong>.h“<br />

#include "MainFrm.h“<br />

#ifdef _DEBUG<br />

#define new DEBUG DEBUG_NEW NEW<br />

#<strong>en</strong>dif<br />

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)<br />

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)<br />

ON_WM_CREATE()<br />

ON_WM_SETFOCUS()<br />

END_MESSAGE_MAP()<br />

Uso del Asist<strong>en</strong>te<br />

Código G<strong>en</strong>erado: MainFrm.cpp (i)<br />

static UINT indicators[] = {ID {ID_SEPARATOR, SEPARATOR, ID ID_INDICATOR_CAPS, INDICATOR CAPS, ID_INDICATOR_NUM, ID INDICATOR NUM, ID ID_INDICATOR_SCRL, INDICATOR SCRL, };<br />

// Construcción y destrucción de CMainFrame<br />

CMainFrame::CMainFrame() {// TODO: agregar aquí el código de inicialización de miembros }<br />

CMainFrame::~CMainFrame() { }<br />

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)<br />

{<br />

if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;<br />

// Crear una vista para ocupar el área de cli<strong>en</strong>te del marco<br />

if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) {<br />

TRACE0("No se pudo crear la v<strong>en</strong>tana de vista\n");<br />

return -1; }<br />

if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP<br />

| CBRS_ GRIPPER | CBRS_ TOOLTIPS | CBRS_ FLYBY | CBRS_SIZE_ DYNAMIC) )|| ||<br />

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) {<br />

TRACE0("No se pudo crear la barra de herrami<strong>en</strong>tas\n"); return -1; /* no se pudo crear */ }<br />

if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT))) {<br />

TRACE0("No se pudo crear la barra de estado\n"); return -1; /* No se pudo crear */}<br />

// TODO: eliminar estas tres líneas si no desea que la barra de herrami<strong>en</strong>tas se pueda acoplar<br />

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);<br />

EnableDocking(CBRS_ALIGN_ANY);<br />

DockControlBar(&m_wndToolBar);<br />

return 0; }<br />

50


Uso del Asist<strong>en</strong>te<br />

Código G<strong>en</strong>erado: MainFrm.cpp (ii)<br />

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {<br />

// se llama por las <strong>MFCs</strong> antes de crear físicam<strong>en</strong>te la v<strong>en</strong>tana. se devuelve != 0 si la creación debe continuar, 0<br />

<strong>en</strong> otro caso.<br />

if( !CF !CFrameWnd::PreCreateWindow(cs) W d P C Wi d ( ) ) return FALSE FALSE;<br />

// TODO: modificar aquí la clase Window o los estilos cambiando CREATESTRUCT cs<br />

}<br />

cs.dwExStyle &= ~WS_EX_CLIENTEDGE;<br />

cs.lpszClass l Cl = Af AfxRegisterWndClass(0);<br />

R i t W dCl (0)<br />

return TRUE;<br />

#ifd #ifdef f _DEBUG DEBUG<br />

void CMainFrame::AssertValid() const { CFrameWnd::AssertValid();}<br />

void CMainFrame::Dump(CDumpContext& dc) const { CFrameWnd::Dump(dc); }<br />

#<strong>en</strong>dif //_DEBUG<br />

void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/) {<br />

// <strong>en</strong>viar foco a la v<strong>en</strong>tana de vista<br />

m_wndView.SetFocus();<br />

}<br />

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) {<br />

// Permitir que la vista se interrumpa primero <strong>en</strong> el comando<br />

if ( (m_wndView.OnCmdMsg(nID, dVi O C dM ( ID nCode, C d pExtra, E t pHandlerInfo)) H dl I f )) return t TRUE TRUE;<br />

// De lo contrario, proceder con el control predeterminado<br />

51<br />

return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);<br />

}


ChildView.h: ChildView h: interfaz de la clase CChildView<br />

//<br />

#pragma once<br />

// V<strong>en</strong>tana de CChildView<br />

class CChildView : public CWnd {<br />

// Construcción<br />

public: CChildView();<br />

// Atributos<br />

public:<br />

// Operaciones<br />

public:<br />

// Reemplazos<br />

protected:<br />

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);<br />

// Implem<strong>en</strong>tación<br />

public:<br />

virtual ~CChildView();<br />

// Funciones de asignación de m<strong>en</strong>sajes g<strong>en</strong>eradas<br />

protected:<br />

};<br />

afx_msg void OnPaint();<br />

DECLARE_MESSAGE_MAP()<br />

Uso del Asist<strong>en</strong>te<br />

Código G<strong>en</strong>erado: ChildView.h<br />

52


#include "stdafx.h"<br />

#include "Hello<strong>MFCs</strong>.h"<br />

#include "ChildView ChildView.h h"<br />

#ifdef _DEBUG<br />

#define new DEBUG_NEW<br />

#<strong>en</strong>dif<br />

CChildView::CChildView() { }<br />

CChildView::~CChildView() { }<br />

BEGIN_MESSAGE_MAP(CChildView, CWnd)<br />

ON_WM_PAINT()<br />

END_MESSAGE_MAP()<br />

// Controladores de m<strong>en</strong>saje de CChildView<br />

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) {<br />

if (!CWnd::PreCreateWindow(cs)) return FALSE;<br />

}<br />

Uso del Asist<strong>en</strong>te<br />

Código G<strong>en</strong>erado: ChildView.cpp<br />

cs.dwExStyle y |= | WS_EX_CLIENTEDGE;<br />

_ _<br />

cs.style &= ~WS_BORDER;<br />

cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,<br />

::LoadCursor(NULL, IDC_ARROW), reinterpret_cast(COLOR_WINDOW+1), NULL);<br />

return TRUE;<br />

void CChildView::OnPaint() {}<br />

53


Uso del Asist<strong>en</strong>te<br />

Modificando la aplicación<br />

void CChildView::OnPaint() ()<br />

{<br />

CPaintDC dc(this); // Contexto de dispositivo para dibujo<br />

dc.Rectangle(200, g ( , 200, , 300, , 320); );<br />

dc.DrawText( "Hola <strong>MFCs</strong>!", -1,<br />

CRect( 200, 200, 300, 320),<br />

DT_SINGLELINE|DT_CENTER|<br />

DT_ VCENTER); );<br />

}<br />

54


Bucle de M<strong>en</strong>sajes


Las clases MFC<br />

Arbol jerárquico de clases, con raíz CObject.<br />

CObject permite persist<strong>en</strong>cia (serialize()), chequeo de consist<strong>en</strong>cia de<br />

atributos (AssertValid()), …<br />

Gestión de excepciones: heredan de CException<br />

CException.<br />

ReportError(): muestra la excepción <strong>en</strong> una v<strong>en</strong>tana.<br />

GetErrorMessage(): descripción del error.<br />

Gestión de archivos: CFile.<br />

Contextos de dispositivo: CDC e hijas:<br />

AAcceso al l áárea completa l t dde lla v<strong>en</strong>tana: t CWi CWindowDC. d DC<br />

Dibujo <strong>en</strong> función del ev<strong>en</strong>to WM_PAINT: CPaintDC.<br />

Gestión de Objetos j Gráficos: CGdiObject. j<br />

Gestión de fu<strong>en</strong>tes de letras: CFont.<br />

Gestión de mapas de bits de colores: CBitmap.<br />

Uso de Brochas: CBrush CBrush.<br />

Manejo de plumas: CP<strong>en</strong>.<br />

56


Las clases MFC<br />

CC CCmdTarget: dT t clase l bbase para lla gestión ió dde m<strong>en</strong>sajes. j<br />

Clases docum<strong>en</strong>to: CDocum<strong>en</strong>t, con hijas: COleDocum<strong>en</strong>t,<br />

CHtmlEditDoc, , etc.<br />

Gestión de comunicaciones OLE: COleObjectFactory,<br />

COleDataSource, COleDropTarget, etc.<br />

CW CWnd: d Gestión G tió dde v<strong>en</strong>tanas. t<br />

CFrameWnd e hijas (v<strong>en</strong>tana principal).<br />

CSplitterWnd p (p (paneles de v<strong>en</strong>tana). )<br />

CControlBar (gestión de barras de control y estado): CToolBar,<br />

CStateBar, CReBar, CDialogBar.<br />

CDialog: gestión de v<strong>en</strong>tanas de diálogo. diálogo CColorDialog (selección<br />

de colores), CPrintDialog (imprimir), CFileDialog (elegir un fichero),<br />

CFontDialog (selección de fu<strong>en</strong>tes).<br />

57


Las clases MFC<br />

Gestión de vistas <strong>en</strong> la arquitectura q Docum<strong>en</strong>to/Vista:<br />

CView.<br />

CEditView: Edición de textos.<br />

CHtmlView: Visualización de páginas HTML.<br />

Controles (heredan de CWnd):<br />

Texto estático (CS (CStatic). )<br />

Texto modificable (CEdit).<br />

Listas de elem<strong>en</strong>tos: CListBox, CListBox CCheckListBox CCheckListBox, CDrawListBox<br />

CDrawListBox,<br />

etc.<br />

Clases que no heredan de CObject: Clases de soporte<br />

(ej.: CWaitCursor), API servidor de Internet,<br />

sincronización, etc.<br />

58


Las clases MFC<br />

59


CObject<br />

Las<br />

clases<br />

MFC<br />

CCmdTarget<br />

60


ject<br />

COb<br />

Las clases MFC<br />

61


Mapas de M<strong>en</strong>sajes<br />

Subclases de CCmdTarget.<br />

Declaración del mapa de m<strong>en</strong>sajes: DECLARE_MESSAGE_MAP(),<br />

que nos crea:<br />

Un vector de m<strong>en</strong>sajes privado ( (_messageEntries).<br />

messageEntries)<br />

Un puntero protegido al inicio del vector (messageMap).<br />

Método virtual GetMessageMap(), que devuelve el cont<strong>en</strong>ido de<br />

messageMap. M<br />

Declaración de los métodos que gestionarán los ev<strong>en</strong>tos (precederlos<br />

de afx_msg). g)<br />

Definir la lista que relaciona ev<strong>en</strong>tos con las funciones que los<br />

gestionan:<br />

BEGIN BEGIN_MESSAGE_MAP(clase,claseBase)<br />

MESSAGE MAP(clase claseBase)<br />

Sintaxis que dep<strong>en</strong>de del tipo de ev<strong>en</strong>to: comando, v<strong>en</strong>tana o controles.<br />

END_MESSAGE_MAP()<br />

62


M<strong>en</strong>sajes de V<strong>en</strong>tana<br />

110 tipos de m<strong>en</strong>sajes, producidos por la v<strong>en</strong>tana que<br />

estamos gestionando.<br />

EEmpiezan i por WM WM_XX XX ( (excepto t WM WM_COMMAND).<br />

COMMAND)<br />

Se defin<strong>en</strong> <strong>en</strong> la lista con ON_+.<br />

Ej Ejemplo, l para WM WM_PAINT, PAINT WM WM_RBUTTON_DOWN:<br />

RBUTTON DOWN<br />

BEGIN_MESSAGE_MAP(CChildView, CWnd)<br />

ON ON_WM_PAINT()<br />

WM PAINT()<br />

ON_WM_RBUTTON_DOWN()<br />

END_MESSAGE_MAP()<br />

Se llama a OnPaint() y a OnRButtonDown(UINT, CPoint).<br />

Podemos usar el asist<strong>en</strong>te para gestionar esta lista.<br />

63


M<strong>en</strong>sajes de V<strong>en</strong>tana<br />

Ejemplo: Capturar el ev<strong>en</strong>to WM_LBUTTONDOWN<br />

//ChildView //ChildView.h h<br />

class CChildView : public CWnd<br />

{<br />

public:<br />

CChildView();<br />

protected: p<br />

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);<br />

CPoint lastClicked;<br />

// Implem<strong>en</strong>tación<br />

public:<br />

virtual ~CChildView();<br />

// Funciones de asignación de m<strong>en</strong>sajes g<strong>en</strong>eradas<br />

protected:<br />

afx_msg void OnPaint();<br />

DECLARE_MESSAGE_MAP()<br />

public: bli<br />

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);<br />

};<br />

64


M<strong>en</strong>sajes de V<strong>en</strong>tana<br />

Ejemplo: Capturar el ev<strong>en</strong>to WM_LBUTTONDOWN<br />

//ChildView.cpp<br />

CChildView::CChildView() : lastClicked ( (-1, 1 -1) 1) {}<br />

BEGIN_MESSAGE_MAP(CChildView, CWnd)<br />

ON_WM_PAINT()<br />

ON_WM_LBUTTONDOWN()<br />

END END_MESSAGE_MAP()<br />

MESSAGE MAP()<br />

void CChildView::OnPaint() {<br />

CPaintDC dc(this); // Contexto de dispositivo para dibujo<br />

}<br />

dc.Rectangle(200, 200, 300, 320);<br />

dc.DrawText( "Hola <strong>MFCs</strong>!", -1, CRect( 200, 200, 300, 320),<br />

DT DT_SINGLELINE|DT_CENTER|DT_VCENTER);<br />

SINGLELINE|DT CENTER|DT VCENTER);<br />

if (lastClicked.x>=0 && lastClicked.y>0)<br />

dc.TextOut( lastClicked.x, lastClicked.y, "click");<br />

void CChildView::OnLButtonDown(UINT nFlags, CPoint point) {<br />

lastClicked=point;<br />

InvalidateRect(NULL);<br />

CW CWnd::OnLButtonDown(nFlags, d O LB tt D ( Fl point); i t)<br />

}<br />

65


M<strong>en</strong>sajes de V<strong>en</strong>tana<br />

Ejemplo: Capturar el ev<strong>en</strong>to WM_LBUTTONDOWN<br />

66


M<strong>en</strong>sajes de Controles<br />

EEv<strong>en</strong>tos t que lanza l lla v<strong>en</strong>tana t hij hija al l padre d que lla<br />

conti<strong>en</strong>e.<br />

Ejemplo: el control de edición manda el m<strong>en</strong>saje<br />

EN_CHANGE cuando se modifica el texto que conti<strong>en</strong>e.<br />

Tipos: p<br />

ON_BN_XX: m<strong>en</strong>sajes de botones.<br />

ON_EN_XX: m<strong>en</strong>sajes de editores.<br />

ON ON_CB_XX: CB XX m<strong>en</strong>sajes j dde combo-boxes. b b<br />

ON_LBN_XX: m<strong>en</strong>sajes de listas.<br />

Se mandan mediante el m<strong>en</strong>saje WM WM_COMMAND.<br />

COMMAND<br />

WM_NOTIFY, ON_NOTIFY() para que la función que<br />

gestiona el ev<strong>en</strong>to reciba parámetros.<br />

67


M<strong>en</strong>sajes de Comando<br />

Provi<strong>en</strong><strong>en</strong> de m<strong>en</strong>ús, barras de herrami<strong>en</strong>tas,<br />

teclas aceleradoras y botones.<br />

Macro ON_COMMAND(ev<strong>en</strong>to,metodo).<br />

BEGIN BEGIN_MESSAGE_MAP(CHello<strong>MFCs</strong>App, MESSAGE MAP(CH ll MFC A CWinApp) CWi A )<br />

ON_COMMAND(ID_APP_ABOUT, &CHello<strong>MFCs</strong>App::OnAppAbout)<br />

END_MESSAGE_MAP()<br />

68


M<strong>en</strong>sajes de Comando<br />

Ejemplo: Añadir un elem<strong>en</strong>to de M<strong>en</strong>ú<br />

69


M<strong>en</strong>sajes de Comando<br />

Ejemplo: Añadir el Gestor de Ev<strong>en</strong>tos<br />

70


#pragma once<br />

// V<strong>en</strong>tana de CChildView<br />

class CChildView : public CWnd{<br />

public:<br />

CChildView();<br />

protected: p<br />

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);<br />

private:<br />

const int numColores;<br />

UINT * const CodigoColor; g<br />

CPoint lastClicked;<br />

int curr<strong>en</strong>tColor;<br />

// Implem<strong>en</strong>tación<br />

p<br />

public:<br />

virtual ~CChildView();<br />

protected:<br />

public:<br />

public:<br />

};<br />

M<strong>en</strong>sajes de Comando<br />

// Funciones de asignación g de m<strong>en</strong>sajes j gg<strong>en</strong>eradas<br />

afx_msg void OnPaint();<br />

DECLARE_MESSAGE_MAP()<br />

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);<br />

afx_msg void OnCambiacolor();<br />

Ejemplo: ChildView.h<br />

71


CChildView::CChildView() : numColores (4),<br />

CodigoColor (new UINT[numColores]), curr<strong>en</strong>tColor(0) {<br />

lastClicked = CPoint(-1, -1);<br />

}<br />

CCodigoColor[0] di C l [0] = RGB(0 RGB(0, 00, 0) 0); // Bl Black k<br />

CodigoColor[1] = RGB(255, 0, 0); // Red<br />

CodigoColor[2] = RGB(0, 255, 0); // Gre<strong>en</strong><br />

CodigoColor[3] = RGB(0, 0, 255); // Blue<br />

M<strong>en</strong>sajes de Comando<br />

BEGIN_MESSAGE_MAP(CChildView, CWnd)<br />

ON_WM_PAINT()<br />

ON ON_WM_LBUTTONDOWN()<br />

WM LBUTTONDOWN()<br />

ON_COMMAND(ID_CAMBIACOLOR, &CChildView::OnCambiacolor)<br />

END_MESSAGE_MAP()<br />

Ejemplo: ChildView.cpp<br />

void id CChildVi CChildView::OnPaint() O P i t() {<br />

CPaintDC dc(this); // Contexto de dispositivo para dibujo<br />

dc.Rectangle(200, 200, 300, 320);<br />

dc.DrawText( "Hola <strong>MFCs</strong>!", -1, CRect( 200, 200, 300, 320),DT_SINGLELINE|DT_CENTER|DT_VCENTER);<br />

if (l (lastClicked.x>=0 tCli k d 0 && llastClicked.y>0) tCli k d 0) {<br />

}<br />

}<br />

dc.SetTextColor(CodigoColor[curr<strong>en</strong>tColor]);<br />

dc.DrawText( "Click", -1, CRect( lastClicked, CPoint(lastClicked.x+50, lastClicked.y+20)),<br />

DT_SINGLELINE|DT_CENTER|DT_VCENTER);<br />

void CChildView::OnCambiacolor() { curr<strong>en</strong>tColor = (curr<strong>en</strong>tColor + 1) % numColores; }<br />

72


M<strong>en</strong>sajes de Comando<br />

Resultado<br />

CChildView::~CChildView()<br />

{<br />

delete [ ] CodigoColor;<br />

}<br />

73


Aplicaciones basadas <strong>en</strong> diálogos<br />

Se pued<strong>en</strong> crear aplicaciones basadas <strong>en</strong><br />

diálogo.<br />

Por defecto sin m<strong>en</strong>ús ni teclas aceleradoras.<br />

Para implem<strong>en</strong>tar aplicaciones s<strong>en</strong>cillas,<br />

basadas <strong>en</strong> formularios de toma de datos.<br />

La v<strong>en</strong>tana principal hereda de CDialog CDialog, o de<br />

CDHTMLDialog (para mostrar páginas <strong>en</strong><br />

HTML) HTML).


MapasdeDatos<br />

Mapas de Datos<br />

Intercambio I t bi de d Datos D t de d Diálogo Diál (DDX). (DDX)<br />

Asociar variables a controles del diálogo g<br />

para intercambiar información.<br />

Por Por valor (las variables conti<strong>en</strong><strong>en</strong> el valor<br />

del control) o por refer<strong>en</strong>cia (control).<br />

UpdateData(FALSE) UpdateData(FALSE) actualiza los<br />

controles a partir de las variables.<br />

UpdateData(TRUE) actualiza las variables<br />

a partir del cont<strong>en</strong>ido de los controles.<br />

75


MapasdeDatos<br />

Mapas de Datos<br />

Ejemplo<br />

76


MapasdeDatos<br />

Mapas de Datos<br />

Ejemplo<br />

77


#pragma once<br />

MapasdeDatos<br />

Mapas de Datos<br />

CSimpleDlg.h<br />

// Cuadro de diálogo g de CSimpleDlg p g<br />

class CSimpleDlg : public Cdialog {<br />

// Construcción<br />

public:<br />

CSimpleDlg(CWnd* p g( p pPar<strong>en</strong>t = NULL); ); // Constructor estándar<br />

// Datos del cuadro de diálogo<br />

<strong>en</strong>um { IDD = IDD_SIMPLEDIALOGO_DIALOG };<br />

protected:<br />

virtual void DoDataExchange(CDataExchange* g ( g p pDX); ) // Compatibilidad p con DDX/DDV<br />

// Implem<strong>en</strong>tación<br />

protected:<br />

HICON m_hIcon;<br />

// Funciones de asignación g de m<strong>en</strong>sajes j gg<strong>en</strong>eradas<br />

virtual BOOL OnInitDialog();<br />

afx_msg void OnPaint();<br />

afx_msg HCURSOR OnQueryDragIcon();<br />

DECLARE_MESSAGE_MAP()<br />

_ _ ()<br />

private:<br />

CString strUsrName; // Nombre del usuario<br />

CString strSaludo; // Saludo<br />

public:<br />

afx_msg void OnEnChangeNombre();<br />

afx_msg void OnBnClickedOk();<br />

afx_msg void OnEnKillfocusNombre();<br />

};<br />

78


CSi CSimpleDlg::CSimpleDlg(CWnd* l Dl CSi l Dl (CW d* pPar<strong>en</strong>t P t /*=NULL*/) /* NULL*/)<br />

: CDialog(CSimpleDlg::IDD, pPar<strong>en</strong>t)<br />

, strUsrName(_T(""))<br />

, strSaludo(_T(""))<br />

{<br />

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);<br />

}<br />

void id CSi CSimpleDlg::DoDataExchange(CDataExchange* l Dl D D t E h (CD t E h * pDX) DX)<br />

{<br />

CDialog::DoDataExchange(pDX);<br />

DDX_Text(pDX, IDC_NOMBRE, strUsrName);<br />

DDV DDV_MaxChars(pDX, M Ch ( DX strUsrName, t U N 128); 128)<br />

DDX_Text(pDX, IDC_SALUDO, strSaludo);<br />

}<br />

BEGIN BEGIN_MESSAGE_MAP(CSimpleDlg, MESSAGE MAP(CSi l Dl CDi CDialog) l )<br />

ON_WM_PAINT()<br />

ON_WM_QUERYDRAGICON()<br />

//}}AFX_MSG_MAP<br />

MapasdeDatos<br />

Mapas de Datos<br />

ON ON_EN_CHANGE(IDC_NOMBRE, EN CHANGE(IDC NOMBRE &CSi &CSimpleDlg::OnEnChangeNombre)<br />

l Dl O E Ch N b )<br />

ON_BN_CLICKED(IDOK, &CSimpleDlg::OnBnClickedOk)<br />

ON_EN_KILLFOCUS(IDC_NOMBRE, &CSimpleDlg::OnEnKillfocusNombre)<br />

END_MESSAGE_MAP()<br />

CSimpleDlg.cpp (i)<br />

79


MapasdeDatos<br />

Mapas de Datos<br />

CSimpleDlg.cpp (i)<br />

void CSimpleDlg::OnBnClickedOk()<br />

{<br />

// TODO: Add your control notification handler code here<br />

//OnOK();<br />

}<br />

UpdateData(TRUE);<br />

p ( );<br />

strSaludo = "Hola "+strUsrName+"!";<br />

UpdateData(FALSE);<br />

void CSimpleDlg::OnEnKillfocusNombre()<br />

{ // si ponemos este código <strong>en</strong> EN_CHANGE, se actualiza <strong>en</strong> tiempo de ejecución<br />

UpdateData(TRUE);<br />

strSaludo = "Hola "+strUsrName+"!";<br />

UpdateData(FALSE);<br />

}<br />

80


M<strong>en</strong>ús<br />

Se pued<strong>en</strong> crear <strong>en</strong> el editor de recursos recursos.<br />

El asist<strong>en</strong>te crea un m<strong>en</strong>ú estático <strong>en</strong> la v<strong>en</strong>tana marco (mismo<br />

id<strong>en</strong>tificador que la tabla aceleradora y el icono).<br />

Se cargan todos los recursos <strong>en</strong> InitInstance():<br />

pFrame->LoadFrame(IDR_MAINFRAME,<br />

WS_ OVERLAPPEDWINDOW |FWS | _ ADDTOTITLE, , NULL,NULL); , );<br />

Elem<strong>en</strong>tos del m<strong>en</strong>ú de dos tipos:<br />

pop-up (abr<strong>en</strong> otros m<strong>en</strong>ús).<br />

activos, que g<strong>en</strong>eran un m<strong>en</strong>saje de comando a la aplicación.<br />

Normalm<strong>en</strong>te a través del asist<strong>en</strong>te.<br />

DDos m<strong>en</strong>sajes: j COMMAND y UPDATE_COMMAND_UI.<br />

UPDATE COMMAND UI<br />

El último permite cambiar el aspecto del item de m<strong>en</strong>ú (cambiar<br />

texto, añadir un check, etc.)<br />

81


M<strong>en</strong>ús<br />

Ejemplo<br />

CChildView::CChildView() : numColores (4), CodigoColor (new UINT[numColores]),<br />

curr<strong>en</strong>tColor(0), NombreColor(new CString[numColores]) {<br />

lastClicked = CPoint(-1, -1);<br />

CodigoColor[0] = RGB(0, 0, 0); // Black<br />

//…<br />

NombreColor[0] = "Negro";<br />

//…<br />

}<br />

CChildView::~CChildView() {<br />

delete [] CodigoColor;<br />

delete [] NombreColor;<br />

}<br />

BEGIN_MESSAGE_MAP(CChildView, CWnd)<br />

ON_WM_PAINT()<br />

ON ON_WM_LBUTTONDOWN()<br />

WM LBUTTONDOWN()<br />

ON_COMMAND(ID_CAMBIACOLOR, &CChildView::OnCambiacolor)<br />

ON_UPDATE_COMMAND_UI(ID_CAMBIACOLOR, &CChildView::OnUpdateCambiacolor)<br />

END_MESSAGE_MAP()<br />

void CChildView::OnUpdateCambiacolor(CCmdUI *pCmdUI) {<br />

pCmdUI->SetText("Cambia Color a "+NombreColor[(curr<strong>en</strong>tColor+1)%numColores]);<br />

}<br />

82


CM<strong>en</strong>u<br />

Para cambiar <strong>en</strong>tre distintos m<strong>en</strong>ús, o cargar<br />

uno dinámicam<strong>en</strong>te se usa la clase CM<strong>en</strong>u.<br />

Enmascara un HMENU (<strong>en</strong> m_hM<strong>en</strong>u).<br />

Asignación a la v<strong>en</strong>tana con SetM<strong>en</strong>u().<br />

Algunas funciones miembro:<br />

LoadM<strong>en</strong>u(): LoadM<strong>en</strong>u(): carga un m<strong>en</strong>ú creado como un recurso recurso.<br />

CreateM<strong>en</strong>u(), CreatePopupM<strong>en</strong>u(): crea un m<strong>en</strong>ú<br />

vacío (normal y emerg<strong>en</strong>te).<br />

Attach(): Asocia un CM<strong>en</strong>u a un recurso id<strong>en</strong>tificado por<br />

su HMENU.<br />

83


M<strong>en</strong>ús<br />

Ejemplo: Añadir un M<strong>en</strong>ú a un Diálogo<br />

1<br />

2<br />

3<br />

84


M<strong>en</strong>ús<br />

Ejemplo: Añadir un M<strong>en</strong>ú a un Diálogo<br />

11. Crear el m<strong>en</strong>ú <strong>en</strong> el editor de recursos<br />

(ID=IDR_SIMPLEDIALOG).<br />

22. Añ Añadir di un atributo t ib t dde ti tipo CM CM<strong>en</strong>u a lla clase l CSi CSimpleDlg, l Dl<br />

gestión de items de m<strong>en</strong>ú.<br />

class CSimpleDlg : public CDialog {<br />

…<br />

private:<br />

CM<strong>en</strong>u m<strong>en</strong>u;<br />

CListBox fileListBox; // DDX, control<br />

public:<br />

afx_msg g void OnFicheroSeleccionar(); (); // gestión g de items de m<strong>en</strong>ú<br />

afx_msg void OnFicheroSalir();<br />

};<br />

85


CSimpleDlg::CSimpleDlg(CWnd* pPar<strong>en</strong>t /*=NULL*/)<br />

: CDialog(CSimpleDlg::IDD, pPar<strong>en</strong>t), strUsrName(_T("")), strSaludo(_T("")), m<strong>en</strong>u() {<br />

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);<br />

M<strong>en</strong>ús<br />

}<br />

void CSimpleDlg::DoDataExchange(CDataExchange* pDX) {<br />

CDialog::DoDataExchange(pDX);<br />

DDX_Text(pDX, _ (p IDC_NOMBRE, _ strUsrName); )<br />

DDV_MaxChars(pDX, strUsrName, 12);<br />

DDX_Text(pDX, IDC_SALUDO, strSaludo);<br />

DDX_Control(pDX, IDC_FICHEROS, fileListBox);<br />

}<br />

M<strong>en</strong>ús<br />

CSimpleDlg.cpp<br />

BEGIN_MESSAGE_MAP(CSimpleDlg, CDialog)<br />

ON_WM_PAINT()<br />

ON_WM_QUERYDRAGICON() ()<br />

//}}AFX_MSG_MAP<br />

ON_EN_CHANGE(IDC_NOMBRE, &CSimpleDlg::OnEnChangeNombre)<br />

ON_BN_CLICKED(IDOK, &CSimpleDlg::OnBnClickedOk)<br />

ON_EN_KILLFOCUS(IDC_NOMBRE, &CSimpleDlg::OnEnKillfocusNombre)<br />

ON_COMMAND(ID_FICHERO_SELECCIONAR, &CSimpleDlg::OnFicheroSeleccionar)<br />

ON_COMMAND(ID_FICHERO_SALIR, &CSimpleDlg::OnFicheroSalir)<br />

END_MESSAGE_MAP()<br />

BOOL CSimpleDlg::OnInitDialog() {<br />

CDialog::OnInitDialog();<br />

SetIcon(m_hIcon, TRUE); // Establecer icono grande<br />

}<br />

SetIcon(m_hIcon, FALSE); // Establecer icono pequeño<br />

m<strong>en</strong>u.LoadM<strong>en</strong>u(IDR_SIMPLEDIALOGO);<br />

SetM<strong>en</strong>u(&m<strong>en</strong>u);<br />

return TRUE; // Devuelve TRUE a m<strong>en</strong>os que establezca el foco <strong>en</strong> un control<br />

86


M<strong>en</strong>ús<br />

CSimpleDlg.cpp<br />

void CSimpleDlg::OnFicheroSeleccionar()<br />

{<br />

LPCTSTR C S szCppFilters= C "C++ C Files (* (*.cpp)|*.cpp|All )|* | Files (* (*.*)|*.*||"; *)|* *||<br />

CFileDialog fd(TRUE, "Cpp", "*.cpp",<br />

OFN OFN_FILEMUSTEXIST| FILEMUSTEXIST| OFN_HIDEREADONLY, OFN HIDEREADONLY szCppFilters, szCppFilters this);<br />

if( fd.DoModal ()==IDOK ) {<br />

CString pathName = fd.GetPathName();<br />

UpdateData(TRUE);<br />

fil fileListBox.AddString(pathName);<br />

Li tB AddSt i ( thN )<br />

UpdateData(FALSE);<br />

}<br />

}<br />

void CSimpleDlg::OnFicheroSalir() {<br />

PostMessage(WM_QUIT);<br />

}<br />

87


M<strong>en</strong>ús<br />

Ejemplo: Añadir un M<strong>en</strong>ú Emerg<strong>en</strong>te Dinámico<br />

class CSimpleDlg : public CDialog<br />

{<br />

private:<br />

public:<br />

};<br />

// …<br />

CM<strong>en</strong>u pm<strong>en</strong>u;<br />

afx_msg g void OnRButtonDown(UINT ( nFlags, g , CPoint p point); ); //con asist<strong>en</strong>te<br />

afx_msg void OnItem1(); // a mano<br />

88


CSimpleDlg::CSimpleDlg(CWnd* pPar<strong>en</strong>t /*=NULL*/)<br />

M<strong>en</strong>ús<br />

: CDialog(CSimpleDlg::IDD, pPar<strong>en</strong>t)<br />

, strUsrName(_T("")) , strSaludo(_T("")) , m<strong>en</strong>u(), pm<strong>en</strong>u() {<br />

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); CSimpleDlg.cpp<br />

}<br />

BEGIN_MESSAGE_ MAP(CSimpleDlg, ( p g, CDialog) g)<br />

ON_WM_PAINT()<br />

ON_WM_QUERYDRAGICON()<br />

//}}AFX_MSG_MAP<br />

// …<br />

ON_COMMAND(ID_FICHERO_SELECCIONAR, &CSimpleDlg::OnFicheroSeleccionar)<br />

ON_COMMAND(ID_FICHERO_SALIR, &CSimpleDlg::OnFicheroSalir)<br />

ON_COMMAND(ID_FICHERO_SALIR+1, &CSimpleDlg::OnItem1)<br />

ON ON_WM_RBUTTONDOWN()<br />

WM RBUTTONDOWN()<br />

END_MESSAGE_MAP()<br />

BOOL CSimpleDlg::OnInitDialog() {<br />

CDialog::OnInitDialog();<br />

SetIcon(m_hIcon, TRUE); // Establecer icono grande<br />

SetIcon(m_hIcon, FALSE); // Establecer icono pequeño<br />

m<strong>en</strong>u.LoadM<strong>en</strong>u(IDR ( _ SIMPLEDIALOGO); );<br />

SetM<strong>en</strong>u(&m<strong>en</strong>u);<br />

pm<strong>en</strong>u.CreatePopupM<strong>en</strong>u();<br />

pm<strong>en</strong>u.App<strong>en</strong>dM<strong>en</strong>u(MF_STRING, ID_FICHERO_SALIR+1, "Item 1");<br />

pm<strong>en</strong>u pm<strong>en</strong>u.App<strong>en</strong>dM<strong>en</strong>u(MF_STRING, App<strong>en</strong>dM<strong>en</strong>u(MF STRING ID ID_FICHERO_SELECCIONAR, FICHERO SELECCIONAR "Seleccionar Seleccionar Fichero"); Fichero );<br />

pm<strong>en</strong>u.App<strong>en</strong>dM<strong>en</strong>u(MF_STRING, ID_FICHERO_SALIR, "Salir");<br />

return TRUE; // Devuelve TRUE a m<strong>en</strong>os que establezca el foco <strong>en</strong> un control<br />

}<br />

89


M<strong>en</strong>ús<br />

CSimpleDlg.cpp<br />

void CSimpleDlg::OnFicheroSalir()<br />

{<br />

// TODO: TODO Add your command d hhandler dl code d hhere<br />

PostMessage(WM_QUIT);<br />

}<br />

void CSimpleDlg::OnRButtonDown(UINT nFlags, CPoint point)<br />

{<br />

Cli<strong>en</strong>tToScre<strong>en</strong>(&point);<br />

pm<strong>en</strong>u.TrackPopupM<strong>en</strong>u(TPM_LEFTALIGN, point.x, point.y, this);<br />

}<br />

void CSimpleDlg::OnItem1()<br />

{<br />

AfxMessageBox("Item AfxMessageBox( Item 1 1"); );<br />

}<br />

90


M<strong>en</strong>ús<br />

Ejemplo: Añadir un M<strong>en</strong>ú Emerg<strong>en</strong>te Dinámico<br />

En realidad lo que hemos hecho es un “m<strong>en</strong>ú<br />

contextual”.<br />

PPara ello ll bbasta t con capturar t el l m<strong>en</strong>saje j<br />

WM_CONTEXTMENU.<br />

void id CSimpleDlg::OnContextM<strong>en</strong>u(CWnd* CSi l Dl O C t tM (CW d* pWnd, W d CP CPoint i t point) i t)<br />

{<br />

pm<strong>en</strong>u.TrackPopupM<strong>en</strong>u(TPM_LEFTALIGN, point.x, point. y, this);<br />

}<br />

Si no mostramos un m<strong>en</strong>ú, debemos llamar a<br />

CWnd::OnContextM<strong>en</strong>u(pWnd CWnd::OnContextM<strong>en</strong>u(pWnd, point) antes de salir salir.<br />

91


Teclas Aceleradoras<br />

Asociar una combinación de teclas a un comando.<br />

Si se usa el asist<strong>en</strong>te, la definición de teclas<br />

aceleradoras l d se carga <strong>en</strong> lla v<strong>en</strong>tana t marco con lla<br />

llamada a LoadFrame().<br />

92


Teclas Aceleradoras<br />

Las tablas aceleradoras no funcionan con aplicaciones<br />

basadas <strong>en</strong> diálogo, ya que su bucle de m<strong>en</strong>sajes no<br />

llama a TranslateAccelerator()<br />

TranslateAccelerator().<br />

class CSimpleApp : public CWinApp<br />

{<br />

private:<br />

public: bli<br />

HACCEL m_haccel; // añadir handle a tabla aceleradora<br />

CSimpleApp();<br />

// Reemplazos<br />

public:<br />

virtual BOOL InitInstance();<br />

BOOL ProcessMessageFilter(int code, LPMSG lpMsg); // sobreescribir<br />

DECLARE DECLARE_MESSAGE_MAP()<br />

MESSAGE MAP()<br />

};<br />

93


BOOL CSimpleApp::InitInstance() {<br />

INITCOMMONCONTROLSEX InitCtrls;<br />

InitCtrls.dwSize = sizeof(InitCtrls); Teclas Aceleradoras<br />

InitCtrls.dwICC = ICC_WIN95_CLASSES;<br />

InitCommonControlsEx(&InitCtrls);<br />

CWinApp::InitInstance();<br />

AfxEnableControlContainer(); ();<br />

SetRegistryKey(_T("Aplicaciones g<strong>en</strong>eradas con el Asist<strong>en</strong>te para aplicaciones local"));<br />

m_haccel=::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));<br />

CSimpleDlg dlg;<br />

m_ppMainWnd = &dlg; g;<br />

INT_PTR nResponse = dlg.DoModal();<br />

if (nResponse == IDOK) {<br />

// TODO: insertar aquí el código para controlar cuándo se descarta el cuadro de diálogo con Aceptar<br />

}<br />

else if (nResponse == IDCANCEL) {<br />

// TODO: insertar aquí el código para controlar cuándo se descarta el cuadro de diálogo con Cancelar<br />

}<br />

return FALSE;<br />

}<br />

BOOL CSimpleApp::ProcessMessageFilter(int code, LPMSG lpMsg) {<br />

if (code ( < 0) ) CWinApp::ProcessMessageFilter(code, pp g ( , lpMsg); p g);<br />

if(m_haccel)<br />

{<br />

if (::TranslateAccelerator(m_pMainWnd->m_hWnd, m_haccel, lpMsg))<br />

return(TRUE); ( );<br />

}<br />

return CWinApp::ProcessMessageFilter(code, lpMsg);<br />

}<br />

94


Teclas Aceleradoras<br />

Este podría ser un bucle de m<strong>en</strong>sajes con llamada a las<br />

tteclas l aceleradoras: l d<br />

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow) {<br />

MSG msg;<br />

BOOL bRet;<br />

//…<br />

while ( (bRet = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0) {<br />

if (bRet (bR t == -1) 1) {<br />

// handle the error and possibly exit<br />

}<br />

else { // Check for accelerator keystrokes.<br />

if (!TranslateAccelerator(<br />

hwndMain, // handle to receiving window<br />

haccel, // handle to active accelerator table<br />

&msg)) // message data<br />

{<br />

TranslateMessage(&msg);<br />

DispatchMessage(&msg);<br />

}<br />

}<br />

}<br />

//…<br />

}<br />

95


Diálogos<br />

Las <strong>MFCs</strong> conti<strong>en</strong><strong>en</strong> diálogos preconstruidos<br />

que pued<strong>en</strong> ser usados directam<strong>en</strong>te por el<br />

usuario.<br />

Para crear un diálogo: g<br />

Se usa el editor de recursos.<br />

DoModal() () muestra el diálogo g de manera modal.<br />

Devuelve un UINT con la razón por la que se cerró<br />

(ej.: IDCANCEL o IDOK).<br />

Los no modales se crean como si fueran una v<strong>en</strong>tana<br />

(Create()).<br />

96


Ejemplo: Añadir un Diálogo<br />

Se añade un nuevo elem<strong>en</strong>to al m<strong>en</strong>ú<br />

y a la tabla aceleradora<br />

void CSimpleDlg::OnFicheroDialogo() {<br />

CDialogoEjemplo dlg(this);<br />

dlg dlg.DoModal(); DoModal();<br />

}<br />

Creado usando el<br />

editor de recursos.<br />

SSe crea una clase l que<br />

herede de CDialog<br />

con el asist<strong>en</strong>te asist<strong>en</strong>te.<br />

class CDialogoEjemplo : public CDialog {<br />

DECLARE_DYNAMIC(CDialogoEjemplo)<br />

public:<br />

CDialogoEjemplo(CWnd* CDialogoEjemplo(CWnd pPar<strong>en</strong>t = NULL);<br />

virtual ~CDialogoEjemplo();<br />

<strong>en</strong>um { IDD = IDD_DIALOG1 };<br />

protected:<br />

virtual void<br />

DoDataExchange(CDataExchange* pDX);<br />

DECLARE_MESSAGE_MAP()<br />

};<br />

97


Diálogos Predefinidos<br />

CC CColorDialog: l Di l permite i seleccionar l i un<br />

color.<br />

CFileDialog: permite seleccionar<br />

ficheros.<br />

CFindReplaceDialog: permite realizar<br />

búsqueda o buscar/reemplazar (no<br />

modal, se crea con Create()). 98


Diálogos Predefinidos<br />

CFontDialog: permite elegir una<br />

fu<strong>en</strong>te.<br />

CPrintDialog: permite imprimir y<br />

configurar la impresión.<br />

CPageSetupDialog: permite<br />

imprimir y<br />

99


Controles<br />

Las MFC pon<strong>en</strong> a nuestra disposición un<br />

gran g número de controles qque simplifican p<br />

la creación de aplicaciones.<br />

Los Los controles mandan notificaciones a la<br />

v<strong>en</strong>tana padre (ej.: el control de edición<br />

manda EN_CHANGE C G cuando cambia el<br />

texto). )<br />

100


Controles predefinidos MFC<br />

CAnimateCtrl: public CWnd: Permite<br />

mostrar un vídeo <strong>en</strong> formato AVI.<br />

void CAboutDlg::OnBnClickedButton1()<br />

{<br />

avi_player.Op<strong>en</strong>(IDR_AVI1);<br />

avi avi_player.Play(0, player Play(0 -1 -1, -1);<br />

}<br />

101


Controles predefinidos MFC<br />

CButton: permite gestionar botones.<br />

Ev<strong>en</strong>tos: BN BN_CLICKED, CLICKED, BN BN_DOUBLECLICKED.<br />

DOUBLECLICKED.<br />

Métodos: GetState(), SetState(), SetCursor(), GetCursor().<br />

void CAboutDlg::OnBnClickedMessage()<br />

{<br />

anim.Stop();<br />

AfxMessageBox("Stop!");<br />

}<br />

102


Controles predefinidos MFC<br />

CBit CBitmapButton: B tt SSe crea un botón b tó normal l <strong>en</strong> el l<br />

editor de recursos y:<br />

se selecciona OwnerDraw=true<br />

OwnerDraw true.<br />

<strong>en</strong> el caption se pone una descripción (ej: BOTON).<br />

Se crean de 1 a 4 bitmaps:<br />

ID=“BOTONU”, bitmap normal.<br />

ID=“BOTONF”, bitmap foco de teclado.<br />

ID=“BOTONX”, , bitmap p botón desactivado.<br />

ID=“BOTOND”, bitmap botón pulsado.<br />

Se crea un objeto de la clase CBitmapButton como<br />

miembro del diálogo diálogo.<br />

En la inicialización del diálogo (OnInitDialog()) se llama<br />

a AutoLoad().<br />

103


Ejemplo<br />

class CAboutDlg : public CDialog {<br />

public:<br />

CAboutDlg();<br />

CBitmapButton<br />

//…<br />

virtual void DoDataExchange(CDataExchange* pDX); // Compatibilidad con DDX/DDV<br />

// Implem<strong>en</strong>tación<br />

protected:<br />

DECLARE_MESSAGE_MAP()<br />

private: i t<br />

CAnimateCtrl anim;<br />

CBitmapButton BClose;<br />

public:<br />

afx_msg f void id OOnBnClickedStart(); B Cli k dSt t()<br />

afx_msg void OnBnClickedMessage();<br />

public:<br />

BOOL OnInitDialog();<br />

};<br />

void CAboutDlg::DoDataExchange(CDataExchange* pDX) {<br />

CDialog::DoDataExchange(pDX);<br />

DDX_Control(pDX, IDC_ANIMATE1, anim);<br />

DDX DDX_Control(pDX, C t l( DX IDMESSAGE, IDMESSAGE BCl BClose); )<br />

}<br />

//…<br />

BOOL CAboutDlg::OnInitDialog() {<br />

BCl BClose.AutoLoad(IDMESSAGE, A t L d(IDMESSAGE this); thi )<br />

CDialog::OnInitDialog();<br />

return FALSE;<br />

}<br />

104


Controles predefinidos MFC<br />

CListBox:<br />

Listas<br />

Datos iniciales (<strong>en</strong> “OnInitDialog”)<br />

Selección simple o múltiple<br />

Métodos:<br />

int GetCurSel();<br />

int SetCurSel(int nSelect);<br />

int AddString(LPCTSTR lpszItem);<br />

int InsertString(int nIndex,<br />

LPCTSTR lpszItem);<br />

Ejemplo<br />

void CSimpleDlg::OnLbnKillfocusList1()<br />

{<br />

int sel = nameListBox.GetCurSel();<br />

if (sel>-1) {<br />

CString str;<br />

nameListBox.GetText(sel,str);<br />

Af AfxMessageBox("Selected M B ("S l t d It Item: " "+str); t )<br />

}<br />

105<br />

}


Controles predefinidos MFC<br />

CC CComboBox: b B<br />

Simple (lista siempre visible), Drop-down (permite editar), Drop-<br />

Down List.<br />

Métodos:<br />

GetCount(): número de elem<strong>en</strong>tos que ti<strong>en</strong>e la lista.<br />

GetCurSel()/SetCurSel(): obti<strong>en</strong>e/establece el número de ord<strong>en</strong> del<br />

elem<strong>en</strong>to seleccionado.<br />

SetItemData()/GetItemData(): lee el valor asignado a un<br />

determinado elem<strong>en</strong>to de la lisa.<br />

AddString()/DeleteString()/InsertString(). También se pued<strong>en</strong> cargar<br />

valores estáticos <strong>en</strong> el campo “Data” del editor de recursos<br />

(separados mediante ;)<br />

Dir().<br />

CComboBoxEx: permite introducir imág<strong>en</strong>es <strong>en</strong> los<br />

elem<strong>en</strong>tos a seleccionar, <strong>en</strong>tre otras mejoras.<br />

106


Controles predefinidos MFC<br />

CD CDataTimeCtrl. t Ti Ct l<br />

CEdit.<br />

CHeaderCtrl<br />

CHeaderCtrl.<br />

CHotKeyCtrl.<br />

CIpAddressCtrl<br />

CIpAddressCtrl.<br />

CCheckListBox.<br />

CDragListBox<br />

CDragListBox.<br />

CListCtrl.<br />

CMonthCalCtrl.<br />

COleControl.<br />

CProgressCtrl.<br />

107


Controles predefinidos MFC<br />

CR CReBarCtrl. B Ct l<br />

CRichEditCtrl.<br />

CScrollBar CScrollBar.<br />

CSliderCtrl.<br />

CSpinButtonCtrl<br />

CSpinButtonCtrl.<br />

CStatic.<br />

CStatusBarCtrl<br />

CStatusBarCtrl.<br />

CTabCtrl.<br />

CToolBarCtrl<br />

CToolBarCtrl.<br />

CToolTipCtrl.<br />

CTreeCtrl CTreeCtrl.<br />

108


Clases de Utilidad<br />

Cad<strong>en</strong>as de caracteres<br />

CString CString.<br />

Caracteres unicode vs. ascii.<br />

Definiciones de un “const char*”<br />

typedef wchar_t wchar t WCHAR;<br />

// “wchar_t” es un char “Unicode” (2 bytes)<br />

// o “ANSI” (1 byte) dep<strong>en</strong>di<strong>en</strong>do de<br />

// la opción señalada para el proyecto<br />

typedef __nullterminated CONST WCHAR *LPCWSTR;<br />

typedef LPCWSTR LPCTSTR;<br />

Conversiones. Ejemplo: j p<br />

LPCTSTR t;<br />

// si t<strong>en</strong>emos “opción Unicode” es un error: t="abc";<br />

CString c1("abc");<br />

c1="def"; 1 "d f"<br />

t=c1;<br />

// correcto ya que hace un casting implícito<br />

// y está definido un operador p de casting g<br />

109


Clases de Utilidad<br />

Cad<strong>en</strong>as de caracteres<br />

// sobrecarga de =, +=, + etc<br />

CString s;<br />

s="Hola”;<br />

s= Hola ;<br />

s+=“ soy yo”;<br />

cout


Clases de Utilidad<br />

Cont<strong>en</strong>edores<br />

Similares a los cont<strong>en</strong>edores de la STL.<br />

Definiciones <strong>en</strong> afxtempl.h (que debemos incluir <strong>en</strong><br />

stdafx.h). td f h)<br />

Los templates admit<strong>en</strong> dos parámetros: el tipo de dato, y<br />

el tipo para referirse a él (quizá una refer<strong>en</strong>cia) refer<strong>en</strong>cia).<br />

Cont<strong>en</strong>edor Clase Puntero<br />

Vectores CArray CTypedPtrArray<br />

Listas CList CTypedPtrList<br />

Diccionario CMap CTypedPtrMap


Clases de Utilidad<br />

Cont<strong>en</strong>edores: CArray<br />

Si Similar il a vector t dde lla STL STL.<br />

template < class TYPE, class ARG_TYPE =<br />

const TYPE& > class CArray : public<br />

<br />

CObject<br />

ARG_TYPE es el tipo que se usa para<br />

acceder a los elem<strong>en</strong>tos almac<strong>en</strong>ados.<br />

Ej Ejemplo l<br />

CArray myArray;<br />

Tamaño:<br />

//Addelem<strong>en</strong>tstothearray<br />

// Add elem<strong>en</strong>ts to the array.<br />

GetCount(), GetSize(), GetUpperBound(), for (int i=0;i < 10;i++)<br />

IsEmpty(), SetSize().<br />

myArray.Add( CPoint(i, 2*i) );<br />

Operaciones:<br />

p<br />

FreeExtra(), RemoveAll(), RelocateElem<strong>en</strong>ts().<br />

Aum<strong>en</strong>tando el Array:<br />

Add(), (), App<strong>en</strong>d(), pp (), Copy(), py(), SetAtGrow(). ()<br />

Inserción/eliminación:<br />

InsertAt(), RemoveAt()<br />

Operadores:<br />

Acceso/modificación con el operador [].<br />

// Modify all the points in the array.<br />

for (i=0;i


Clases de Utilidad<br />

Cont<strong>en</strong>edores: CList<br />

ttemplate TYPE& class l CLi CList t : public bli CObj CObject t<br />

Iteración: CList myList; y ;<br />

POSITION pos = myList.GetHeadPosition();<br />

while( pos != NULL ) {<br />

}<br />

CMiClase& clase = myList.GetNext( pos );<br />

// //...<br />

IInserción: ió myList.InsertAfter(myList.GetTailPosition(), Li t I tAft ( Li t G tT ilP iti () elem); l )<br />

Eliminación: myList myList.RemoveAt(pos);<br />

RemoveAt(pos);<br />

113


Clases de Utilidad<br />

Cont<strong>en</strong>edores: CMap<br />

template< l class l KEY KEY, class l<br />

ARG_KEY, class VALUE, class<br />

ARG_VALUE >class CMap : public<br />

CObject<br />

Operaciones:<br />

GetHashTableSize()<br />

GetHashTableSize(),<br />

GetNextAssoc(), PGetNextAssoc(),<br />

GetStartPosition(), PGetFirstAssoc(),<br />

InitHashTable() InitHashTable(), Lookup() Lookup(),<br />

PLookup(), operator[], RemoveAll(),<br />

RemoveKey(), SetAt().<br />

Estado:<br />

GetCount(), GetSize(), IsEmpty().<br />

Miembros de Datos:<br />

CMap::CPair<br />

CM CMap i t i t CP i t CP i t myMap; M<br />

int i;<br />

myMap.InitHashTable( 257 );<br />

// Add 10 elem<strong>en</strong>ts to the map.<br />

for (i=0;i < 200;i++)<br />

myMap[i] = CPoint(i, i);<br />

// Remove the elem<strong>en</strong>ts with ev<strong>en</strong><br />

// key values.<br />

CPoint pt;<br />

f for (i=0; (i 0 myMap.Lookup( M L k ( ii, pt t ) ;i+=2) i+ 2)<br />

{<br />

myMap.RemoveKey( i );<br />

}<br />

Ejemplo


Clases de Utilidad<br />

Cont<strong>en</strong>edores de punteros<br />

Si queremos t<strong>en</strong>er listas de objetos heterog<strong>en</strong>eos<br />

heterog<strong>en</strong>eos.<br />

No podemos usar los cont<strong>en</strong>edores anteriores, ya que si<br />

queremos q serializar una lista a disco, se copiarían p los<br />

punteros, y no los objetos.<br />

Por ello, MFC duplica los cont<strong>en</strong>edores para la gestión de<br />

punteros punteros.<br />

template< class BASE_CLASS, class TYPE > class<br />

CTypedPtrList : public BASE_CLASS<br />

BASE BASE_CLASS: CLASS ti tipo ddel l que se hhereda d para construir t i el l<br />

template.<br />

CObList si los elem<strong>en</strong>tos heredan de CObject (se pued<strong>en</strong> serializar).<br />

CPtrList <strong>en</strong> otro caso. caso<br />

TYPE: tipo de los elem<strong>en</strong>tos que insertamos.<br />

Similar para arrays.


typedef CTypedPtrList CMyList;<br />

CMyList ml;<br />

CMyObject* y j pMyObject y j = new CMyObject(); y j ()<br />

ml.AddTail(pMyObject);<br />

CFileException e;<br />

CFile myFile;<br />

myFile.Op<strong>en</strong>("MyFile.txt",<br />

CFile::modeCreate|CFile::modeWrite, &e);<br />

CArchive ar(&myFile, CArchive::store);<br />

ml.Serialize(ar);<br />

ar.Close();<br />

myFile.Close();<br />

while (!ml.IsEmpty())<br />

{<br />

delete ml.GetHead();<br />

ml.RemoveHead();<br />

}<br />

Clases de Utilidad<br />

Cont<strong>en</strong>edores de punteros, ejemplo<br />

//=====================<br />

// //where h CMyObject CM Obj t iis ddefined fi d bby th the ffollowing ll i fil files:<br />

//CMyObject.h<br />

class CMyObject : public Cobject {<br />

public: bli<br />

int i;<br />

void Serialize(CArchive& ar);<br />

CMyObject() { i = 9876;}<br />

protected: t t d<br />

DECLARE_SERIAL(CMyObject)<br />

};<br />

//CM //CMyObject.cpp Obj t<br />

#include "stdafx.h"<br />

#include "CMyObject.h"<br />

IMPLEMENT IMPLEMENT_SERIAL(CMyObject, SERIAL(CM Obj t CObject, CObj t 0)<br />

void CMyObject::Serialize(CArchive& ar) {<br />

CObject::Serialize( ar );<br />

if( ar.IsStoring() )<br />

ar > i;<br />

}


Clases de Utilidad<br />

Cont<strong>en</strong>edores de punteros: CTypedPtrMap<br />

ttemplate< l t < class l BASE_CLASS, BASE CLASS class l KEY KEY, class l VALUE > class l<br />

CTypedPtrMap : public BASE_CLASS<br />

BASE_CLASS: clase base del diccionario, puede ser, <strong>en</strong> función de<br />

llos tipos ti de d la l clave l y elem<strong>en</strong>tos l t a almac<strong>en</strong>ar: l<br />

CMapPtrToPtr,<br />

CMapPtrToWord,<br />

CMapWordToPtr,<br />

CMapStringToPtr<br />

CMapStringToString<br />

p g g<br />

CMapWordToOb<br />

CMapWordToPtr<br />

KEY: tipo de la clave. clave<br />

VALUE: tipo de los elem<strong>en</strong>tos a almac<strong>en</strong>ar (suele ser un<br />

puntero).<br />

Ej.: typedef CTypedPtrMap MapaAMiObjeto;


Indice<br />

P<strong>Programación</strong> ió bbajo j Wi <strong>Windows</strong>. d<br />

Introducción a las <strong>MFCs</strong>.<br />

A Arquitectura it t Docum<strong>en</strong>to/Vista.<br />

D t /Vi t<br />

Introducción.<br />

SDI y MDI.<br />

Plantillas Plantillas de docum<strong>en</strong>to.<br />

docum<strong>en</strong>to<br />

Ejemplo.<br />

D Docum<strong>en</strong>to, t serialización. i li ió<br />

Bibliografía.<br />

118


Arquitectura Docum<strong>en</strong>to Vista<br />

SSeparar lla visualización i li ió ( (vista) i ) dde llos d datos (d (docum<strong>en</strong>to). )<br />

Similar al patrón “Model-View-Controler”.<br />

El asist<strong>en</strong>te g<strong>en</strong>era clases que heredan de: CFrameWnd CFrameWnd, CView y<br />

CDocum<strong>en</strong>t.<br />

CView es abstracta. Otra posibilidad es usar como base una vista<br />

predefinida: d fi id<br />

CEditView (edición de texto básica). Esta se puede usar directam<strong>en</strong>te.<br />

CRichEditView (permite formateo de texto).<br />

CScrollView (scroll vertical y horizontal).<br />

CListView (listas de elem<strong>en</strong>tos).<br />

CTreeView (árbol de elem<strong>en</strong>tos) elem<strong>en</strong>tos).<br />

CFormView (similar a un cuadro de diálogo).<br />

CDaoRecordView (similar a cuadro de diálogo pero para control de<br />

BBDD) BBDD).<br />

CCtrolView (se pued<strong>en</strong> incluir otras vistas d<strong>en</strong>tro).<br />

119


SDI y MDI<br />

Single Docum<strong>en</strong>t Interface: Un solo tipo de docum<strong>en</strong>to docum<strong>en</strong>to.<br />

Multiple Docum<strong>en</strong>t Interface: Varios tipos de docum<strong>en</strong>to.<br />

Una aplicación SDI Una aplicación MDI<br />

120


Las plantillas de docum<strong>en</strong>to<br />

El docum<strong>en</strong>to, el marco y la vista se relacionan usando plantillas de<br />

docum<strong>en</strong>to, que heredan de CDocTemplate.<br />

CSingleDocTemplate y CMultiDocTemplate para SDI y MDI.<br />

BOOL CSDI2App::InitInstance() CSDI2A I itI t () {<br />

//…<br />

pDocTemplate = new CSingleDocTemplate(<br />

IDR_MAINFRAME,<br />

}<br />

RUNTIME RUNTIME_CLASS(CSDI2Doc),<br />

CLASS(CSDI2D )<br />

RUNTIME_CLASS(CMainFrame), // V<strong>en</strong>tana de marco SDI principal<br />

RUNTIME_CLASS(CSDI2View));<br />

if (!pDocTemplate) return FALSE;<br />

AddD AddDocTemplate(pDocTemplate);<br />

T l t ( D T l t )<br />

EnableShellOp<strong>en</strong>();<br />

RegisterShellFileTypes(TRUE);<br />

// …<br />

RUNTIME_CLASS devuelve un struct CRuntimeClass *.<br />

Nota: Sólo se puede obt<strong>en</strong>er esta información de subclases de CObject que<br />

hayan sido declaradas DECLARE_DYNAMIC, DECLARE_DYNCREATE o<br />

DECLARE_SERIAL.<br />

121


Las plantillas de docum<strong>en</strong>to<br />

Una plantilla de docum<strong>en</strong>to por cada tipo de docum<strong>en</strong>to<br />

soportado, y es responsable de crear y gestionar los<br />

docum<strong>en</strong>tos de ese tipo tipo.<br />

La plantilla conti<strong>en</strong>e el ID con los recursos (m<strong>en</strong>ú, icono,<br />

tablas aceleradoras).<br />

aceleradoras)<br />

Conti<strong>en</strong>e también strings con el nombre del tipo de<br />

docum<strong>en</strong>to, docu e o, la a eext<strong>en</strong>sión e s ó de sus ficheros, c e os, eetc. c<br />

EnableShellOp<strong>en</strong>(): permite abrir ficheros de datos<br />

haci<strong>en</strong>do doble click <strong>en</strong> ellos <strong>en</strong> el explorador. p<br />

RegisterShellFileTypes(cCompat): Registra los tipos de<br />

docum<strong>en</strong>tos <strong>en</strong> el explorador. Si bCompat==TRUE<br />

<strong>en</strong>tonces se pued<strong>en</strong> imprimir los ficheros desde el<br />

explorador.<br />

122


Arquitectura Docum<strong>en</strong>to Vista<br />

Ejemplo<br />

123


Arquitectura Docum<strong>en</strong>to Vista<br />

Ejemplo<br />

St String i asociado i d a la l aplicación li ió IDR IDR_MAINFRAME<br />

MAINFRAME<br />

7 pedazos:<br />

Vista derivada de CFormView.<br />

Se crea también un diálogo vacío<br />

<strong>en</strong> el editor de recursos:<br />

124


El Docum<strong>en</strong>to<br />

Encargado de gestionar los datos, incluido su grabación y<br />

recuperación del disco.<br />

virtual BOOL OnNewDocum<strong>en</strong>t(); se llama cuando se va a<br />

crear un nuevo fichero (sobreescribirlo permite chequear si<br />

queremos dejar crearlo o no).<br />

virtual BOOL OnOp<strong>en</strong>Docum<strong>en</strong>t(LPCTSTR lpszPathName);<br />

se llama cuando se va a abrir un fichero.<br />

virtual void OnCloseDocum<strong>en</strong>t(); se llama cuando se va a<br />

cerrar un fichero fichero.<br />

virtual BOOL OnSaveDocum<strong>en</strong>t(LPCTSTR lpszPathName);<br />

se llama cuando se va a salvar un docum<strong>en</strong>to.<br />

void SetModifiedFlag(BOOL bModified = TRUE); marca<br />

el docum<strong>en</strong>to como cambiado.<br />

BOOL IsModified(); comprueba si un docum<strong>en</strong>to está<br />

modificado. 125


Colaboración de Objetos <strong>en</strong> la<br />

Aplicación<br />

AAcceso a unos objetos bj t ddesde d otros: t<br />

Obj Objeto Mé Método d<br />

Docum<strong>en</strong>to GetFirstViewPosition()/GetNextView()<br />

Docum<strong>en</strong>to GetDocTemplate()<br />

Vista GetDocum<strong>en</strong>t()<br />

Vista GetPar<strong>en</strong>tFrame()<br />

V<strong>en</strong>tana marco del docum<strong>en</strong>to GetActiveView()<br />

V<strong>en</strong>tana marco del docum<strong>en</strong>to GetActiveDocum<strong>en</strong>t()<br />

V<strong>en</strong>tana principal (MDI) MDIGetActive()<br />

V<strong>en</strong>tana marco GetActiveFrame()


Colaboración de Objetos <strong>en</strong> la<br />

Aplicación<br />

CWinApp pp<br />

1<br />

1<br />

m_pMainWnd<br />

CFrameWnd<br />

1<br />

1<br />

CView<br />

1..*<br />

getPar<strong>en</strong>t();<br />

1<br />

CDocum<strong>en</strong>t<br />

getActiveView();<br />

g ();<br />

{POSITION p=GetFirstViewPosition();<br />

GetNextView(p);}<br />

getDocum<strong>en</strong>t();<br />

g ();


Arquitectura Docum<strong>en</strong>to Vista<br />

Serialización<br />

GGuardar/leer d /l los l ddatos dde di disco.<br />

virtual void Serialize(CArchive& ar); provisto por CObject.<br />

Sirve para leer y escribir. escribir<br />

Se usan los operadores > sobre el CArchive.<br />

void CSDI2Doc::Serialize(CArchive& ar) {<br />

POSITION pos = GetFirstViewPosition(); // m_viewList conti<strong>en</strong>e lista punteros a vistas<br />

CSDI2View* pView = dynamic_cast(GetNextView(pos));<br />

if (ar.IsStoring()){<br />

}<br />

}<br />

else {<br />

}<br />

pView->UpdateData(TRUE);<br />

pView >UpdateData(TRUE);<br />

ar nombre;<br />

ar direccion;<br />

ar edad;<br />

ar >> pView->nombre;<br />

ar >> pView->direccion;<br />

ar >> pView pView->edad; >edad;<br />

pView->UpdateData(FALSE);<br />

128


Arquitectura Docum<strong>en</strong>to Vista<br />

Serialización<br />

class CSDI2Doc : public CDocum<strong>en</strong>t {<br />

//..<br />

private: p<br />

CSDI2View* pView;<br />

CSDI2View* getView();<br />

// …<br />

};<br />

inline CSDI2View* CSDI2Doc::getView(){<br />

if (!pView) {<br />

}<br />

return pView;<br />

}<br />

void CSDI2Doc::Serialize(CArchive& ar){<br />

getView();<br />

POSITION pos p = GetFirstViewPosition(); ();<br />

pView = dynamic_cast(GetNextView(pos));<br />

if (ar.IsStoring()) {<br />

pView->UpdateData(TRUE);<br />

p p ( )<br />

ar nombre direccion edad;<br />

}<br />

else {<br />

ar >> pView->nombre >> pView->direccion >> pView->edad;<br />

pView->UpdateData(FALSE);<br />

}<br />

}<br />

// el ev<strong>en</strong>to salvar llama por defecto a la serialización del docum<strong>en</strong>to<br />

129


Arquitectura q Docum<strong>en</strong>to Vista<br />

Creación de un nuevo docum<strong>en</strong>to<br />

BOOL CSDI2Doc::OnNewDocum<strong>en</strong>t()<br />

{<br />

if (!CDocum<strong>en</strong>t::OnNewDocum<strong>en</strong>t())<br />

return t FALSE; FALSE<br />

}<br />

// TODO: agregar aquí código de reinicio<br />

// (los docum<strong>en</strong>tos SDI volverán a utilizar este docum<strong>en</strong>to)<br />

getView()->nombre="";<br />

pView->direccion="";<br />

pView pView->edad=0; >edad=0;<br />

pView->UpdateData(FALSE);<br />

return TRUE;<br />

130


Ejemplo


Indice<br />

<strong>Programación</strong> g bajo j <strong>Windows</strong>.<br />

Introducción a las <strong>MFCs</strong>.<br />

Arquitectura Docum<strong>en</strong>to/Vista<br />

Docum<strong>en</strong>to/Vista.<br />

Aspectos avanzados de las <strong>MFCs</strong>.<br />

Diálogos no modales.<br />

Creación Creación dinámica de widgets. widgets<br />

Registro.<br />

Otros aspectos de las <strong>MFCs</strong>.<br />

Bibliografía<br />

Bibliografía.<br />

132


Diálogos No Modales<br />

PPara ejecutar j t diálogos diál <strong>en</strong> fformal l modal, d l<br />

simplem<strong>en</strong>te hay que llamar al método<br />

DoModal().<br />

Para crear un diálogo no modal, hay que<br />

hacerlo como si fuera una v<strong>en</strong>tana cualquiera,<br />

mediante Create().<br />

Esto crea el diálogo y continúa la ejecución.<br />

Por tanto el diálogo se debe crear usando memoria<br />

dinámica!<br />

Liberación de la memoria <strong>en</strong> OnNcDestroy() y() del<br />

diálogo. Aquí se pued<strong>en</strong> pasar datos a la<br />

v<strong>en</strong>tana principal.<br />

133


void CGraficosSDIApp::OnAppAbout() {<br />

}<br />

Diálogos No Modales<br />

if (!pAboutDlg) {<br />

Ejemplo: About No Modal<br />

pAboutDlg = new CAboutDlg(); // puntero miembro<br />

pAboutDlg->Create( MAKEINTRESOURCE(CAboutDlg::IDD), // string con ID<br />

CWnd::GetDesktopWindow()); // puntero al escritorio,<br />

// evita que el diálogo esté siempre <strong>en</strong>cima<br />

pAboutDlg->ShowWindow(SW_SHOW);<br />

}<br />

else pAboutDlg->SetForegroundWindow(); // el diálogo ya existía, llevarlo al fr<strong>en</strong>te<br />

void CGraficosSDIApp::CloseDialog() { // acciones al cerrar el diálogo<br />

pAboutDlg g = 0; // simplem<strong>en</strong>te apunta a NULL<br />

}<br />

void CAboutDlg::OnNcDestroy() { // último m<strong>en</strong>saje que se recibe antes de cerrar<br />

CDialog::OnNcDestroy();<br />

((CGraficosSDIApp*)AfxGetApp())->CloseDialog(); // avisar a la aplicación, podríamos avisar a la v<strong>en</strong>tana padre<br />

// otra posibilidad es mandarle un m<strong>en</strong>saje definido por el<br />

// usuario con GetPar<strong>en</strong>t()->PostMessage(WM_USR,0,0)<br />

delete this; // importante: borramos la memoria dinámica<br />

}<br />

void CAboutDlg::OnOK() { // importante sobreescribir si se ti<strong>en</strong>e un IDOK, ya que por defecto MFC llama a<br />

// EndDialog(), que sólo vale para DoModal()<br />

if(UpdateData(true))<br />

DestroyWindow();<br />

}


Creación dinámica de widgets<br />

void CSDI2View::OnBnClickedButton1()<br />

{<br />

CButton* pButton=new CButton;<br />

pButton->Create("Submit",<br />

pButton Create( Submit ,<br />

WS_CHILD | WS_VISIBLE,<br />

CRect(170, 120, 270, 143),<br />

this, ,<br />

0x302); // un ID<br />

}<br />

135


Registro<br />

La mayoría de las aplicaciones dejan cierto grado de customización al<br />

usuario.<br />

Por ejemplo: posición y tamaño de la v<strong>en</strong>tana v<strong>en</strong>tana, posición de las barras<br />

de controles, etc.<br />

Guardar esta información de configuración <strong>en</strong> el registro (hasta<br />

windows 3.11, esta información se guardaba <strong>en</strong> ficheros INI).<br />

En InitInstance() se llama a SetRegistryKey() SetRegistryKey(), para establecer una<br />

clave (se crea debajo de HKEY_CURRENT_USER/software).<br />

SetRegistryKey() asigna valor al atributo m_pszRegistryKey de la clase<br />

CWinApp. pp<br />

El resto de llamadas del API (GetProfileString(), GetProfileInt(),<br />

WriteProfileString(), g() WriteProfileInt()) ())<br />

utilizan dichos métodos.


Registro<br />

BOOL CGraficosSDIApp::InitInstance()<br />

{<br />

//…<br />

SetRegistryKey(_T("GraficosSDI"));<br />

LoadStdProfileSettings(4); // Cargar opciones de archivo INI estándar<br />

// (incluidas las de la lista MRU)<br />

//…<br />

}<br />

Normalm<strong>en</strong>te se leerá la información del registro <strong>en</strong><br />

“OnCreate()” de la v<strong>en</strong>tana marco.<br />

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)<br />

{<br />

if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;<br />

WINDOWPLACEMENT PosV<strong>en</strong>;<br />

if (LeePosicionV<strong>en</strong>tana(&PosV<strong>en</strong>)) SetWindowPlacem<strong>en</strong>t(&PosV<strong>en</strong>);<br />

//…<br />

}


Registro<br />

bool CMainFrame::LeePosicionV<strong>en</strong>tana(LPWINDOWPLACEMENT pPosV<strong>en</strong>)<br />

{<br />

CString strClave = AfxGetApp()->GetProfileString(_T("Arranque"), _T("Posicion"));<br />

if (strClave.IsEmpty()) return false;<br />

int numDatos = sscanf_s(strClave, "%u,%u,%d,%d,%d,%d,%d,%d,%d,%d",<br />

&pPosV<strong>en</strong>->flags, &pPosV<strong>en</strong>->showCmd, &pPosV<strong>en</strong>->ptMinPosition.x,<br />

&pPosV<strong>en</strong>->ptMinPosition.y, &pPosV<strong>en</strong>->ptMaxPosition.x, &pPosV<strong>en</strong>->ptMaxPosition.y,<br />

&pPosV<strong>en</strong>->rcNormalPosition.left, &pPosV<strong>en</strong>->rcNormalPosition.top,<br />

&pPosV<strong>en</strong>->rcNormalPosition.right, &pPosV<strong>en</strong>->rcNormalPosition.bottom);<br />

if (numDatos != 10) return false;<br />

pPosV<strong>en</strong>->l<strong>en</strong>gth=sizeof(pPosV<strong>en</strong>);<br />

return true;<br />

}


Registro<br />

void id CM CMainFrame::OnClose()<br />

i F O Cl ()<br />

{<br />

WINDOWPLACEMENT PosV<strong>en</strong>;<br />

PosV<strong>en</strong>.l<strong>en</strong>gth=sizeof(PosV<strong>en</strong>);<br />

if (G (GetWindowPlacem<strong>en</strong>t(&PosV<strong>en</strong>))<br />

tWi d Pl t(&P V ))<br />

{<br />

if (PosV<strong>en</strong>.showCmd!=SW_SHOWMINIMIZED)<br />

EscribirPosicionV<strong>en</strong>tana(&PosV<strong>en</strong>);<br />

}<br />

}<br />

CFrameWnd::OnClose();<br />

void CMainFrame::EscribirPosicionV<strong>en</strong>tana(LPWINDOWPLACEMENT pPosV<strong>en</strong>)<br />

{<br />

TCHAR szBuffer[8*6+2*5+9+1];<br />

}<br />

wsprintf(szBuffer, i tf( B ff "%u,%u,%d,%d,%d,%d,%d,%d,%d,%d",<br />

"% % %d%d%d%d%d%d%d%d"<br />

pPosV<strong>en</strong>->flags, pPosV<strong>en</strong>->showCmd, pPosV<strong>en</strong>->ptMinPosition.x,<br />

pPosV<strong>en</strong>->ptMinPosition.y, pPosV<strong>en</strong>->ptMaxPosition.x, pPosV<strong>en</strong>->ptMaxPosition.y,<br />

pPosV<strong>en</strong>->rcNormalPosition.left, pPosV<strong>en</strong>->rcNormalPosition.top,<br />

pPosV<strong>en</strong>->rcNormalPosition.right, P V > N lP iti i ht pPosV<strong>en</strong>->rcNormalPosition.bottom);<br />

P V > N lP iti b tt )<br />

AfxGetApp()->WriteProfileString(_T("Arranque"), _T("Posicion"), szBuffer);


Otros aspectos de las <strong>MFCs</strong><br />

Bases de datos<br />

Sincronización<br />

Sincronización<br />

<strong>Windows</strong> sockets<br />

Servicios Internet<br />

140


Indice<br />

<strong>Programación</strong> bajo <strong>Windows</strong>.<br />

Introducción Introducción a las <strong>MFCs</strong>. <strong>MFCs</strong><br />

Arquitectura Docum<strong>en</strong>to/Vista.<br />

Aspectos avanzados de las <strong>MFCs</strong>.<br />

Bibliografía<br />

Bibliografía.<br />

141


Bibliografía<br />

MSDN (ayuda <strong>en</strong> línea) línea).<br />

“<strong>Programación</strong> Avanzada <strong>en</strong> <strong>Windows</strong> 2000 con Visual<br />

C++ y MFC”. Pascual, J., Charte, F., Segarra, g M. J., de<br />

Antonio, A., Clavijo, J. A. McGraw Hill. 2000.<br />

MFC:<br />

http://www http://www.functionx.com/visualc/<br />

functionx com/visualc/<br />

http://www.dcp.com.ar/mfc/indice.htm<br />

http://www.uta.fi/~jl/pguibook/<br />

http://www http://www.samspublishing.com/library/library.asp?b=Visual_C_<br />

samspublishing com/library/library asp?b Visual C<br />

PlusPlus&rl=1 (libro “Visual C++ Unleashed”)<br />

Docum<strong>en</strong>tación MFC al estilo de javadoc:<br />

http://www http://www.cppdoc.com/example/mfc/mfc.html<br />

cppdoc com/example/mfc/mfc html<br />

Controles<br />

http://www.functionx.com/visualc/controls/<br />

142

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!