UNIDAD 5: CAJAS DE DIALOGO
CAJAS DE DIALOGO Las cajas de diálogo son usadas primero como dispositivos de entrada/salida. Como tal, una caja de diálogo puede ser considerada como una "caja negra" de entrada/salida lo que significa que no tienes que saber cómo funciona internamente una caja de diálogo para usarla, sólo tienes que saber cómo interactuar con ella. Es un principio de la programación orientada a objetos llamado encapsulamiento u ocultamiento de la información. Si la caja negra es *perfectamente* diseñada , el usuario puede emplearla sin tener conocimiento de cómo funciona. Lo único es que la caja negra debe ser perfecta, algo difícil de alcanzar en el mundo real. La API de Win32 también ha sido diseñada como una caja negra. Las cajas de diálogo han sido diseñadas para reducir la carga de trabajo del programador. Normalmente si se tiene que poner controles de ventanas hijas sobre una ventana normal, hay que subclasificarlas y escribir uno mismo la lógica del teclado. Pero si se ponen en una caja de diálogo, Windows manejará la lógica por tí. Sólo hay que saber cómo obtener la entrada del usuario de la caja de diálogo o como enviar órdenes a ella. Como el menú, una caja de diálogo se define como un recurso. Se esc ribe una plantilla describiendo las características de la caja de diálogo y sus controles y luego se compi la el guión de recursos con un compilador de recursos.
LIBRERÍA COMCTL32 Windows nos provee de muchos recursos, pero ya que hay muchos, cargarlos todos en memoria y registrarlos sería un despilfarro de recursos. Todos ellos, con excepción del control "rich edit", están almacenados en comctl32.dll, desde donde las aplicaciones pueden cargarlas cuando se quiera usarlos. El control "rich edit" reside en su propia dll, richedXX.dll. Para cargar comctl32.dll se incluye una llamada a InitCommonControls en tu programa. InitCommonControls es una función en comctl32.dll, así que refiriéndola en cualquier parte del código de tu programa hará que el cargador de archivos cargue comctl32.dll cuando corra tu programa. ¡Esta función no hace NADA! Su unica instrucción es "ret". Su único propósito es incluir la referencia a comctl32.dll en la sección de importación de m anera que el caragador de archivos la cargue cada vez que el programa sea cargado. El verdadero caballo de batalla es el punto de entrada de la función en la DLL que registra todas las clases de controles comunes cuando es cargada la dll. Los controles comunes son creados sobre la base de esas clases así como los controles de ventana hija tales como "edit", "listbox", etc.
CAJAS DE DIALOGO Todos los recursos se encuentran en el mismo archivo de guión de recursos. Se Puede emplear cualquier editor de texto para escribir un guión de recursos, pero no es recomendable. Hay que usar un editor de recursos para hacer la tarea visualmente ya que arreglar la disposición de los controles en la caja de diálogo es una tarea difícil de hacer manualmente. Utilizaremos el editor de recursos que viene con el RadASM se puede crear en forma fácil y rápida con estos pasos: 1. 2. 3. 4.
En el menú archivo, seleccione Nuevo Proyecto Escriba el nombre y descripción del proyecto En el asistente de proyectos en la parte de plantilla seleccione DialogApp.tpl Presione aceptar hasta que termine el asistente de proyectos
Se genera un proyecto de caja de dialogo, con archivos .asm, .inc, .dlg y .rc Si se corre este proyecto, se genera una caja de dialogo con el caption con el nombre del archivo .dlg
FUNCION DialogBoxParam El código para mostrar una ventana simple utilizando las cajas de dialogo es más sencil lo que cuando lo hacemos con puras APIS. En el código generado podemos ver el uso de la funcion API DialogBoxParam, que se encuentra en la librería user32.lib: int DialogBoxParam( HANDLE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam
// manipulador a la instancia de la aplicación // identifica el recurso de cuadro de diálogo // manipulador a la ventana propietaria // dirección del procedimiento de diálogo // valor de inicialización );
Esta función es la principal en nuestro programa, por que es la causante de mostrar la ventana que esta en el recurso y además ubicar la dirección donde se encuentra los procesos de ella, veamos para que sirva cada uno de los parámetros. dwInitParam.- Definimos con que valor queremos que tenga al inic io el parámetro lParam, esto no se usara en nuestro programa y colocaremos el valor NULL.
FUNCION DialogBoxParam DialogBoxParam, hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL hInstance.- Especificamos el manejador de la instancia del modulo. lpTemplate.- Especificamos el ID de nuestra caja de dialogo, ese ID nosotros lo podemos determinar en las propiedades de la caja: El ID de nuestra caja es 101 y el nombre es IDD_DIALOG1, ese datos lo debemos declarar en nuestro archivo INC en la sección const:
hWndParent.- Definimos el handle de donde pertenece la ventana, aquí ponemos NULL por ser nuestra ventana principal, si en caso fuera la segunda ventana especificaremos el handle de la primera ventana (padre). lpDialogFunc.- Definimos la dirección de la etiqueta donde se encuentra los procedimientos. DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
PROCEDIMIENTO DE DIALOGO DlgProc proc hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM Mov eax,uMsg .if eax==WM_INITDIALOG .elseif eax==WM_COMMAND .elseif eax==WM_CLOSE invoke EndDialog,hWin,0 .else Mov eax,FALSE ; movemos a EAX el valor 0 para reciclar los mensajes que no utilizamos, ; si no hacemos esto, no será compatible con window Xp y NT ret .endif Mov eax,TRUE ret DlgProc endp Como observamos este procedimiento es similar a los procesos de las ventanas con puras APiS que hemos creado en el capitulo anterior, porque toda ventana maneja los mismos mensajes con excepción de algunos que son solo para Dialog como por ejemplo WM_INITDIALOG, este mensaje se envía antes de mostrar la caja de dialogo en el escritorio, Para diferenciar los mensajes que son solo para cajas de diálogo, se pone la palabra DIALOG al final del mensaje.
CAJAS DE DIALOGO CON BOTONES 1. 2. 3. 4. 5. 6. 7. 8. 9.
Abra el recurso *.dlg. Seleccione el control botón y ubique dos dentro de la caja de diálogo. Importante: Identificar el ID de los botones Cambie el nombre (name) a boton01 y boton02. En el archivo *.inc declare estos nombres como constantes y asígneles su ID, de esta manera podremos referirnos a los botones por el nombre asignado. En el archivo *.asm ubíquese en DlgProc. Pase a edx wParam (La variable wparam contiene el ID del control que seleccionemos). Ponga el código correspondiente a la acción a realizar por boton01 y boton02. Para salir de la caja de diálogo, ponga la siguiente instrucción: invoke EndDialog, hWin,0 En el archivo *.inc declare el texto y caption de la ventana
CAJAS DE DIALOGO CON BOTONES 10. 11.
Para cambiar el título de los botones, cambie el caption de cada uno de ellos en el archivo *.inc Para cambiar el caption de la caja de diálogo, cambie el caption del objeto en el archivo *.inc
EXTRACCION DEL CODIGO DE NOTIFICACION mov eax,wParam mov edx,eax shr edx,16 .IF dx==BN_CLICKED .if ax == boton01 .elseif ax == boton02 .endif .endif BN_CLICKED este código de notificación se envía cuando pulsamos cualquier botón. Por ejemplo el ID del boton01 es 1001 en decimal (3E9 en hex.), cuando nosotros pulsamos el boton01 el valor de wParam será igual a 00003E9h donde: El código de notificación: 0000 igual BN_CLICKED. El ID del control: 03E9. mov eax,wParam mov edx,eax shr edx,16 .IF DX==BN_CLICKED .endif
; EAX = 00003E9h ; Movemos el contenido de EAX a EDX = 00003E9h ; EDX = 00000000 ; Compara si DX es igual a CERO
CAMPOS EDITABLES La función GetDlgItemText recupera el título o el texto asociado con un control en un cuadro de diálogo. UINT GetDlgItemText( HWND hDlg, // manejador al cuadro de diálogo int nIDDlgItem, // identificador del control LPCTSTR lpString, // dirección del buffer de texto int nMaxCount // máximo tamaño de la cadena ); Parámetros: hDlg: Identifica al cuadro de diálogo que contienen el control. nIdDlgItem: Especifica el identificador del control del que se recuperará el título o el • •
texto. lpString: Puntero al buffer que recibirá el título o el texto. nMaxCount: Especifica la longitud máxima, en caracteres, de la cadena a copiar en le
• •
buffer apuntado por lpString. Si la longitud de la cadena excede el límite, la cadena se truncará. Valor de retorno
Si la función tiene éxito, el valor de retorno indicará el número de caracteres copiados a buffer, sin incluir el carácter nulo de terminación.
CAMPOS EDITABLES La función SetDlgItemText cambia el título o el texto de un control de un cuadro de diál ogo. BOOL SetDlgItemText( HWND hwndDlg, // manipulador al cuadro de diálogo int idControl, // identificador del control LPCTSTR lpsz // texto a poner ); Parámetros: hwndDlg: idControl: lpsz: •
• •
Identifica al cuadro de diálogo que contienen el control. Especifica el identificador del control que recibe el mensaje. Puntero a cadena terminada en cero que contiene el texto a ser copiado al control.
Valor de retorno
Si la función tiene éxito, el valor de retorno es TRUE. Si la función falla, el valor de retorno es FALSE.
MENSAJES DE WINDOWS El sistema operativo Windows, es un sistema conducido por "eventos", como las pulsaciones de tecla, movimientos y acciones con el Mouse, arrastre y dibujado de ventanas, entre muchos otros. Las aplicaciones Windows, pueden comunicarse entre si y pasarse información básicamente por un sistema de mensajes, mantenido por el mismo Sistema Operativo. El sistema de mensajes de Windows, las aplicaciones, aunque no compartan la memoria, comparten el mismo sistema operativo. Los últimos sistemas operativos son más estables, donde se ve cuanto tiempo de procesador tiene cada proceso y poder detenerlo sin temor a que se cuelgue el sistema operativo. Todos los procesos mediante API's pueden ver la cola de mensajes de Windows y así tomar los suyos y continuar con su trabajo, de esta manera podemos comunicar dos o mas programas entre si. Windows mantiene una cola de mensajes para cada aplicación. Cada aplicación recoge sus mensajes y los procesa. Esto se basa en tres componentes principales: Cola de mensajes: administrada por Windows, para que cada aplicación recoja sus mensajes en cuanto le toca su turno de procesador. Ciclo de mensajes: es un ciclo que tiene cada programa que se encarga de recoger estos mensajes. Procedimiento de ventana: Cada ventana tiene un procedimiento que procesa los mensajes que son pasados por el ciclo de mensajes. •
•
•
FUNCION SENDMESSAGE Por ejemplo si queremos enviar un icono a nuestra ventana especificamos el manejador de la ventana, el tipo de mensaje, el tamaño del icono, y el manejador del icono. De esta manera declaramos la función SendMessage para enviar un icono a nuestro programa: SendMessage, hWin.- Manejador de la ventana. WM_SETICON.- Tipo de mensaje. ICON_BIG.- Tamaño del Icono. h_icono.- manejador del icono. Si nosotros queremos cerrar nuestra ventana principal uno de tantos métodos sería enviando el mensaje WM_CLOSE ejemplo: SendMessage.hWin.- Manejador de la ventana. WM_CLOSE.- Tipo de mensaje. 0.- No especificamos. 0.- No especificamos.
MENSAJES DE WINDOWS Todos los mensajes de Windows, tienen un numero que los identifica, siempre definidos en Constantes, los nombres de constantes de mensajes Windows, comienzan con WM_ (Windows Message o Mensaje Windows. El proceso que se da para manipular un mensaje es el s iguiente: a) Ocurre un evento en el sistema. b) Windows coloca la información del evento en una estructura de mensaje y lo coloca en la cola de mensajes. c) El ciclo de mensajes de la aplicación recoge el mensaje. d) La cola de mensajes manda el evento al procedimiento de ventana adecuado. e) Se interpreta el mensaje en su aplicación. Algunos mensajes: WM_ACTIVATE
La ventana ha obtenido el foco.
WM_CLOSE
La ventana va a ser cerrada.
WM_COMMAND
Ha sido seleccionada una opción del menú.
WM_CREATE
La ventana ha sido creada.
WM_LBUTTONDBLCLK
Se ha hecho doble-click en el botón izquierdo
WM_LBUTTONDOWN
Se ha hecho click en el botón izquierdo.
WM_MOUSEMOVE
El ratón se ha movido.
WM_MOVE
La ventana se ha movido.
MENSAJES SOPORTADOS POR ENSAMBLADOR (WINDOWS.INC) WM_USER WM_NULL WM_CREATE WM_DESTROY WM_MOVE WM_SIZE WM_ACTIVATE WM_SETFOCUS WM_KILLFOCUS WM_ENABLE WM_SETREDRAW WM_SETTEXT WM_GETTEXT WM_GETTEXTLENGTH WM_PAINT WM_CLOSE WM_QUERYENDSESSION WM_QUIT
WM_QUERYOPEN WM_ERASEBKGND WM_SYSCOLORCHANGE WM_ENDSESSION WM_SHOWWINDOW WM_WININICHANGE WM_SETTINGCHANGE WM_WININICHANGE WM_DEVMODECHANGE WM_ACTIVATEAPP WM_FONTCHANGE WM_TIMECHANGE WM_CANCELMODE WM_SETCURSOR
WM_MOUSEACTIVATE WM_CHILDACTIVATE WM_QUEUESYNC WM_GETMINMAXINFO
WM_PAINTICON WM_ICONERASEBKGND WM_NEXTDLGCTL WM_SPOOLERSTATUS WM_DRAWITEM WM_MEASUREITEM WM_DELETEITEM WM_VKEYTOITEM WM_CHARTOITEM WM_SETFONT WM_GETFONT WM_SETHOTKEY WM_GETHOTKEY WM_QUERYDRAGICON WM_COMPAREITEM WM_GETOBJECT WM_COMPACTING WM_OTHERWINDOWCREATED WM_OTHERWINDOWDESTROYED WM_COMMNOTIFY
AGREGANDO UN ICONO Si queremos enviar un icono a nuestra ventana especificamos el manejador de la ventana, el tipo de mensaje, el tamaño del icono, y el manejador del icono. De esta manera declaramos la función SendMessage para enviar un icono a nuestro programa: SendMessage, hWin WM_SETICON ICON_BIG h_icono
Manejador de la ventana. Tipo de mensaje. Tamaño del Icono. Manejador del icono.
Si nosotros queremos cerrar nuestra ventana principal uno de tantos métodos seria envi amos el mensaje WM_CLOSE ejemplo: SendMessage.hWin WM_CLOSE 0 0
Manejador de la ventana. Tipo de mensaje. No utilizado. No utilizado.