Vous êtes sur la page 1sur 142

Programacin en Windows y MFCs

Tema 6

Grupo 46 TACC II Curso 2008/09 1

Indice
Programacin bajo Windows.
Introduccin. Introduccin Hola mundo!. El API de Windows.
Introduccin a las MFCs MFCs. Arquitectura Documento/Vista. Aspectos avanzados de las MFCs. g Bibliografa.
2

Programacin Bajo Windows


Proramacin orientada a eventos en contraste con la programacin eventos, para MS-DOS, que es secuencial. Evento: Algo que sucede en el sistema (click de ratn movimiento ratn, de ratn, pulsacin de una tecla, etc.) Windows convierte estos eventos en mensajes (aaden informacin a los eventos). P.ej.: cuando se hace click con el ratn, el mensaje incluye las coordenadas, la ventana sobre la que se puls, etc. Windows pasa el mensaje a la parte interesada (ej. la ventana sobre la que se hizo click). La aplicacin puede obviar el mensaje, o puede tener cdigo que la haga reaccionar.
3

Programacin Bajo Windows


Estructura genrica de una aplicacin windows:
1. Iniciar la aplicacin. p
Iniciar la aplicacin y la instancia. En las versiones de 32 bits se inicializa la aplicacin cada vez que se inicializa la instancia. En las versiones de 16 bits slo con la 1 instancia (compartir informacin, ahorro memoria). Todas las aplicaciones tienen una o ms ventanas (hay excepciones, excepciones como los controladores de dispositivo) dispositivo). Clases (tipos) de ventanas definidas mediante parmetros. Registro de la clase de ventana. Esto se hace al inicializar la aplicacin. Al inicializar la instancia, se crea una ventana de la clase definida. Hay H que d el nombre d l ventana, sus coordenadas, dar l b de la t d d dimensiones, men, etc.

2. 3. 3 4.

Esperar que llegue algn mensaje. Reaccionar ante el mensaje recibido recibido. Volver a 2.

Programacin Bajo Windows


Estructura genrica de una aplicacin windows:
1. Iniciar la aplicacin. 2. Esperar que llegue algn mensaje.
Bucle de captura de mensajes. Filtrar los mensajes que van a la aplicacin, adaptarlos y hacerlos ll h l llegar a l ventana correspondiente. la t di t Procedimiento de ventana, recibe mensaje y adopta uno u otro comportamiento.

3. Reaccionar ante el mensaje recibido. 4. Volver a 2.


5

#include "stdafx.h" #include <windows.h> // Crear un proyecto win32 application vaco (o Hello World en VC 6.0) LRESULT CALLBACK G GestorMensajes( M j ( HANDLE hW d hWnd, UINT mensaje, WPARAM wParam, LPARAM lParam) { HDC hDc; // Device context PAINTSTRUCT ps; // Estructura de dibujado RECT rect; // Rectngulo cliente

Hola Mundo!

