el Guille, la Web del Visual Basic, C#, .NET y más...

Obtener un control de un cuadro de diálogo

 

Autor: RFOG (MVP de Visual C++)
Publicado: 12/Abr/2008
Actualizado: 12/Abr/2008

Cómo obtener un control situado dentro de un cuadro de diálogo sin utilizar una variable DDX, obteniendo el control a partir de su ID de recurso.




 

Introducción:

Estrenemos año con una nueva sección: trucos y cosas para MFC. La verdad es que me he pensado muy seriamente iniciar una sección sobre este tema, ya que casi cualquier cosa que queramos saber, ya está escrita por algún sitio en internet, pero tras reflexionar me he dado cuenta de que en general todo está en inglés. Con esto no pretendo dedicarme a traducir cosas existentes, o al menos no es esa la idea de igual modo que no lo ha sido para la sección de C++/CLI (que sigue viva) y la de bugs; eso no quiere decir que alguna vez, si lo considero interesante, traduzca o parafrasee algo, pero en ese caso, y como viene siendo habitual en mi, así lo diré.

La verdad es que lo que voy a contar en esta entrada es bastante chorra, pero es una de esas cosas que nunca se me queda en la cabeza y siempre tengo que estar buscándolo y recordándolo, así que lo pongo y listo.

Y sin más preámbulo vamos al tajo.

Obtener un control de un cuadro de diálogo

La forma habitual de trabajar con cuadros de diálogo en MFC es derivar una clase de CDialog que toma el valor del ID del recurso del diálogo en cuestión, cosa que suele hacer el asistente adecuado. Dentro de esa clase pondremos nuestras variables y utilizaremos el DDX o intercambio dinámico de datos, para mapear cada control del cuadro con variables que representen a dicho control; también suele hacerlo automáticamente el asistente desde la edición del plantilla, y es una forma muy sencilla de mantener actualizados los controles, casi idéntica a una ficha de Windows Forms.

Pero a veces puede resultarnos inadecuado montar toda la parafernalia del DDX para un control al que solamente le vamos a cambiar algo durante la creación del diálogo. O quizás estemos creando el diálogo de forma dinámica a partir de una plantilla o, como es mi caso actual, cuanta menos memoria ocupe, mejor.

Cada variable DDX es un objeto derivado de CWnd, y ocupa su memoria, aparte de tener datos enlazados en las estructuras globales de la aplicación (quizás más adelante explique cómo funciona eso, aunque ya hay algo publicado por ahí), por lo que en determinadas circunstancias podríamos no querer tener una variable completa.

Entonces, ¿cómo podemos acceder al control? Hay que obtener un puntero a una clase que lo represente. ¿Cómo? Usando GetDlgItem(), pero no la función global de WIN32, sino el método miembro de CDialog (que realmente no está definido en CDialog, sino en CWnd). Este método recibe como parámetro el ID del control o de la ventana hija y devuelve un puntero a CWnd que representa dicho control.

Una vez obtenido el puntero, podemos utilizar los métodos miembro de CWnd o de sus hijas para enviarle mensajes y cambiar su aspecto y/o comportamiento.

Por ejemplo, el código 1:

GetDlgItem(IDC_BTNCONFMS)->EnableWindow(false);

situado dentro de una clase derivada de CDialog deshabilitará en control IDC_BTNCONFMS, que en el caso que nos ocupa es un botón normal y corriente. Lo que hace el código de arriba es dejarlo deshabilitado, de modo que no se pueda presionar.

Pero ¿qué ocurre si nuestro control es, por ejemplo, un CheckBox y queremos marcarlo o desmarcarlo? GetDlgItem() devuelve un puntero a un objeto CWnd, pero CWnd no tiene ningún método para marcar o desmarcar una casilla de verificación.

Una opción perfectamente válida es la de enviarle un mensaje, en concreto un BM_SETCHECK mediante SendMessage() o PostMessage(), ya que ambos métodos están definidos en CWnd, pero resulta una forma bastante bruta de hacerlo.

La forma MFC consiste en convertir el resultado de GetDlgItem() en el tipo de variable que nos interese y luego usar dicha variable: 1:

CButton *ckb=(CButton *)GetDlgItem(IDC_INSTALLKB);
ckb->SetWindowText(TEXT("Remove Keyboard Driver"));
ckb->SetCheck(BST_CHECKED);

Lo acabamos de ver, aunque el ejemplo es bastante atípico pero válido: estamos cambiando el estado de una caja de verificación (esos a los que se les pone una x al hacer clic sobre ellos) pero que tiene la presencia visual de un botón, es decir, se queda resaltado cuando está marcado.

De todos modos hay que andar con cuidado a la hora de realizar este tipo de moldeos, ya que podríamos hacerlo sobre una clase no válida y entonces el resultado podría ser cualquiera, en general el disparo de alguna aserción dentro del código de MFC.

 


Ir al índice de los artículos de RFOG en el sitio del Guille




La fecha/hora en el servidor es: 22/12/2024 7:17:48

La fecha actual GMT (UTC) es: 

©Guillermo 'guille' Som, 1996-2024