Ejemplo: dlg_one
Dif�cilmente exista un programa en Windows que no use cajas de di�logos. Simplemente haz click en File/Open de cualquier editor de textos o cualquier otro tipo de editor y �sorpresa! est�s enfrente de una caja de di�logo, una que probablemente te permita escoger el archivo que deseas abrir.
Los di�logos no est�n limitados a los di�logos estandar para abrir un archivo, por el contrario, pueden lucir como se te ocurra. El punto atractivo de los di�logos es que proveen una forma r�pida de ordenar y crear Interfaces Graficas al Usuario (GUI) y tambi�n realizar algunos procesos por default, disminuyendo la cantidad de c�digo que debemos escribir.
Una cosa para recordar es que los di�logos son solo ventanas. La diferencia entre un dialogo y una ventana "normal" es que, con los di�logos, el sistema hace algunos procesos adicionales por default, como crear e inicializar controles y manipular el orden del tab. Todas las APIs que son aplicables a las ventanas "normales" funcionan correctamente en los di�logos y viceversa.
El primer paso es crear el recurso dialogo. La manera en que se hace depende de cada compilador/IDE, al igual que con todos los recursos. Aqui, voy a mostrarte el texto plano del dialogo en el archivo .rc y debes incorporarlo tu mismo en tu proyecto.
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 66
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "My About Box"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
PUSHBUTTON "&Cancel",IDCANCEL,174,35,50,14
GROUPBOX "About this program...",IDC_STATIC,7,7,225,52
CTEXT "An example program showing how to use Dialog Boxes\r\n\r\nby theForger",
IDC_STATIC,16,18,144,33
END
En la primer l�nea, IDD_ABOUTDLG es el ID del recurso. DIALOG es el tipo de recurso y los cuatro numeros son: coordenada X de la esquina superior Izquierda, coordenada Y de la esquina superior Izquierda, Ancho y Alto del dialogo. Estas NO SON PIXELES, est�n expresadas en unidades de di�logos que est�n basadas en el tama�o de la fuente usada por el sistema (y elegida por el usuario). Si tienes seleccionada una fuente grande el dialgo ser� grande y si utilizas una fuente peque�a el dialogo ser� mucho menor. Esto
es importante porque asegura que todos los controles tengan el tama�o apropiado para poder mostrar adecuadamente el texto con la fuente seleccionada. Puedes convertir unidades de di�logo a pixeles en tiempo de ejecuci�n usando MapDialogRect( ). DISCARDABLE le dice al sistema que puede realizar un "swap" para copiar el dialogo de la memoria al disco cuando no est� siendo utilizado para conservar recursos del sistema.
La segunda linea comienza con STYLE y sigue con los estilos de ventana que ser�n usados para crear el di�logo. Esto deber�a estar explicado en CreateWindow() en tus archivos de ayuda. Para poder usar las constantes predefinidas necesitamos agregar #include "windows.h" en nuestro archivo de recursos .rc o en el caso de VC++ podemos usar "winres.h" o "afxres.h". Si utilizas un editor de recursos estos archivos ser�n inclu�dos autom�ticamente, si es necesario.
Con CAPTION indicamos el t�tulo del di�logo.
La l�nea FONT especifica el nombre y tama�o de la fuente que utilizaremos para este di�logo. Esta puede no ser la misma para todas las computadoras, depende de las fuentes que cada persona tenga instaladas y de los tama�os que haya especificado.
Ahora tenemos la lista de controles para crear el di�logo
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
Esta es la l�nea para el bot�n OK. El "&" indica que la letra que sigue (en este caso la "O") puede ser combinada con la tecla Alt para activcar el control mediante el teclado (Alt+O, en este caso). Todo esto es parte del proceso autom�tico que he mensionado.
IDOK es el identificador del control. IDOK es un control pre-definido por lo tanto no necesitamos definirlo. Los cuatro n�meros al final son las coordenadas X e Y de la esquina superior izquierda y el ancho y alto de bot�n, todas en unidades de di�logos.
Si utilizas un editor de recursos para crear di�logos, esta informaci�n deber�a ser puramente acad�mica, de todos modos suele ser necesario conocer como hacerlo directamente en el archivo de recursos (.rc), especialmente si no tienes un editor visual de recursos.
Hay dos controles que tienen un ID IDC_STATIC (el cual es -1), esto es usado para indicar que nunca necesitamos acceder a ellos, por lo tanto no necesitamos un identificador. Sin embargo esto no quita la posibilidad de darle un ID o que editor de recursos lo haga autom�ticamente.
El texto "\r\n" en la linea del CTEXT es el par CR-LF que representa el comienzo de una nueva linea.
Bien, habiendo agregado esto a nuestro archivo de recursos (.rc) necesitamos escribir un Dialog Procedure para procesar los mensajes de este dialogo. No te preocupes esto no es nada nuevo, pr�cticamente es lo mismo que con nuestro Window Procedure (aunque no exactamente).
BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
Hay algunas diferencias importantes entre un Dialog Procedure y un Windows Procedure. Una es que NO llamamos a DefWindowProc( ) para mensajes que no manejamos. Con los di�logos esto es realizado autom�ticamente.
Otra diferencia es que, generalmente, retornamos FALSE para aquellos mensajes que no procesamos y TRUE para aquellos que si procesamos, A MENOS que el mensaje especifique que valor debemos retornar. Observa que esto es lo que hicimos anteriormente, por default, no debemos hacer nada y retornar FALSE, mientras que los mensajes que si procesamos entran en el switch() y retornan TRUE.
La siguiente diferencia es que no llamamos a DestroyWindow() para cerrar el di�logo, si no que utilizamos EndDialog( ). El segundo par�metro es el valor retornado a quien halla llamado a DialogBox().
Por �ltimo, en vez de procesar WM_CREATE, procesamos WM_INITDIALOG para realizar cualquier proceso que sea necesario antes que aparezca el di�logo y luego retornamos TRUE para darle el foco al teclado en el control asignado por default.(Puedes procesar el mensaje WM_CREATE, pero �ste es enviado ANTES que los controles hayan sido creados, por lo tanto no puedes acceder a ellos. Cuando procesamos WM_INITDIALOG los controles ya han sido creados, lo que nos permite acceder
a ellos).
Suficiente, hag�moslo...
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_HELP_ABOUT:
{
int ret = DialogBox(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
if(ret == IDOK){
MessageBox(hwnd, "Dialog exited with IDOK.", "Notice",
MB_OK | MB_ICONINFORMATION);
}
else if(ret == IDCANCEL){
MessageBox(hwnd, "Dialog exited with IDCANCEL.", "Notice",
MB_OK | MB_ICONINFORMATION);
}
else if(ret == -1){
MessageBox(hwnd, "Dialog failed!", "Error",
MB_OK | MB_ICONINFORMATION);
}
}
break;
// Other menu commands...
}
break;
Este es el c�digo que he usado para crear mi dialogo "About", seguramente te preguntas por que est� puesto dentro del manejador WM_COMMAND, si no tienes claro este aspecto, puedes revisar la secci�n de menu�s e iconos. ID_HELP_ABOUT es el dentificador del item men� Help\About.
Debido a que queremos que el men� de nuestra ventana pricipal cree el di�logo, obviamnete debemos poner este c�digo en el WinProc( ) de nuestra ventana principal, no en el Dialog Procedure.
Ademas, he almacenado los valores de retorno de las llamadas a DialogBox( ), solamente con el prop�sito de observar el efecto de presionar dentro del di�logo los dos Botones, Esc, Enter, etc... y poder ilustrar como utilizar los valores de retorno de un di�logo para chequear si tubo �xito, hubo alguna falla o para ver la elecci�n del usuario o alguna otra informaci�n que elijas para envi�rsela de retorno a quien lo llame desde el Dialog Procedure.
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
IDD_ABOUT es el ID del recurso di�logo. hwnd el el handle a la ventana padre del di�logo. AboutDlgProc( ) es, por su puesto, el Dialog Procedure usado para controlar el di�logo.
Un astuto lector eventualmente podr�a haberse preguntado: si DialogBox() no retorna hasta que el di�logo sea cerrado, entonces no podemos procesar mensajes mientras el dialogo est� activo, �como funciona esto?. Bueno, el tema es que los di�logos tienen su propio bucle de mensajes, por lo tanto mientras el di�logo esta siendo mostrado en pantalla (esta activo), nuestro bucle de mensajes es pasado a un segundo plano y empieza a ejecutarse el bucle que Windows utiliza por default. Este bucle es manejado por Windows y tambi�n
se encarga de cosas como mover el foco del teclado de control en control cada vez que presionamos la tecla Tab.
Otro efecto de usar DialogBox( ) es que la ventana principal queda desactivada hasta que el di�logo sea despachado. A veces esto es lo que deseamos y otras veces no, como cuando queremos usar un di�logo con una barra de herramientas flotante. En este caso queremos ser capaz de interactuar con ambos, la ventana y el di�logo. Pero esto ser� visto en la pr�xima secci�n.
Versi�n en espa�ol: Federico Pizarro - 2003