switch (mensaje) { case WM_PAINT: hDc BeginPaint((HWND)hWnd, & ) hD = B i P i t((HWND)hW d &ps); GetClientRect((HWND)hWnd,&rect); DrawText(hDc, TEXT("Hola Mundo!), -1, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER); EndPaint((HWND)hWnd, &ps); break; b k case WM_DESTROY: PostQuitMessage(0); break; default: t d f lt return DefWindowProc((HWND)hWnd,mensaje,wParam,lParam); D fWi d P ((HWND)hW d j P lP ) } 6 return (NULL); }

Hola Mundo!
BOOL IniciaAplicacion (HINSTANCE hInstance) { WNDCLASS wc; C SS wc.style = CS_HREDRAW | CS_VREDRAW; //Estilo de la clase wc.lpfnWndProc wc lpfnWndProc = (WNDPROC)GestorMensajes; // Procedimiento gestor wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; // Instancia hI t hI t I t i wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Icono de la ventana wc.hCursor = LoadCursor(NULL, IDC_ARROW); // cursor de la ventana wc.hbrBackground = (HBRUSH)GetStockObject(WHITE BRUSH); // Color de fondo (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; // Nombre del men asociado wc.lpszClassName = TEXT("ClaseVentana); // Nombre de la clase de la ventana return (RegisterClass(&wc)); }
7

Hola Mundo!
BOOL IniciaInstancia(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hWnd = CreateWindow( TEXT("ClaseVentana), // Clase de ventana a la que pertenece (caract. UNICODE) TEXT("TACC II, grupo 46, curso 2008/09),// Ttulo de la ventana WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL, // Estilo _ | _ | _ CW_USEDEFAULT, // Posicion X por defecto CW_USEDEFAULT, // Posicion Y por defecto CW_USEDEFAULT, // Anchura por defecto CW_USEDEFAULT, // Altura por defecto NULL, // Sin ventana padre NULL, // Sin menu hInstance, // Instancia NULL); // Parametros if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); // dice cmo mostrar la ventana UpdateWindow(hWnd); // actualiza la ventana: genera un evento WM_PAINT return TRUE; }
8

Hola Mundo!
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG Mensaje; BOOL bret; if (!hPrevInstance){ if (!IniciaAplicacion(hInstance)) return FALSE; } if (!IniciaInstancia(hInstance, nCmdShow)) return FALSE; while ((bret = GetMessage(&Mensaje, NULL, NULL, NULL)) != 0) { TranslateMessage(&Mensaje); // traduce de teclas convencionales a WM_CHAR DispatchMessage(&Mensaje); // hace llegar el mensaje al proc. de ventana } return (Mensaje.wParam); }
9

La clase de Ventana
typedef struct { UINT style; // combinacin de estilos de clase WNDPROC lpfnWndProc; // Puntero al procedimiento de ventana int cbClsExtra; // num. bytes extra a asignar seguidos a esta estructura int cbWndExtra; // num. bytes extra a asignar seguidos a la instancia HINSTANCE hInstance; // handle a la instancia que contiene el proc. ventana HICON hIcon; // handle al icono de la clase (si NULL se da uno por def). HCURSOR hCursor; // handle al cursor de la clase HBRUSH hbrBackground; // handle a brocha para color de fondo, o un color LPCTSTR lpszMenuName; // nombre del men asociado LPCTSTR lpszClassName; // nombre de la clase de ventana } WNDCLASS, *PWNDCLASS;

Tipos de clases de ventana: del sistema (ej.: BUTTON, COMBOBOX, etc.), etc ) globales y locales de aplicacin aplicacin. Algunos estilos: CS_HREDRAW, CS_VREDRAW (redibuja la venta entera si hay un cambio de tamao horizontal), CS_NOCLOSE,. La estructura WNDCLASSEX permite asociar un icono pequeo a la

ventana (RegisterClassEx).

10

Inicializacin de la Instancia
HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int i t x, int y, int nWidth, int nHeight nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance hInstance, LPVOID lpParam ); // nombre registrado clase de ventana // ttulo de la ventana // estilo de la ventana // posicin h i i i horizontal d l ventana t l de la t // posicin vertical de la ventana // anchura de ventana // altura de ventana // handle de la ventana padre // handle del men de ventana // handle a la instancia de la aplicacin // puntero a parmetros.

Creacin d una ventana d una clase registrada. C i de t de l i t d CreateWindowEx para estilos extendidos (ej.: layered windows windows-> ventanas no rectangulares o que cambian de forma) 11

Estilos de Ventana
WS_BORDER: ventana con borde fino. WS_CAPTION: ventana con barra de ttulo (incluye WS_BORDER). WS_CHILD, WS_CHILDWINDOW WS CHILD WS CHILDWINDOW : ventana hij ( puede t t hija (no d tener men ni puede usarse con i d WS_POPUP). WS_CLIPCHILDREN: Excluye el rea ocupada por las ventanas hijas cuando se dibuja e la padre. Se usa cuando se crea la ventana padre. WS_CLIPSIBLINGS: WS CLIPSIBLINGS: WS_DISABLED: crea una ventana deshabilitada. WS_DLGFRAME: ventana con borde igual al de las cajas de dilogo. WS_GROUP: Primer control de un grupo. WS_HSCROLL: ventana con scrooll horizonta. WS_ICONIC, WS_MINIMIZE: ventana inicialmente minimizada. WS_MAXIMIZE: ventana inicialmente maximizada. WS_MAXIMIZEBOX, WS_MINIMIZEBOX : ventana con botn de maximizar/minimizar. _ , _ WS_OVERLAPPED, WS_TILED; ventana con ttulo y borde. WS_OVERLAPPEDWINDOW, WS_TILEDWINDOW: ventana con estilos: WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, y WS_MAXIMIZEBOX WS_POPUP: ventana de pop-up. WS_POPUPWINDOW : ventana de pop-up con WS_BORDER, WS_POPUP, y WS_SYSMENU WS_SIZEBOX, WS_THICKFRAME: ventana con borde redimensionable. WS SYSMENU: ventana co men de s ste a S_S S U e ta a con e sistema. WS_TABSTOP: control que recibe el foco cuando se pulsa TAB. 12 WS_VISIBLE: ventana inicialmente visible. WS_VSCROLL: ventana con barra de desplazamiento vertical.

Estilos de Ventana
Men de sistema Barra de ttulo Botones minimizar/ maximizar/cerrar

borde Area cliente

Scroll horizontal

Scroll vertical

13

Mensajes
Mensajes: M j
typedef struct { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; ; POINT pt; } MSG, *PMSG;

// handle a la ventana que recibe el mensaje // identificador del mensaje // info adicional, dependiente del tipo de mensaje // info adicional, dependiente del tipo de mensaje // instante en el que el mensaje fue enviado q j // posicin del cursor en coordenadas de pantalla

Todos los mensajes que enva windows empiezan por WM XXX y estn definidos en windows h WM_XXX windows.h
14

GetMessage
GetMessage: Espera a que llegue un mensaje mensaje.
BOOL GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax );

lpMsg: Puntero a la estructura MSG que recibe el mensaje hWnd: Handle de la ventana que recibe los mensajes. wMsgFilterMin: Menor valor entero del mensaje a recibir (ej.: WM_KEYFIRST, WM_MOUSEFIRST o WM_INPUT) wMsgFilterMax: Mayor valor entero del mensaje a recibir (ej.: WM_KEYFIRST, WM_MOUSEFIRST o WM_INPUT) Retorno:
Si se devuelve un mensaje distinto de WM_QUIT, el valor es distinto de cero. Si el mensaje es WM_QUIT, el valor es cero. Si hay un error el valor es -1. Por ejemplo, esto sucede si hWnd es un handle de ventana invlida o lpWnd es un puntero invlido invlido.
15

DispatchMessage
MSG
hwnd=h

DispatchMessage

instancias de ventana

hinstance=h lpClassName = CN

hinstance=h1 lpClassName = CN

hinstance=h2 lpClassName = CN2

hinstance=h3 lpClassName=CN3

WNDCLASS lpszClassName = CN lpfnWndProc proc lpfnWndProc=proc

lpszClassName = CN2 lpfnWndProc proc2 lpfnWndProc=proc2

lpszClassName = CN3 lpfnWndProc proc3 lpfnWndProc=proc3

clases de ventana registradas


LRESULT CALLBACK proc (HANDLE hWnd, UINT mensaje, WPARAM wParam, LPARAM lParam){..} LRESULT CALLBACK proc2 (HANDLE hWnd, UINT mensaje, WPARAM wParam, LPARAM lParam){..} LRESULT CALLBACK proc3 (HANDLE hWnd, UINT 16 mensaje, WPARAM wParam, LPARAM lParam){..}

Handles
Un identificador para los distintos objetos: ventanas ventanas, controles (que son ventanas), ficheros, imgenes, memoria, etc. Similar a punteros: se obtienen y luego se destruyen.

17

Gestionar un nuevo evento


LRESULT CALLBACK GestorMensajes( HANDLE hWnd, hWnd UINT mensaje, WPARAM wParam, LPARAM lParam)

{ HDC hDc; // // Device context

switch (mensaje) { case WM_LBUTTONDOWN: MessageBox((HWND)hWnd, TEXT("Button click"), TEXT("dialogo"), MB_ICONHAND); break; default: return DefWindowProc((HWND)hWnd,mensaje,wParam,lParam); } return (NULL); }

18

Juegos de Caracteres
~1890: BCDIC (6 bit 64 caracteres). 1890 bits->64 t ) ~1950: ASCII (7 bits->128 caracteres). ( ) ASCII extendido (8 bits->256 caracteres).
pginas de cdigos regionales para los ltimos 128.

DBCS: los primeros 128 bytes igual que ASCII, los posteriores ocupan dos bytes. Unicode: U i d 16 bit (65536 caracteres). bits t )
Sistema de doble anchura (wide char).
19

Caracteres Unicode
Tipo de datos wchar_t. j _ [ ] j p Ej.: wchar_t nombre[50]=LBjarne Stroustrup. Mejor usar macros, que aseguran que el programa funciona en Unicode o ASCII:
TCHAR * Nombre = TEXT(Hola);

20

La Notacin Hngara
Convencin para los nombres de variables (uso de prefijos), de tal manera que al leerlos sepamos su tipo. Despus del prefijo se empieza por maysculas. Ejemplo: hWnd es un handle (h) a una ventana. lpfnWndProc es un puntero (p) largo (l) a una funcin (fn).
Tipo de Dato char BYTE(unsigned char) short int int cuando indica coordenadas int cuando indica dimensiones WORD (unsigned int) LONG (long) Prefijo c by n i x, y cx, cy y w l Tipo de Dato DWORD(unsigned long) BOOL(int) o Flag Handle Puntero Funcin Cadena Cadena terminada en \0 Prefijo dw bf h p fn s sz

El API de Windows
Llamadas al sistema operativo almacenadas en DLLs operativo, DLLs. Win32, WinSock, WinInet, ODBC, etc. Dentro de Win32 se engloban como extensiones el resto de las API que se puedan aadir a Windows. Win32 proprociona un entorno de programacin comn a la plataforma Windows: 3.1 (win32s), 95/98, NT4.0, 2000, CE, XP, Vista. Vista En algunas plataformas el win32 (p. ej. CE) no est implementada en su totalidad totalidad. Win32: CreateWindow(), RegisterClass(), UpdateWindow(), DrawText(), etc. UpdateWindow() DrawText() etc ShowWindow(),
22

Win32
Varias categoras de funciones:
Administracin de ventanas (en user32.dll)
Crear y administrar la GUI, despachar mensajes, administrar ventanas, DDE ventanas DDE. Ej.: CreateWindow(), RegisterClass(), ShowWindow()

Graphics Device Interface (GDI).


Generar salidas en di ti t di G lid distintos dispositivos: pantalla, i iti t ll impresora. P j P.ej.: dibujar objetos. Ej.: BeginPaint(), GetClientRect(), DrawText(), EndPaint().

Media C t l I t f M di Control Interface (MCI) (MCI).


Reproducir y Grabar Audio, uso de vdeo, control de dispositivos multimedia.

Servicios del Sistema. S i i d l Si t


Administracin de memoria, archivos y procesos, funciones de trabajo en red, informacin del sistema, IPC.

Remote Procedure Call (RPC).


23

Bibliotecas de Extensin
Proporcionan servicios a l apliciones P i i i las li i fuera del mbito del Win32.
Controles comunes. Cuadros de dilogo comunes. Descompresin de datos. Administracin de intercambio dinmico de datos (DDE). Instalacin de archivos. Intercambio dinmico de datos sobre redes. ...
24

Indice
Programacin bajo Windows.

Introduccin a las MFCs MFCs.


Introduccin. Ventana vaca sin el wizard wizard. Uso del wizard. Un vistazo a las clases de MFC MFC. Mapas de Mensajes. Mens y Teclas Aceleradoras Aceleradoras. Dilogos Comunes. Controles. Clases de utilidad Arquitectura Documento/Vista. Aspectos avanzados de las MFCs. Bibliografa.

25

Microsoft Foundation Classes


El API para l programacin di la i directa d aplicaciones Wi d de li i Windows d da acceso total a la funcionalidad del sistema operativo, pero es de bajo nivel. MFC es un framework que ofrece una serie de funciones, constantes, constantes tipos de datos y clases que simplifica la creacin de aplicaciones para las distintas plataformas Windows. Es la respuesta de Microsoft a frameworks de otras compaias como OWL de Borland. Visual C++ contiene un asistente (wizard) que facilita la creacin de aplicaciones MFC (generacin de cdigo).
26

Clases Bsicas para la creacin de ventanas

27

Secuencia de Creacin de una Aplicacin

28

#include "stdafx.h" #include <afxwin.h> #i l d < f i h> // MFC core and standard components d t d d t #include <afxext.h> // MFC extensions // proyecto con Shared DLL #ifdef _DEBUG #define new DEBUG NEW DEBUG_NEW #endif

Creacin de una Ventana en Blanco sin el wizard l i d

class CMainFrame : public CFrameWnd { p public: CMainFrame() { Create(NULL, _T("Hellow World Application")); } // suele ir en OnCreate() }; // se suele llamar a LoadFrame class HelloWorldApp : public CWinApp { public: virtual BOOL I itI t it l InitInstance(); () }; HelloWorldApp theApp; // Declarar un unico objecto CWinApp BOOL HelloWorldApp::InitInstance() { CWinApp::InitInstance(); g y y(_ ( pp )) SetRegistryKey(_T("Hello World Application")); CMainFrame* pFrame = new CMainFrame; if (!pFrame) return FALSE; m_pMainWnd = pFrame; pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); F U d t Wi d () return TRUE; } //NOTA: El WinMain est dentro del framework MFCs

29

Uso del Asistente


Configuracin Inicial de la Aplicacin
File/new Project; seleccionar MFC Application

30

Uso del Asistente


Configuracin Inicial de la Aplicacin

Configurar el tipo de aplicacin: Single document Sin soporte de arquitectura Documento/Vista. Documento/Vista MFC en librera esttica (incluye en el exe las DLLs necesarias)

31

Uso del Asistente


Configuracin Inicial de la Aplicacin
Configurar el soporte para BBDD

32

Uso del Asistente


Configuracin Inicial de la Aplicacin
Configurar la interfaz de usuario

33

Uso del Asistente


Configuracin Inicial de la Aplicacin
Configurar nombre de las clases y de los ficheros que se van a generar

34

Uso del Asistente


Aplicacin Generada

35

Uso del Asistente


Qu ficheros se han generado?

Definicin de D fi i i d nombres d l recursos, para b de los poder ser usados por la aplicacin. Fichero de recursos (.rc y .rc2). ( ) Clase de la ventana de trabajo (hereda de CWnd), dentro de la ventana marco Clase Aplicacin (hereda de CWinApp) Clase de la ventana marco (hereda de CFrameWnd) Cabeceras precompiladas. stdafx.h incluye las cabeceras comunes del sistema Se ha de incluir sistema. antes que cualquier otra 36

Uso del Asistente


Recursos de la Aplicacin

Resource.h
#define IDD_ABOUTBOX #define IDP_OLE_INIT_FAILED #define IDR_MAINFRAME IDR MAINFRAME #define IDR_HelloMFCsTYPE 100 100 128 129

37

Uso del Asistente


Estructura de la Aplicacin
WinMain(): Wi M i ()
Dentro del framework. Se llama a mtodos miembros del nico objeto de tipo CWinApp:
InitApplication(): Normalmente no hay que tocar este mtodo. InitInstance(): Tareas generales de la aplicacin, ej: inicializar OLE. Despus se crean las ventanas de la aplicacin, y se hacen visibles (ShowWindow()) Run(): Que implementa al bucle de mensajes hasta que llega WM_QUIT.

CWinApp:
Clase que hay que subclasificar, se debe crear un objeto nico global. Procesa mensajes hasta que llega WM_QUIT, momento en el que ejecuta ExitInstance() por defecto defecto. Si no hay mensajes, llama a onIdle(), vaca por defecto.

38

Sec cuenc de Creacin de cia e n una Apli a icaci n

39

Uso del Asistente


Estructura de la Aplicacin: La clase ventana (CWnd)
Casi todas las li C i t d l aplicaciones ti i tienen una o ms ventanas. t La clase base es CWnd.
Contiene un handle a la ventana fsica de Windows. La ventana fsica se crea mediante Create(), se destruye con el destructor de la subclase de CWnd. Parmetros de Create(): lpszClassName: nombre de la clase registrada con AfxRegisterWindowClass() o NULL (atributos por defecto). lpszWindowName: nombre de la ventana. dwStyle: Estilo de la ventana a crear. rect: Referencia a un objeto constante de tipo RECT, para indicar posicin y tamao de la ventana. pParentWindow: puntero al objecto CWnd padre de la ventana. No puede ser NULL Si l ventana es l principal, usar d NULL. la la i i l CreateWindowEx(). nId: Identificador de la ventana. pContext: P t C t t Puntero a un objeto d ti CC t C t t para bj t de tipo CCreateContext, asociar vistas y documentos a la ventana, puede ser NULL. 40

Uso del Asistente


Estructura de la Aplicacin: La clase ventana (CWnd)
CWnd CW d agrupa acciones que se podan realizar sobre ventanas. i d li b t Las hace ms accesibles y seguras. Evita por ejemplo tener q p p j p que pasar el handle como primer parmtero p p (almacenado en el atributo m_hWnd). Ejemplo:
los mtodos de CWnd:
void CWnd::MoveWindow( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE ); void CWnd::MoveWindow( LPCRECT lpRect, BOOL bRepaint = TRUE );

encapsulan la llamada a la API de Windows:


BOOL MoveWindow( HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);

41

Uso del Asistente


Estructura de la Aplicacin: La clase CFrameWnd
Hereda de CWnd, H d d CW d es utilizado en aplicaciones SDI tili d li i SDI. Tiene en su interior una ventana hija que normalmente ser la ventana principal de la aplicacin. La ventana marco interacciona con el usuario cambiando el tamao entana s ario tamao, movindose, etc., y gestiona estos cambios provocando modificaciones en la ventana hija. Para crear una ventana marco: Create(), LoadFrame(), que toma menos parmetros. Toma valores por defecto de los recursos que se le pasan como parmetros: men ttulo icono y men, ttulo, tabla de teclas acelaradoras.
virtual BOOL LoadFrame( UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL );

Se destruye llamando a DestroyWindow(). Sus clases derivadas deben declarar DECLARE DYNCREATE() (gestin DECLARE_DYNCREATE() dinmica de clases) si se usa la arquitectura documento/vista, y poner IMPLEMENT_DYNCREATE() en la implementacin.

42

Uso del Asistente


Handles
Las clases de la MFC ocultan los handles (CWnd::m_hWnd), para facilitar su uso uso. Se pueden construir objetos a partir de elementos grficos ya construidos:
static CWnd* PASCAL FromHandle( HWND hWnd ) );

El objeto devuelto es temporal (eliminado en prxima llamada a OnIdle()). Clases que encapsulan handles a objetos grficos: Elemento Grfico HWND HDC HMENU HPEN, HBRUSH, HFONT, HBITMAP, HPALETTE, HRGN HIMAGELIST SOCKET Clase de Objeto CWnd y derivadas CDC y derivadas CMenu CGdiObject CImageList
43

CSocket

Uso del Asistente


Dnde est el bucle de eventos?
Tabla con los elementos a manejar: el mapa de mensajes. Mediante Macros, normalmente insertadas por el asistente. Declaracin del mapa de mensajes en la clase: DECLARE_MESSAGE_MAP(). DECLARE MESSAGE MAP(). Declaramos tambin los mtodos que manejarn los mensajes mediante afx_msg:
class CMainFrame : public CFrameWnd { public: CMainFrame(); protected: DECLARE_DYNAMIC(CMainFrame) DECLARE DYNAMIC(CM i F ) // Funciones de asignacin de mensajes generadas protected: afx_msg afx msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSetFocus(CWnd *pOldWnd); DECLARE_MESSAGE_MAP() } };
44

Uso del Asistente


Dnde est el bucle de eventos?
Una vez declarado, hay que definir el mapa de mensajes, y enlazar , yq p j , cada mensaje con la funcin que la va a procesar. En el fichero de implementacin (.cpp) se aade: BEGIN_MESSAGE_MAP() //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() Mensajes que ON_WM_SETFOCUS() se van a tratar //}}AFX_MSG_MAP //}}AFX MSG MAP END_MESSAGE_MAP()

Usado por versiones anteriores de Visual C++ C

Los L mensajes no referenciados en l t bl se pasan a l clase j f i d la tabla la l padre (o a la clase de la ventana contenedora), y as sucesivamente hasta que se trate por algn ancestro.
45

Uso del Asistente


Cdigo Generado: HelloMFCs.h
// HelloMFCs.h: archivo de encabezado principal para la aplicacin HelloMFCs HelloMFCs h: #pragma once #ifndef __AFXWIN_H__ #error "incluir 'stdafx h' antes de incluir este archivo para PCH" incluir stdafx.h PCH #endif #include "resource.h" // Smbolos principales

class CHelloMFCsApp : public CWinApp { public: CHelloMFCsApp(); // Reemplazos public: virtual BOOL InitInstance(); // Implementacin public: afx_msg void OnAppAbout(); DECLARE_MESSAGE_MAP() DECLARE MESSAGE MAP() };
46

extern CHelloMFCsApp theApp;

#include "stdafx.h" #include "HelloMFCs.h" #include "MainFrm.h #ifdef _DEBUG DEBUG #define new DEBUG_NEW #endif

Uso del Asistente


Cdigo Generado: HelloMFCs.cpp (i)

BEGIN_MESSAGE_MAP(CHelloMFCsApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, &CHelloMFCsApp::OnAppAbout) END_MESSAGE_MAP() CHelloMFCsApp::CHelloMFCsApp() { // TODO: agregar aqu el cdigo de construccin, Colocar toda la inicializacin importante en InitInstance } CHelloMFCsApp theApp; // El nico objeto CHelloMFCsApp // Inicializacin de CHelloMFCsApp BOOL CHelloMFCsApp::InitInstance() { INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); if (!AfxOleInit()) {// Inicializar bibliotecas OLE AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); SetRegistryKey( T("Aplicaciones g g y y(_ ( p generadas con el Asistente p para aplicaciones local")); p )); CMainFrame* pFrame = new CMainFrame; if (!pFrame) return FALSE; m_pMainWnd = pFrame; // Crear y cargar el marco con sus recursos pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW FWS_ADDTOTITLE, NULL,NULL); pFrame >LoadFrame(IDR MAINFRAME WS OVERLAPPEDWINDOW | FWS ADDTOTITLE NULL NULL); pFrame->ShowWindow(SW_SHOW); // Se ha inicializado la nica ventana; mostrarla y actualizarla 47 pFrame->UpdateWindow(); return TRUE; }

// Cuadro de dilogo CAboutDlg utilizado // para el comando Acerca de class CAboutDlg : public Cdialog { public: CAboutDlg();

Uso del Asistente


Cdigo Generado: HelloMFCs.cpp (ii)

// Datos del cuadro de dilogo enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* p ); g ( g pDX); // Implementacin protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) {}

// Compatibilidad con DDX/DDV p

void CAboutDlg::DoDataExchange(CDataExchange* p ) { g g ( g pDX) CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) ( g, g) END_MESSAGE_MAP() // Comando de la aplicacin para ejecutar el cuadro de dilogo void CHelloMFCsApp::OnAppAbout() { pp pp () CAboutDlg aboutDlg; aboutDlg.DoModal(); }

48

#pragma once #include "ChildView h" ChildView.h

Uso del Asistente


Cdigo Generado: MainFrm.h (i)

class CMainFrame : public CFrameWnd { Permite acceder a informacin en tiempo de public: CMainFrame(); ejecucin a la clase (puede usarse la macro protected: DECLARE_DYNAMIC(CMainFrame) DECLARE DYNAMIC(CMainFrame) RUNTIME_CLASS RUNTIME CLASS en l arquitectura la it t // Reemplazos documento/vista) public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL OnCmdMsg(UINT nID, int nCode, void pExtra AFX CMDHANDLERINFO* pHandlerInfo); nID nCode void* pExtra, AFX_CMDHANDLERINFO // Implementacin public: virtual ~CMainFrame(); #ifdef _DEBUG DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // Miembros incrustados de la barra de control CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; CChildView m wndView; m_wndView; // Funciones de asignacin de mensajes generadas protected: afx_msg afx msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSetFocus(CWnd *pOldWnd); DECLARE_MESSAGE_MAP() };

49

#include "stdafx.h" #include "HelloMFCs.h #include "MainFrm.h #ifdef _DEBUG #define new DEBUG NEW DEBUG_NEW #endif IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_WM_SETFOCUS() END_MESSAGE_MAP()

Uso del Asistente


Cdigo Generado: MainFrm.cpp (i)

static UINT indicators[] = {ID SEPARATOR, ID INDICATOR CAPS, ID_INDICATOR_NUM, ID INDICATOR SCRL, }; {ID_SEPARATOR, ID_INDICATOR_CAPS, ID INDICATOR NUM, ID_INDICATOR_SCRL, // Construccin y destruccin de CMainFrame CMainFrame::CMainFrame() {// TODO: agregar aqu el cdigo de inicializacin de miembros } CMainFrame::~CMainFrame() { } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // Crear una vista para ocupar el rea de cliente del marco if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) { TRACE0("No se pudo crear la ventana de vista\n"); return -1; } if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || ) !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("No se pudo crear la barra de herramientas\n"); return -1; /* no se pudo crear */ } if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT))) { TRACE0("No se pudo crear la barra de estado\n"); return -1; /* No se pudo crear */} // TODO: eliminar estas tres lneas si no desea que la barra de herramientas se pueda acoplar m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); 50 DockControlBar(&m_wndToolBar); return 0; }

Uso del Asistente


Cdigo Generado: MainFrm.cpp (ii)
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { // se llama por las MFCs antes de crear fsicamente la ventana. se devuelve != 0 si la creacin debe continuar, 0 en otro caso. if( !CF !CFrameWnd::PreCreateWindow(cs) ) return FALSE W d P C Wi d ( ) FALSE; // TODO: modificar aqu la clase Window o los estilos cambiando CREATESTRUCT cs cs.dwExStyle &= ~WS_EX_CLIENTEDGE; cs.lpszClass = Af R i t W dCl l Cl AfxRegisterWndClass(0); (0) return TRUE; } #ifdef DEBUG #ifd f _DEBUG void CMainFrame::AssertValid() const { CFrameWnd::AssertValid();} void CMainFrame::Dump(CDumpContext& dc) const { CFrameWnd::Dump(dc); } #endif //_DEBUG void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/) { // enviar foco a la ventana de vista m_wndView.SetFocus(); } BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // Permitir que la vista se interrumpa primero en el comando if ( (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) return TRUE dVi O C dM ( ID C d E t H dl I f )) t TRUE; // De lo contrario, proceder con el control predeterminado 51 return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); }

Uso del Asistente


Cdigo Generado: ChildView.h
// ChildView.h: interfaz de la clase CChildView ChildView h: // #pragma once // Ventana de CChildView class CChildView : public CWnd { // Construccin public: CChildView(); // Atributos public: // Operaciones public: // Reemplazos protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); // Implementacin public: virtual ~CChildView(); // Funciones de asignacin de mensajes generadas protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() };

52

Uso del Asistente


Cdigo Generado: ChildView.cpp
#include "stdafx.h" #include "HelloMFCs.h" #include "ChildView h" ChildView.h #ifdef _DEBUG #define new DEBUG_NEW #endif CChildView::CChildView() { } CChildView::~CChildView() { } BEGIN_MESSAGE_MAP(CChildView, CWnd) ON_WM_PAINT() END_MESSAGE_MAP() // Controladores de mensaje de CChildView BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) { if (!CWnd::PreCreateWindow(cs)) return FALSE; y | _ _ cs.dwExStyle |= WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL); return TRUE; } void CChildView::OnPaint() {}
53

Uso del Asistente


Modificando la aplicacin
void CChildView::OnPaint() () { CPaintDC dc(this); // Contexto de dispositivo para dibujo dc.Rectangle(200, 200, 300, 320); g ( , , , ); dc.DrawText( "Hola MFCs!", -1, CRect( 200, 200, 300, 320), DT_SINGLELINE|DT_CENTER| DT_VCENTER); ); }

54

Bucle de Mensajes

Las clases MFC


Arbol jerrquico de clases, con raz CObject. CObject permite persistencia (serialize()), chequeo de consistencia de atributos (AssertValid()), Gestin de excepciones: heredan de CException CException.
ReportError(): muestra la excepcin en una ventana. GetErrorMessage(): descripcin del error.

Gestin de archivos: CFile. Contextos de dispositivo: CDC e hijas:


Acceso al A l rea completa d l ventana: CWi d DC l t de la t CWindowDC. Dibujo en funcin del evento WM_PAINT: CPaintDC.

Gestin de Objetos Grficos: CGdiObject. j j


Gestin de fuentes de letras: CFont. Gestin de mapas de bits de colores: CBitmap. Uso de Brochas: CBrush CBrush. Manejo de plumas: CPen.

56

Las clases MFC


CCmdTarget: clase b CC dT t l base para l gestin d mensajes. la i de j Clases documento: CDocument, con hijas: COleDocument, CHtmlEditDoc, etc. , Gestin de comunicaciones OLE: COleObjectFactory, COleDataSource, COleDropTarget, etc. CWnd: G ti de CW d Gestin d ventanas. t
CFrameWnd e hijas (ventana principal). CSplitterWnd (p p (paneles de ventana). ) CControlBar (gestin de barras de control y estado): CToolBar, CStateBar, CReBar, CDialogBar. CDialog: gestin de ventanas de dilogo. CColorDialog (seleccin dilogo de colores), CPrintDialog (imprimir), CFileDialog (elegir un fichero), CFontDialog (seleccin de fuentes).
57

Las clases MFC


Gestin de vistas en la arquitectura Documento/Vista: q CView.
CEditView: Edicin de textos. CHtmlView: Visualizacin de pginas HTML.

Controles (heredan de CWnd):


Texto esttico (CS (CStatic). ) Texto modificable (CEdit). Listas de elementos: CListBox, CCheckListBox CDrawListBox CListBox CCheckListBox, CDrawListBox, etc.

Clases que no heredan de CObject: Clases de soporte (ej.: CWaitCursor), API servidor de Internet, sincronizacin, etc.
58

Las clases MFC

59

CObject

CCmdTarget

Las clases MFC

60

Las clases MFC

COb bject

61

Mapas de Mensajes
Subclases de CCmdTarget. Declaracin del mapa de mensajes: DECLARE_MESSAGE_MAP(), que nos crea:
Un vector de mensajes privado ( messageEntries) (_messageEntries). Un puntero protegido al inicio del vector (messageMap). Mtodo virtual GetMessageMap(), que devuelve el contenido de messageMap. M

Declaracin de los mtodos que gestionarn los eventos (precederlos de afx_msg). g) Definir la lista que relaciona eventos con las funciones que los gestionan:
BEGIN_MESSAGE_MAP(clase,claseBase) BEGIN MESSAGE MAP(clase claseBase) Sintaxis que depende del tipo de evento: comando, ventana o controles. END_MESSAGE_MAP()
62

Mensajes de Ventana
110 tipos de mensajes, producidos por la ventana que estamos gestionando. Empiezan por WM XX ( E i WM_XX (excepto WM COMMAND) t WM_COMMAND). Se definen en la lista con ON_+<nombre_mensaje>. Ejemplo, para WM PAINT WM RBUTTON DOWN Ej l WM_PAINT, WM_RBUTTON_DOWN:
BEGIN_MESSAGE_MAP(CChildView, CWnd) ON_WM_PAINT() ON WM PAINT() ON_WM_RBUTTON_DOWN() END_MESSAGE_MAP()

Se llama a OnPaint() y a OnRButtonDown(UINT, CPoint). Podemos usar el asistente para gestionar esta lista.
63

Mensajes de Ventana
Ejemplo: Capturar el evento WM_LBUTTONDOWN
//ChildView.h //ChildView h class CChildView : public CWnd { public: CChildView(); p protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); CPoint lastClicked; // Implementacin public: virtual ~CChildView(); // Funciones de asignacin de mensajes generadas protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() public: bli afx_msg void OnLButtonDown(UINT nFlags, CPoint point); };

64

Mensajes de Ventana
Ejemplo: Capturar el evento WM_LBUTTONDOWN
//ChildView.cpp
CChildView::CChildView() : lastClicked ( 1 -1) {} (-1, 1) BEGIN_MESSAGE_MAP(CChildView, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() END MESSAGE MAP() void CChildView::OnPaint() { CPaintDC dc(this); // Contexto de dispositivo para dibujo dc.Rectangle(200, 200, 300, 320); dc.DrawText( "Hola MFCs!", -1, CRect( 200, 200, 300, 320), DT_SINGLELINE|DT_CENTER|DT_VCENTER); DT SINGLELINE|DT CENTER|DT VCENTER); if (lastClicked.x>=0 && lastClicked.y>0) dc.TextOut( lastClicked.x, lastClicked.y, "click"); } void CChildView::OnLButtonDown(UINT nFlags, CPoint point) { lastClicked=point; InvalidateRect(NULL); CWnd::OnLButtonDown(nFlags, point); CW d O LB tt D ( Fl i t) }

65

Mensajes de Ventana
Ejemplo: Capturar el evento WM_LBUTTONDOWN

66

Mensajes de Controles
Eventos que lanza l ventana hij al padre que l E t l la t hija l d la contiene. Ejemplo: el control de edicin manda el mensaje EN_CHANGE cuando se modifica el texto que contiene. Tipos: p
ON_BN_XX: mensajes de botones. ON_EN_XX: mensajes de editores. ON_CB_XX: ON CB XX mensajes d combo-boxes. j de b b ON_LBN_XX: mensajes de listas.

Se mandan mediante el mensaje WM COMMAND WM_COMMAND. WM_NOTIFY, ON_NOTIFY() para que la funcin que gestiona el evento reciba parmetros.
67

Mensajes de Comando
Provienen de mens, barras de herramientas, teclas aceleradoras y botones. Macro ON_COMMAND(evento,metodo).
BEGIN_MESSAGE_MAP(CHelloMFCsApp, CWinApp) BEGIN MESSAGE MAP(CH ll MFC A CWi A ) ON_COMMAND(ID_APP_ABOUT, &CHelloMFCsApp::OnAppAbout) END_MESSAGE_MAP()

68

Mensajes de Comando
Ejemplo: Aadir un elemento de Men

69

Mensajes de Comando
Ejemplo: Aadir el Gestor de Eventos

70

Mensajes de Comando
#pragma once

Ejemplo: ChildView.h

// Ventana de CChildView class CChildView : public CWnd{ public: CChildView(); p protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); private: const int numColores; UINT * const CodigoColor; g CPoint lastClicked; int currentColor; // Implementacin p public: virtual ~CChildView(); // Funciones de asignacin de mensajes g g j generadas protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() public: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); public: afx_msg void OnCambiacolor(); };
71

Mensajes de Comando
CChildView::CChildView() : numColores (4), CodigoColor (new UINT[numColores]), currentColor(0) { lastClicked = CPoint(-1, -1); CodigoColor[0] RGB(0, 0, 0); Black C di C l [0] = RGB(0 0 0) // Bl k CodigoColor[1] = RGB(255, 0, 0); // Red CodigoColor[2] = RGB(0, 255, 0); // Green CodigoColor[3] = RGB(0, 0, 255); // Blue }

Ejemplo: ChildView.cpp

BEGIN_MESSAGE_MAP(CChildView, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON WM LBUTTONDOWN() ON_COMMAND(ID_CAMBIACOLOR, &CChildView::OnCambiacolor) END_MESSAGE_MAP() void CChildVi id CChildView::OnPaint() { O P i t() CPaintDC dc(this); // Contexto de dispositivo para dibujo dc.Rectangle(200, 200, 300, 320); dc.DrawText( "Hola MFCs!", -1, CRect( 200, 200, 300, 320),DT_SINGLELINE|DT_CENTER|DT_VCENTER); if (l tCli k d (lastClicked.x>=0 && l tCli k d 0) { 0 lastClicked.y>0) dc.SetTextColor(CodigoColor[currentColor]); dc.DrawText( "Click", -1, CRect( lastClicked, CPoint(lastClicked.x+50, lastClicked.y+20)), DT_SINGLELINE|DT_CENTER|DT_VCENTER); } }
72

void CChildView::OnCambiacolor() { currentColor = (currentColor + 1) % numColores; }

Mensajes de Comando
Resultado

CChildView::~CChildView() { delete [ ] CodigoColor; }

73

Aplicaciones basadas en dilogos


Se pueden crear aplicaciones basadas en dilogo. Por defecto sin mens ni teclas aceleradoras. Para implementar aplicaciones sencillas, basadas en formularios de toma de datos. La ventana principal hereda de CDialog o de CDialog, CDHTMLDialog (para mostrar pginas en HTML). HTML)

Mapas de Datos
Intercambio de Datos de Dilogo (DDX). I t bi d D t d Dil (DDX) Asociar variables a controles del dilogo g para intercambiar informacin. Por valor (las variables contienen el valor del control) o por referencia (control). UpdateData(FALSE) actualiza los controles a partir de las variables. UpdateData(TRUE) actualiza las variables a partir del contenido de los controles.
75

Mapas de Datos
Ejemplo

76

Mapas de Datos
Ejemplo

77

Mapas de Datos
#pragma once

CSimpleDlg.h

// Cuadro de dilogo de CSimpleDlg g p g class CSimpleDlg : public Cdialog { // Construccin public: CSimpleDlg(CWnd* p p g( pParent = NULL); ); // Constructor estndar // Datos del cuadro de dilogo enum { IDD = IDD_SIMPLEDIALOGO_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* p ) g ( g pDX); // Compatibilidad con DDX/DDV p // Implementacin protected: HICON m_hIcon; // Funciones de asignacin de mensajes g g j generadas virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() _ _ () private: CString strUsrName; // Nombre del usuario CString strSaludo; // Saludo public: afx_msg void OnEnChangeNombre(); afx_msg void OnBnClickedOk(); afx_msg void OnEnKillfocusNombre(); };

78

Mapas de Datos
CSimpleDlg.cpp (i)
CSimpleDlg::CSimpleDlg(CWnd* P CSi l Dl CSi l Dl (CW d* pParent /*=NULL*/) t /* NULL*/) : CDialog(CSimpleDlg::IDD, pParent) , strUsrName(_T("")) , strSaludo(_T("")) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CSi l Dl D D t E h id CSimpleDlg::DoDataExchange(CDataExchange* pDX) (CD t E h * DX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_NOMBRE, strUsrName); DDV_MaxChars(pDX, t U N DDV M Ch ( DX strUsrName, 128); 128) DDX_Text(pDX, IDC_SALUDO, strSaludo); } BEGIN_MESSAGE_MAP(CSimpleDlg, CDialog) BEGIN MESSAGE MAP(CSi l Dl CDi l ) ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_EN_CHANGE(IDC_NOMBRE, &CSimpleDlg::OnEnChangeNombre) ON EN CHANGE(IDC NOMBRE &CSi l Dl O E Ch N b ) ON_BN_CLICKED(IDOK, &CSimpleDlg::OnBnClickedOk) ON_EN_KILLFOCUS(IDC_NOMBRE, &CSimpleDlg::OnEnKillfocusNombre) END_MESSAGE_MAP()

79

Mapas de Datos
CSimpleDlg.cpp (i)
void CSimpleDlg::OnBnClickedOk() { // TODO: Add your control notification handler code here //OnOK(); UpdateData(TRUE); p ( ); strSaludo = "Hola "+strUsrName+"!"; UpdateData(FALSE); } void CSimpleDlg::OnEnKillfocusNombre() { // si ponemos este cdigo en EN_CHANGE, se actualiza en tiempo de ejecucin UpdateData(TRUE); strSaludo = "Hola "+strUsrName+"!"; UpdateData(FALSE); }
80

Mens
Se pueden crear en el editor de recursos recursos. El asistente crea un men esttico en la ventana marco (mismo identificador que la tabla aceleradora y el icono). Se cargan todos los recursos en InitInstance():
pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW |FWS_ADDTOTITLE, NULL,NULL); | , , );

Elementos del men de dos tipos:


pop-up (abren otros mens). activos, que generan un mensaje de comando a la aplicacin. Normalmente a travs del asistente.

Dos D mensajes: COMMAND y UPDATE_COMMAND_UI. j UPDATE COMMAND UI El ltimo permite cambiar el aspecto del item de men (cambiar texto, aadir un check, etc.)
81

Mens
Ejemplo
CChildView::CChildView() : numColores (4), CodigoColor (new UINT[numColores]), currentColor(0), NombreColor(new CString[numColores]) { lastClicked = CPoint(-1, -1); CodigoColor[0] = RGB(0, 0, 0); // Black // NombreColor[0] = "Negro"; // } CChildView::~CChildView() { delete [] CodigoColor; delete [] NombreColor; } BEGIN_MESSAGE_MAP(CChildView, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON WM LBUTTONDOWN() ON_COMMAND(ID_CAMBIACOLOR, &CChildView::OnCambiacolor) ON_UPDATE_COMMAND_UI(ID_CAMBIACOLOR, &CChildView::OnUpdateCambiacolor) END_MESSAGE_MAP() void CChildView::OnUpdateCambiacolor(CCmdUI *pCmdUI) { pCmdUI->SetText("Cambia Color a "+NombreColor[(currentColor+1)%numColores]); }
82

CMenu
Para cambiar entre distintos mens, o cargar uno dinmicamente se usa la clase CMenu. Enmascara un HMENU (en m_hMenu). Asignacin a la ventana con SetMenu(). Algunas funciones miembro:
LoadMenu(): carga un men creado como un recurso recurso. CreateMenu(), CreatePopupMenu(): crea un men vaco (normal y emergente). Attach(): Asocia un CMenu a un recurso identificado por su HMENU.
83

Mens
Ejemplo: Aadir un Men a un Dilogo

2 3

84

Mens
Ejemplo: Aadir un Men a un Dilogo

1. 1 Crear el men en el editor de recursos (ID=IDR_SIMPLEDIALOG). 2. Aadir 2 A di un atributo d ti CM t ib t de tipo CMenu a l clase CSi l Dl la l CSimpleDlg, gestin de items de men.
class CSimpleDlg : public CDialog { private: CMenu menu; CListBox fileListBox; // DDX, control public: afx_msg void OnFicheroSeleccionar(); // gestin de items de men g (); g afx_msg void OnFicheroSalir(); };

85

CSimpleDlg::CSimpleDlg(CWnd* pParent /*=NULL*/) : CDialog(CSimpleDlg::IDD, pParent), strUsrName(_T("")), strSaludo(_T("")), menu() { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CSimpleDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_NOMBRE, strUsrName); _ (p _ ) DDV_MaxChars(pDX, strUsrName, 12); DDX_Text(pDX, IDC_SALUDO, strSaludo); DDX_Control(pDX, IDC_FICHEROS, fileListBox); }

Mens

CSimpleDlg.cpp

BEGIN_MESSAGE_MAP(CSimpleDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() () //}}AFX_MSG_MAP ON_EN_CHANGE(IDC_NOMBRE, &CSimpleDlg::OnEnChangeNombre) ON_BN_CLICKED(IDOK, &CSimpleDlg::OnBnClickedOk) ON_EN_KILLFOCUS(IDC_NOMBRE, &CSimpleDlg::OnEnKillfocusNombre) ON_COMMAND(ID_FICHERO_SELECCIONAR, &CSimpleDlg::OnFicheroSeleccionar) ON_COMMAND(ID_FICHERO_SALIR, &CSimpleDlg::OnFicheroSalir) END_MESSAGE_MAP() BOOL CSimpleDlg::OnInitDialog() { CDialog::OnInitDialog(); SetIcon(m_hIcon, TRUE); // Establecer icono grande SetIcon(m_hIcon, FALSE); // Establecer icono pequeo menu.LoadMenu(IDR_SIMPLEDIALOGO); SetMenu(&menu); return TRUE; // Devuelve TRUE a menos que establezca el foco en un control }

86

Mens
CSimpleDlg.cpp
void CSimpleDlg::OnFicheroSeleccionar() { LPCTSTR szCppFilters= "C++ Files (* C S C C (*.cpp)|*.cpp|All Files (* *)|* *|| )|* | (*.*)|*.*||"; CFileDialog fd(TRUE, "Cpp", "*.cpp", OFN_FILEMUSTEXIST| OFN HIDEREADONLY szCppFilters OFN FILEMUSTEXIST| OFN_HIDEREADONLY, szCppFilters, this); if( fd.DoModal ()==IDOK ) { CString pathName = fd.GetPathName(); UpdateData(TRUE); fileListBox.AddString(pathName); fil Li tB AddSt i ( thN ) UpdateData(FALSE); } } void CSimpleDlg::OnFicheroSalir() { PostMessage(WM_QUIT); }
87

Mens
Ejemplo: Aadir un Men Emergente Dinmico

class CSimpleDlg : public CDialog { private: // CMenu pmenu; public: afx_msg void OnRButtonDown(UINT nFlags, CPoint p g ( g , point); //con asistente ); afx_msg void OnItem1(); // a mano 88 };

CSimpleDlg::CSimpleDlg(CWnd* pParent /*=NULL*/) : CDialog(CSimpleDlg::IDD, pParent) , strUsrName(_T("")) , strSaludo(_T("")) , menu(), pmenu() { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); CSimpleDlg.cpp } BEGIN_MESSAGE_MAP(CSimpleDlg, CDialog) ( p g, g) ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP // ON_COMMAND(ID_FICHERO_SELECCIONAR, &CSimpleDlg::OnFicheroSeleccionar) ON_COMMAND(ID_FICHERO_SALIR, &CSimpleDlg::OnFicheroSalir) ON_COMMAND(ID_FICHERO_SALIR+1, &CSimpleDlg::OnItem1) ON_WM_RBUTTONDOWN() ON WM RBUTTONDOWN() END_MESSAGE_MAP() BOOL CSimpleDlg::OnInitDialog() { CDialog::OnInitDialog(); SetIcon(m_hIcon, TRUE); // Establecer icono grande SetIcon(m_hIcon, FALSE); // Establecer icono pequeo menu.LoadMenu(IDR_SIMPLEDIALOGO); ( ); SetMenu(&menu); pmenu.CreatePopupMenu(); pmenu.AppendMenu(MF_STRING, ID_FICHERO_SALIR+1, "Item 1"); pmenu.AppendMenu(MF_STRING, ID_FICHERO_SELECCIONAR, Seleccionar Fichero ); pmenu AppendMenu(MF STRING ID FICHERO SELECCIONAR "Seleccionar Fichero"); pmenu.AppendMenu(MF_STRING, ID_FICHERO_SALIR, "Salir"); return TRUE; // Devuelve TRUE a menos que establezca el foco en un control }

Mens

89

Mens
CSimpleDlg.cpp
void CSimpleDlg::OnFicheroSalir() { // TODO: Add your command h dl code h TODO d handler d here PostMessage(WM_QUIT); } void CSimpleDlg::OnRButtonDown(UINT nFlags, CPoint point) { ClientToScreen(&point); pmenu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this); } void CSimpleDlg::OnItem1() { AfxMessageBox( Item 1"); AfxMessageBox("Item 1 ); }

90

Mens
Ejemplo: Aadir un Men Emergente Dinmico

En realidad lo que hemos hecho es un men contextual. Para ello b t con capturar el mensaje P ll basta t l j WM_CONTEXTMENU.
void CSimpleDlg::OnContextMenu(CWnd* pWnd, CP i t point) id CSi l Dl O C t tM (CW d* W d CPoint i t) { pmenu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point. y, this); }

Si no mostramos un men, debemos llamar a CWnd::OnContextMenu(pWnd, CWnd::OnContextMenu(pWnd point) antes de salir salir.

91

Teclas Aceleradoras
Asociar una combinacin de teclas a un comando. Si se usa el asistente, la definicin de teclas aceleradoras se carga en l ventana marco con l l d la t la llamada a LoadFrame().

92

Teclas Aceleradoras
Las tablas aceleradoras no funcionan con aplicaciones basadas en dilogo, ya que su bucle de mensajes no llama a TranslateAccelerator() TranslateAccelerator().
class CSimpleApp : public CWinApp { private: HACCEL m_haccel; public: bli CSimpleApp();

// aadir handle a tabla aceleradora

// Reemplazos public: virtual BOOL InitInstance(); BOOL ProcessMessageFilter(int code, LPMSG lpMsg); // sobreescribir DECLARE_MESSAGE_MAP() DECLARE MESSAGE MAP() };

93

BOOL CSimpleApp::InitInstance() { INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); AfxEnableControlContainer(); (); SetRegistryKey(_T("Aplicaciones generadas con el Asistente para aplicaciones local")); m_haccel=::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1)); CSimpleDlg dlg; m_p pMainWnd = &dlg; g; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: insertar aqu el cdigo para controlar cundo se descarta el cuadro de dilogo con Aceptar } else if (nResponse == IDCANCEL) { // TODO: insertar aqu el cdigo para controlar cundo se descarta el cuadro de dilogo con Cancelar } return FALSE; ; } BOOL CSimpleApp::ProcessMessageFilter(int code, LPMSG lpMsg) { if (code < 0) CWinApp::ProcessMessageFilter(code, lpMsg); ( ) pp g ( , p g); if(m_haccel) { if (::TranslateAccelerator(m_pMainWnd->m_hWnd, m_haccel, lpMsg)) return(TRUE); ( ); } return CWinApp::ProcessMessageFilter(code, lpMsg); }

Teclas Aceleradoras

94

Teclas Aceleradoras
Este podra ser un bucle de mensajes con llamada a las teclas t l aceleradoras: l d
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow) { MSG msg; BOOL bRet; // while ( (bRet = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0) { if (bRet == -1) { (bR t 1) // handle the error and possibly exit } else { // Check for accelerator keystrokes. if (!TranslateAccelerator( hwndMain, // handle to receiving window haccel, // handle to active accelerator table &msg)) // message data { TranslateMessage(&msg); DispatchMessage(&msg); } } } // }

95

Dilogos
Las MFCs contienen dilogos preconstruidos que pueden ser usados directamente por el usuario. g Para crear un dilogo:
Se usa el editor de recursos. DoModal() muestra el dilogo de manera modal. () g Devuelve un UINT con la razn por la que se cerr (ej.: IDCANCEL o IDOK). Los no modales se crean como si fueran una ventana (Create()).
96

Ejemplo: Aadir un Dilogo


Creado usando el editor de recursos. Se S crea una clase que l herede de CDialog con el asistente asistente.

Se aade un nuevo elemento al men y a la tabla aceleradora


void CSimpleDlg::OnFicheroDialogo() { CDialogoEjemplo dlg(this); dlg.DoModal(); dlg DoModal(); }

class CDialogoEjemplo : public CDialog { DECLARE_DYNAMIC(CDialogoEjemplo) public: CDialogoEjemplo(CWnd CDialogoEjemplo(CWnd* pParent = NULL); virtual ~CDialogoEjemplo(); enum { IDD = IDD_DIALOG1 }; protected: virtual void DoDataExchange(CDataExchange* pDX); 97 DECLARE_MESSAGE_MAP() };

Dilogos Predefinidos
CColorDialog: permite seleccionar un CC l Di l i l i color.

CFileDialog: permite seleccionar ficheros.

CFindReplaceDialog: permite realizar bsqueda o buscar/reemplazar (no modal, se crea con Create()).

98

Dilogos Predefinidos
CFontDialog: permite elegir una fuente.

CPrintDialog: permite imprimir y configurar la impresin.

CPageSetupDialog: imprimir y

permite

99

Controles
Las MFC ponen a nuestra disposicin un g gran nmero de controles q simplifican que p la creacin de aplicaciones. Los controles mandan notificaciones a la ventana padre (ej.: el control de edicin manda EN_CHANGE cuando cambia el C G ) texto).

100

Controles predefinidos MFC


CAnimateCtrl: public CWnd: Permite mostrar un vdeo en formato AVI.
void CAboutDlg::OnBnClickedButton1() { avi_player.Open(IDR_AVI1); avi_player.Play(0, -1, avi player Play(0 -1 -1); }

101

Controles predefinidos MFC


CButton: permite gestionar botones.
Eventos: BN CLICKED, BN DOUBLECLICKED. BN_CLICKED, BN_DOUBLECLICKED. Mtodos: GetState(), SetState(), SetCursor(), GetCursor().

void CAboutDlg::OnBnClickedMessage() { anim.Stop(); AfxMessageBox("Stop!"); }

102

Controles predefinidos MFC


CBitmapButton: S crea un botn normal en el CBit B tt Se b t l l editor de recursos y:
se selecciona OwnerDraw=true OwnerDraw true. en el caption se pone una descripcin (ej: BOTON). Se crean de 1 a 4 bitmaps:
ID=BOTONU, bitmap normal. ID=BOTONF, bitmap foco de teclado. ID=BOTONX, bitmap botn desactivado. , p ID=BOTOND, bitmap botn pulsado.

Se crea un objeto de la clase CBitmapButton como miembro del dilogo dilogo. En la inicializacin del dilogo (OnInitDialog()) se llama a AutoLoad().
103

class CAboutDlg : public CDialog { public: CAboutDlg(); // virtual void DoDataExchange(CDataExchange* pDX);

Ejemplo
CBitmapButton
// Compatibilidad con DDX/DDV

// Implementacin protected: DECLARE_MESSAGE_MAP() private: i t CAnimateCtrl anim; CBitmapButton BClose; public: afx_msg void O B Cli k dSt t() f id OnBnClickedStart(); afx_msg void OnBnClickedMessage(); public: BOOL OnInitDialog(); }; void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_ANIMATE1, anim); DDX_Control(pDX, IDMESSAGE BClose); DDX C t l( DX IDMESSAGE, BCl ) } // BOOL CAboutDlg::OnInitDialog() { BClose.AutoLoad(IDMESSAGE, this); BCl A t L d(IDMESSAGE thi ) CDialog::OnInitDialog(); return FALSE; }

104

Controles predefinidos MFC


CListBox:
Listas Datos iniciales (en OnInitDialog) Seleccin simple o mltiple Mtodos:
int int int int GetCurSel(); SetCurSel(int nSelect); AddString(LPCTSTR lpszItem); InsertString(int nIndex, LPCTSTR lpszItem); Ejemplo void CSimpleDlg::OnLbnKillfocusList1() { int sel = nameListBox.GetCurSel(); if (sel>-1) { CString str; nameListBox.GetText(sel,str); AfxMessageBox("Selected It Af M B ("S l t d Item: " t ) "+str); } 105 }

Controles predefinidos MFC


CComboBox: CC b B
Simple (lista siempre visible), Drop-down (permite editar), DropDown List. Mtodos:
GetCount(): nmero de elementos que tiene la lista. GetCurSel()/SetCurSel(): obtiene/establece el nmero de orden del elemento seleccionado. SetItemData()/GetItemData(): lee el valor asignado a un determinado elemento de la lisa. AddString()/DeleteString()/InsertString(). Tambin se pueden cargar valores estticos en el campo Data del editor de recursos (separados mediante ;) Dir().

CComboBoxEx: permite introducir imgenes en los elementos a seleccionar, entre otras mejoras.

106

Controles predefinidos MFC


CDataTimeCtrl. CD t Ti Ct l CEdit. CHeaderCtrl. CHeaderCtrl CHotKeyCtrl. CIpAddressCtrl. CIpAddressCtrl CCheckListBox. CDragListBox. CDragListBox CListCtrl. CMonthCalCtrl. COleControl. CProgressCtrl.
107

Controles predefinidos MFC


CReBarCtrl. CR B Ct l CRichEditCtrl. CScrollBar. CScrollBar CSliderCtrl. CSpinButtonCtrl. CSpinButtonCtrl CStatic. CStatusBarCtrl. CStatusBarCtrl CTabCtrl. CToolBarCtrl. CToolBarCtrl CToolTipCtrl. CTreeCtrl. CTreeCtrl
108

Clases de Utilidad
Cadenas de caracteres
CString. CString Caracteres unicode vs. ascii. Definiciones de un const char* typedef wchar_t WCHAR; wchar t // wchar_t es un char Unicode (2 bytes) // o ANSI (1 byte) dependiendo de // la opcin sealada para el proyecto typedef __nullterminated CONST WCHAR *LPCWSTR; typedef LPCWSTR LPCTSTR; j p Conversiones. Ejemplo:
LPCTSTR t; // si tenemos opcin Unicode es un error: t="abc"; CString c1("abc"); c1="def"; 1 "d f" t=c1; // correcto ya que hace un casting implcito // y est definido un operador de casting p g
109

Clases de Utilidad
Cadenas de caracteres
// sobrecarga de =, +=, etc + CString s; s= Hola ; s="Hola; s+= soy yo; cout << Saludo: << s; Saludo: // conversin CString a char* // No imprime en p p pantalla // Para mensajes, imprimir en controles // o con MessageBox string s2=s;

110

Clases de Utilidad
Contenedores

Similares a los contenedores de la STL. Definiciones en afxtempl.h (que debemos incluir en stdafx.h). td f h) Los templates admiten dos parmetros: el tipo de dato, y el tipo para referirse a l (quiz una referencia) referencia).

Contenedor Vectores Listas Diccionario

Clase CArray CList CMap

Puntero CTypedPtrArray CTypedPtrList CTypedPtrMap

Clases de Utilidad
Contenedores: CArray
Similar Si il a vector d l STL t de la STL. template < class TYPE, class ARG_TYPE = const TYPE& > class CArray : public CObject ARG_TYPE es el tipo que se usa para acceder a los elementos almacenados. Tamao:
GetCount(), GetSize(), GetUpperBound(), IsEmpty(), SetSize().

Ejemplo Ej l
CArray<CPoint,CPoint> myArray; // Add elements to the array array. for (int i=0;i < 10;i++) myArray.Add( CPoint(i, 2*i) ); // Modify all the points in the array. for (i=0;i <= myArray.GetUpperBound();i++) { myArray[i].x myArray[i] x = 0; }

Operaciones: p
FreeExtra(), RemoveAll(), RelocateElements().

Aumentando el Array:
Add(), Append(), Copy(), SetAtGrow(). (), pp (), py(), ()

Insercin/eliminacin:
InsertAt(), RemoveAt()

Operadores:
Acceso/modificacin con el operador [].

Clases de Utilidad
Contenedores: CList
template<class TYPE class ARG_TYPE=const TYPE&> class CLi t : public CObj t t l t l TYPE, l ARG TYPE t TYPE& l CList bli CObject

Iteracin:

CList<CMiClase, CMiClase&> myList; , y ; POSITION pos = myList.GetHeadPosition(); while( pos != NULL ) { CMiClase& clase = myList.GetNext( pos ); //... // }

Insercin: myList.InsertAfter(myList.GetTailPosition(), elem); I i Li t I tAft ( Li t G tT ilP iti () l ) Eliminacin: myList RemoveAt(pos); myList.RemoveAt(pos);

113

Clases de Utilidad
Contenedores: CMap
template< class KEY class l l KEY, l ARG_KEY, class VALUE, class ARG_VALUE >class CMap : public CObject Operaciones:
GetHashTableSize(), GetHashTableSize() GetNextAssoc(), PGetNextAssoc(), GetStartPosition(), PGetFirstAssoc(), InitHashTable(), Lookup(), InitHashTable() Lookup() PLookup(), operator[], RemoveAll(), RemoveKey(), SetAt().
CMap<int,int,CPoint,CPoint> myMap; CM i t i t CP i t CP i t M int i; myMap.InitHashTable( 257 ); // Add 10 elements to the map. for (i=0;i < 200;i++) myMap[i] = CPoint(i, i); // Remove the elements with even // key values. CPoint pt; for (i 0 f (i=0; myMap.Lookup( i pt ) ;i+=2) M L k ( i, t i+ 2) { myMap.RemoveKey( i ); }

Ejemplo

Estado:
GetCount(), GetSize(), IsEmpty().

Miembros de Datos:
CMap::CPair

Clases de Utilidad
Contenedores de punteros

Si queremos tener listas de objetos heterogeneos heterogeneos. No podemos usar los contenedores anteriores, ya que si q queremos serializar una lista a disco, se copiaran los p punteros, y no los objetos. Por ello, MFC duplica los contenedores para la gestin de punteros. punteros template< class BASE_CLASS, class TYPE > class CTypedPtrList : public BASE_CLASS
BASE_CLASS: tipo del BASE CLASS ti d l que se h d para construir el hereda t i l template.
CObList si los elementos heredan de CObject (se pueden serializar). CPtrList en otro caso. caso

TYPE: tipo de los elementos que insertamos. Similar para arrays.

Clases de Utilidad
Contenedores de punteros, ejemplo
//===================== //where CMyObject i d fi d b th f ll i fil // h CM Obj t is defined by the following files: typedef CTypedPtrList<CObList, CMyObject*> CMyList; CMyList ml; CMyObject* pMyObject = new CMyObject(); y j y j y j () ml.AddTail(pMyObject); CFileException e; CFile myFile; myFile.Open("MyFile.txt", CFile::modeCreate|CFile::modeWrite, &e); CArchive ar(&myFile, CArchive::store); ml.Serialize(ar); ar.Close(); myFile.Close(); while (!ml.IsEmpty()) { delete ml.GetHead(); ml.RemoveHead(); } //CMyObject.h class CMyObject : public Cobject { public: bli int i; void Serialize(CArchive& ar); CMyObject() { i = 9876;} protected: t t d DECLARE_SERIAL(CMyObject) }; //CMyObject.cpp //CM Obj t #include "stdafx.h" #include "CMyObject.h" IMPLEMENT_SERIAL(CMyObject, CObj t IMPLEMENT SERIAL(CM Obj t CObject, 0) void CMyObject::Serialize(CArchive& ar) { CObject::Serialize( ar ); if( ar.IsStoring() ) ar << i; i else ar >> i; }

Clases de Utilidad
Contenedores de punteros: CTypedPtrMap
template< class BASE_CLASS, class KEY class VALUE > class t l t < l BASE CLASS l KEY, l l CTypedPtrMap : public BASE_CLASS BASE_CLASS: clase base del diccionario, puede ser, en funcin de los ti l tipos de la clave y elementos a almacenar: d l l l t l
CMapPtrToPtr, CMapPtrToWord, CMapWordToPtr, CMapStringToPtr CMapStringToString p g g CMapWordToOb CMapWordToPtr

KEY: tipo de la clave. clave VALUE: tipo de los elementos a almacenar (suele ser un puntero). Ej.: typedef CTypedPtrMap<CMapStringToOb, CString, CMiObjeto*> MapaAMiObjeto;

Indice
Programacin b j Wi d P i bajo Windows. Introduccin a las MFCs.

Arquitectura Documento/Vista. A it t D t /Vi t


Introduccin. SDI y MDI. Plantillas de documento. documento Ejemplo. Documento, serializacin. D t i li i
Bibliografa.
118

Arquitectura Documento Vista


Separar l visualizacin ( i ) d l d S la i li i (vista) de los datos (d (documento). ) Similar al patrn Model-View-Controler. El asistente genera clases que heredan de: CFrameWnd CView y CFrameWnd,
CDocument.

CView es abstracta. Otra posibilidad es usar como base una vista predefinida: d fi id
CEditView (edicin de texto bsica). Esta se puede usar directamente. CRichEditView (permite formateo de texto). CScrollView (scroll vertical y horizontal). CListView (listas de elementos). CTreeView (rbol de elementos) elementos). CFormView (similar a un cuadro de dilogo). CDaoRecordView (similar a cuadro de dilogo pero para control de BBDD). BBDD) 119 CCtrolView (se pueden incluir otras vistas dentro).

SDI y MDI
Single Document Interface: Un solo tipo de documento documento. Multiple Document Interface: Varios tipos de documento.

Una aplicacin SDI

Una aplicacin MDI

120

Las plantillas de documento


El documento, el marco y la vista se relacionan usando plantillas de documento, que heredan de CDocTemplate. CSingleDocTemplate y CMultiDocTemplate para SDI y MDI.
BOOL CSDI2App::InitInstance() { CSDI2A I itI t () // pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CSDI2Doc), RUNTIME CLASS(CSDI2D ) RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CSDI2View)); if (!pDocTemplate) return FALSE; AddDocTemplate(pDocTemplate); AddD T l t ( D T l t ) EnableShellOpen(); RegisterShellFileTypes(TRUE); // }

// Ventana de marco SDI principal

RUNTIME_CLASS devuelve un struct CRuntimeClass *.


Nota: Slo se puede obtener esta informacin de subclases de CObject que hayan sido declaradas DECLARE_DYNAMIC, DECLARE_DYNCREATE o 121 DECLARE_SERIAL.

Las plantillas de documento


Una plantilla de documento por cada tipo de documento soportado, y es responsable de crear y gestionar los documentos de ese tipo tipo. La plantilla contiene el ID con los recursos (men, icono, tablas aceleradoras). aceleradoras) Contiene tambin strings con el nombre del tipo de docu e o, a extensin documento, la e e s de sus ficheros, e c c e os, etc. EnableShellOpen(): permite abrir ficheros de datos haciendo doble click en ellos en el explorador. p RegisterShellFileTypes(cCompat): Registra los tipos de documentos en el explorador. Si bCompat==TRUE entonces se pueden imprimir los ficheros desde el 122 explorador.

Arquitectura Documento Vista


Ejemplo

123

Arquitectura Documento Vista


Ejemplo

Vista derivada de CFormView.

Se crea tambin un dilogo vaco en el editor de recursos:

String St i asociado a la aplicacin IDR MAINFRAME i d l li i IDR_MAINFRAME

7 pedazos:

124

El Documento
Encargado de gestionar los datos, incluido su grabacin y recuperacin del disco. virtual BOOL OnNewDocument(); se llama cuando se va a crear un nuevo fichero (sobreescribirlo permite chequear si queremos dejar crearlo o no). virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); se llama cuando se va a abrir un fichero. virtual void OnCloseDocument(); se llama cuando se va a cerrar un fichero fichero. virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); se llama cuando se va a salvar un documento. void SetModifiedFlag(BOOL bModified = TRUE); marca el documento como cambiado. BOOL IsModified(); comprueba si un documento est modificado. 125

Colaboracin de Objetos en la Aplicacin


Acceso a unos objetos d d otros: A bj t desde t
Objeto Obj Documento Documento Vista Vista Mtodo M d GetFirstViewPosition()/GetNextView() GetDocTemplate() GetDocument() GetParentFrame()

Ventana marco del documento GetActiveView() Ventana marco del documento GetActiveDocument() Ventana principal (MDI) Ventana marco MDIGetActive() GetActiveFrame()

Colaboracin de Objetos en la Aplicacin


CWinApp pp
1

1 m_pMainWnd

CFrameWnd
1 getParent(); 1 g getActiveView(); ();

CView
1..* {POSITION p=GetFirstViewPosition(); GetNextView(p);} 1 g getDocument(); ();

CDocument

Arquitectura Documento Vista


Serializacin
Guardar/leer los d G d /l l datos d di de disco. virtual void Serialize(CArchive& ar); provisto por CObject. Sirve para leer y escribir. escribir Se usan los operadores << y >> sobre el CArchive.
void CSDI2Doc::Serialize(CArchive& ar) { POSITION pos = GetFirstViewPosition(); // m_viewList contiene lista punteros a vistas CSDI2View* pView = dynamic_cast<CSDI2View*>(GetNextView(pos)); if (ar.IsStoring()){ pView >UpdateData(TRUE); pView->UpdateData(TRUE); ar << pView->nombre; ar << pView->direccion; ar << pView->edad; } else { ar >> pView->nombre; ar >> pView->direccion; ar >> pView >edad; pView->edad; pView->UpdateData(FALSE); } }

128

Arquitectura Documento Vista


Serializacin
class CSDI2Doc : public CDocument { //.. p private: CSDI2View* pView; CSDI2View* getView(); // }; inline CSDI2View* CSDI2Doc::getView(){ if (!pView) { POSITION pos = GetFirstViewPosition(); p (); pView = dynamic_cast<CSDI2View*>(GetNextView(pos)); } return pView; } void CSDI2Doc::Serialize(CArchive& ar){ getView(); if (ar.IsStoring()) { p pView->UpdateData(TRUE); p ( ) ar << pView->nombre << pView->direccion << pView->edad; } else { ar >> pView->nombre >> pView->direccion >> pView->edad; pView->UpdateData(FALSE); } } // el evento salvar llama por defecto a la serializacin del documento

129

Arquitectura Documento Vista q


Creacin de un nuevo documento
BOOL CSDI2Doc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; t FALSE // TODO: agregar aqu cdigo de reinicio // (los documentos SDI volvern a utilizar este documento) getView()->nombre=""; pView->direccion=""; pView->edad=0; pView >edad=0; pView->UpdateData(FALSE); return TRUE; }

130

Ejemplo

Indice
Programacin bajo Windows. g j Introduccin a las MFCs. Arquitectura Documento/Vista Documento/Vista.

Aspectos avanzados de las MFCs.


Dilogos no modales. Creacin dinmica de widgets. widgets Registro. Otros aspectos de las MFCs.
Bibliografa. Bibliografa
132

Dilogos No Modales
Para ejecutar dilogos en f P j t dil formal modal, l d l simplemente hay que llamar al mtodo DoModal(). Para crear un dilogo no modal, hay que hacerlo como si fuera una ventana cualquiera, mediante Create().
Esto crea el dilogo y contina la ejecucin. Por tanto el dilogo se debe crear usando memoria dinmica!

Liberacin de la memoria en OnNcDestroy() del y() dilogo. Aqu se pueden pasar datos a la ventana principal.
133

void CGraficosSDIApp::OnAppAbout() { if (!pAboutDlg) { Ejemplo: About No Modal pAboutDlg = new CAboutDlg(); // puntero miembro pAboutDlg->Create( MAKEINTRESOURCE(CAboutDlg::IDD), // string con ID CWnd::GetDesktopWindow()); // puntero al escritorio, // evita que el dilogo est siempre encima pAboutDlg->ShowWindow(SW_SHOW); } else pAboutDlg->SetForegroundWindow(); // el dilogo ya exista, llevarlo al frente } void CGraficosSDIApp::CloseDialog() { // acciones al cerrar el dilogo pAboutDlg = 0; g // simplemente apunta a NULL }

Dilogos No Modales

void CAboutDlg::OnNcDestroy() { // ltimo mensaje que se recibe antes de cerrar CDialog::OnNcDestroy(); ((CGraficosSDIApp*)AfxGetApp())->CloseDialog(); // avisar a la aplicacin, podramos avisar a la ventana padre // otra posibilidad es mandarle un mensaje definido por el // usuario con GetParent()->PostMessage(WM_USR,0,0) delete this; // importante: borramos la memoria dinmica } void CAboutDlg::OnOK() { // importante sobreescribir si se tiene un IDOK, ya que por defecto MFC llama a // EndDialog(), que slo vale para DoModal() if(UpdateData(true)) DestroyWindow(); }

Creacin dinmica de widgets


void CSDI2View::OnBnClickedButton1() { CButton* pButton=new CButton; pButton Create( Submit , pButton->Create("Submit", WS_CHILD | WS_VISIBLE, CRect(170, 120, 270, 143), this, , 0x302); // un ID }

135

Registro
La mayora de las aplicaciones dejan cierto grado de customizacin al usuario. Por ejemplo: posicin y tamao de la ventana posicin de las barras ventana, de controles, etc. Guardar esta informacin de configuracin en el registro (hasta windows 3.11, esta informacin se guardaba en ficheros INI). En InitInstance() se llama a SetRegistryKey() para establecer una SetRegistryKey(), clave (se crea debajo de HKEY_CURRENT_USER/software).
SetRegistryKey() asigna valor al atributo m_pszRegistryKey de la clase CWinApp. pp

El resto de llamadas del API (GetProfileString(), GetProfileInt(), g() ()) WriteProfileString(), WriteProfileInt()) utilizan dichos mtodos.

Registro
BOOL CGraficosSDIApp::InitInstance() { // SetRegistryKey(_T("GraficosSDI")); LoadStdProfileSettings(4); // Cargar opciones de archivo INI estndar // (incluidas las de la lista MRU) // }

Normalmente se leer la informacin del registro en OnCreate() de la ventana marco.


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; WINDOWPLACEMENT PosVen; if (LeePosicionVentana(&PosVen)) SetWindowPlacement(&PosVen); // }

Registro
bool CMainFrame::LeePosicionVentana(LPWINDOWPLACEMENT pPosVen) { CString strClave = AfxGetApp()->GetProfileString(_T("Arranque"), _T("Posicion")); if (strClave.IsEmpty()) return false; int numDatos = sscanf_s(strClave, "%u,%u,%d,%d,%d,%d,%d,%d,%d,%d", &pPosVen->flags, &pPosVen->showCmd, &pPosVen->ptMinPosition.x, &pPosVen->ptMinPosition.y, &pPosVen->ptMaxPosition.x, &pPosVen->ptMaxPosition.y, &pPosVen->rcNormalPosition.left, &pPosVen->rcNormalPosition.top, &pPosVen->rcNormalPosition.right, &pPosVen->rcNormalPosition.bottom); if (numDatos != 10) return false; pPosVen->length=sizeof(pPosVen); return true; }

Registro
void CM i F id CMainFrame::OnClose() O Cl () { WINDOWPLACEMENT PosVen; PosVen.length=sizeof(PosVen); if (G tWi d Pl (GetWindowPlacement(&PosVen)) t(&P V )) { if (PosVen.showCmd!=SW_SHOWMINIMIZED) EscribirPosicionVentana(&PosVen); } CFrameWnd::OnClose(); } void CMainFrame::EscribirPosicionVentana(LPWINDOWPLACEMENT pPosVen) { TCHAR szBuffer[8*6+2*5+9+1]; wsprintf(szBuffer, "%u,%u,%d,%d,%d,%d,%d,%d,%d,%d", i tf( B ff "% % %d %d %d %d %d %d %d %d" pPosVen->flags, pPosVen->showCmd, pPosVen->ptMinPosition.x, pPosVen->ptMinPosition.y, pPosVen->ptMaxPosition.x, pPosVen->ptMaxPosition.y, pPosVen->rcNormalPosition.left, pPosVen->rcNormalPosition.top, pPosVen->rcNormalPosition.right, pPosVen->rcNormalPosition.bottom); P V > N lP iti i ht P V > N lP iti b tt ) AfxGetApp()->WriteProfileString(_T("Arranque"), _T("Posicion"), szBuffer); }

Otros aspectos de las MFCs


Bases de datos Sincronizacin Windows sockets Servicios Internet

140

Indice
Programacin bajo Windows. Introduccin a las MFCs. MFCs Arquitectura Documento/Vista. Aspectos avanzados de las MFCs.

Bibliografa. Bibliografa

141

Bibliografa
MSDN (ayuda en lnea) lnea). Programacin Avanzada en Windows 2000 con Visual C++ y MFC. Pascual, J., Charte, F., Segarra, M. J., de g Antonio, A., Clavijo, J. A. McGraw Hill. 2000. MFC:
http://www.functionx.com/visualc/ http://www functionx com/visualc/ http://www.dcp.com.ar/mfc/indice.htm http://www.uta.fi/~jl/pguibook/ http://www.samspublishing.com/library/library.asp?b=Visual_C_ http://www samspublishing com/library/library asp?b Visual C PlusPlus&rl=1 (libro Visual C++ Unleashed) Documentacin MFC al estilo de javadoc: http://www.cppdoc.com/example/mfc/mfc.html http://www cppdoc com/example/mfc/mfc html

Controles
http://www.functionx.com/visualc/controls/
142

Vous aimerez peut-être aussi