Académique Documents
Professionnel Documents
Culture Documents
Tema 6
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
2. 3. 3 4.
Esperar que llegue algn mensaje. Reaccionar ante el mensaje recibido recibido. Volver a 2.
#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
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=h3 lpClassName=CN3
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
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()
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.
25
27
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
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
30
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
32
33
34
35
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
Resource.h
#define IDD_ABOUTBOX #define IDP_OLE_INIT_FAILED #define IDR_MAINFRAME IDR MAINFRAME #define IDR_HelloMFCsTYPE 100 100 128 129
37
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
39
41
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
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
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
class CHelloMFCsApp : public CWinApp { public: CHelloMFCsApp(); // Reemplazos public: virtual BOOL InitInstance(); // Implementacin public: afx_msg void OnAppAbout(); DECLARE_MESSAGE_MAP() DECLARE MESSAGE MAP() };
46
#include "stdafx.h" #include "HelloMFCs.h" #include "MainFrm.h #ifdef _DEBUG DEBUG #define new DEBUG_NEW #endif
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();
// 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) {}
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
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()
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; }
52
54
Bucle de Mensajes
56
Clases que no heredan de CObject: Clases de soporte (ej.: CWaitCursor), API servidor de Internet, sincronizacin, etc.
58
59
CObject
CCmdTarget
60
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
Mensajes de Comando
Resultado
73
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); | , , );
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();
// 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
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.
CFindReplaceDialog: permite realizar bsqueda o buscar/reemplazar (no modal, se crea con Create()).
98
Dilogos Predefinidos
CFontDialog: permite elegir una fuente.
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
101
102
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
CComboBoxEx: permite introducir imgenes en los elementos a seleccionar, entre otras mejoras.
106
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).
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
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.
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.
120
123
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
Ventana marco del documento GetActiveView() Ventana marco del documento GetActiveDocument() Ventana principal (MDI) Ventana marco MDIGetActive() GetActiveFrame()
1 m_pMainWnd
CFrameWnd
1 getParent(); 1 g getActiveView(); ();
CView
1..* {POSITION p=GetFirstViewPosition(); GetNextView(p);} 1 g getDocument(); ();
CDocument
128
129
130
Ejemplo
Indice
Programacin bajo Windows. g j Introduccin a las MFCs. Arquitectura Documento/Vista Documento/Vista.
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(); }
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) // }
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); }
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