Introducción:
Siguiendo con el texto del mes pasado, ahora nos toca
heredar nuestro control a partir del que Visual Studio nos ha colocado por
defecto en el cuadro de diálogo.
Pero antes de heredar debemos crearnos una variable DDX
para el intercambio entre la clase que representa el diálogo y el propio
diálogo. Para ello hacemos clic con el botón derecho del ratón sobre el
control de lista en la plantilla y seleccionamos “Add Member Variable”. Le
vamos a dar el nombre de “c_lb”:
Si nos fijamos en “Variable Type” veremos que la clase
que representa al control se llama
CVSListBox: ya sabemos de quién heredar. También podemos verlo en el
fichero cabecera del diálogo:
public:
CVSListBox c_lb;
Una vez conocemos la clase, creamos un nuevo par de
ficheros con nuestra herencia. Podemos hacerlo a mano o con el asistente
para clase nueva. Si lo hacemos con el asistente, nos ponemos en el nombre
del proyecto en el Explorador de Soluciones y con el botón derecho del ratón
elegimos Add -> Class. Se nos abre una ventana y elegimos “MFC Class”.
Entonces se nos abre la siguiente ventana, que tiene el único cometido de
elegir la clase base del desplegable y dar el nombre de la nuestra:
Al aceptar, el IDE nos crea los ficheros y el esqueleto
de la clase. En nuestro caso ha añadido dos nuevos ficheros con los nombres
de MyListbox.h y MyListbox.cpp, que contienen el interfaz y el cuerpo de los
nuevos métodos y ha insertado las macros y otras parafernalias que son
necesarias a la hora que nuestras clases formen parte inherente a MFC.
Ahora tan solo nos queda ir al fichero cabecera del
diálogo (en nuestro caso es cambiar_controlDLG.h) y sustituir el tipo de “c_lb”
por el nuestro:
public:
CMyVSListbox c_lb;
};
También tenemos que incluir el fichero cabecera para la
clase Ccambiar_contolDLG sepa qué es CMyVSListbox:
#pragma
once
#include
"afxvslistbox.h"
#include
"MyVSListbox.h"
// Ccambiar_controlDlg dialog
class
Ccambiar_controlDlg :
public
CDialogEx
{
// Construction
public:
Ccambiar_controlDlg(CWnd*
pParent =
NULL);
// standard constructor
// Dialog Data
enum { IDD
= IDD_CAMBIAR_CONTROL_DIALOG };
protected:
virtual void
DoDataExchange(CDataExchange*
pDX);
// DDX/DDV support
// Implementation
protected:
HICON
m_hIcon;
// Generated message map functions
virtual BOOL
OnInitDialog();
afx_msg
void OnSysCommand(UINT
nID,
LPARAM lParam);
afx_msg
void OnPaint();
afx_msg
HCURSOR
OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CMyVSListbox c_lb;
};
Si compilamos y ejecutamos, el programa funciona igual
que antes, pero ahora el cuadro de lista es nuestro cuadro de lista, y en
subsiguientes entradas iremos viendo cómo cambiar el comportamiento.
Si os dais cuenta, la biblioteca MFC
entiende de este tipo de
sustituciones, y si abrimos el diálogo con el editor de diálogos de Visual
Studio, veremos que seguimos teniendo el control de lista exactamente igual
que si fuera el original y no el nuestro.
Esto tiene una explicación muy sencilla: en la
plantilla de diálogo, el control sigue siendo el mismo. Para quien no lo
sepa, los cuadros de diálogo de MFC (y de Win32) vienen definidos en un
lenguaje propio que Microsoft inventó con la salida de la primera
herramienta de desarrollo para Windows: los ficheros de recursos y su
terminología. Si queréis ver dónde y cómo se almacena todo esto, id al
fichero “cambiar_control.rc” en el Explorador de Soluciones y seleccionad
“View Code” con el botón derecho del ratón.
Ahí veréis un fichero de texto con una serie de
instrucciones más o menos coherentes. Aunque hubo una época en la que había
que escribir todo eso a mano, compilar, ver el resultado, volver a cambiar,
y repetir, hace muchísimos años que, salvo excepciones o para cambios
rápidos, todas las herramientas de desarrollo para Windows y C/C++ suelen
llevar su editor visual e integrado.
En el caso que nos ocupa, el cuadro de diálogo
principal queda como:
IDD_CAMBIAR_CONTROL_DIALOG
DIALOGEX 0, 0, 320, 200
STYLE DS_SETFONT |
DS_FIXEDSYS |
WS_POPUP |
WS_VISIBLE |
WS_CAPTION |
WS_SYSMENU |
WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "cambiar_control"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON
"OK",IDOK,209,179,50,14
PUSHBUTTON
"Cancel",IDCANCEL,263,179,50,14
CTEXT
"TODO: Place dialog controls here.",IDC_STATIC,10,96,300,8
CONTROL
"",IDC_MFCVSLISTBOX1,"MfcVSListBox",WS_TABSTOP,7,7,125,186
END
Si os fijáis en la penúltima línea, “CONTROL” etc.
define el cuadro de lista. La cadena “MfcVSListBox” indica que
clase de control es, de modo que
tanto el IDE como luego en ejecución, se sabrá qué pintar.
Luego, el compilador de recursos cogerá ese fichero y
generará una serie de metadatos que irán insertados en el ejecutable y que,
al igual que la reflexión en .NET, construirán el diálogo. La ventaja frente
a .NET es que este proceso es prácticamente inmediato incluso con cuadros de
diálogo con cientos y cientos de controles. Digamos que este método es el
padre de XAML, que es mucho más potente.
Pues bien, lo que hace aquí MFC es que en tiempo de
ejecución, al asignar la clase que se corresponda con ese control, pondrá
nuestra clase en lugar de CVSListbox al modo que se utilizan clases
virtuales: se instancia al padre pero se llama al constructor del hijo, todo
ello de forma automática y transparente para nosotros.
Ir al índice de los artículos de RFOG en el
sitio del Guille