[C con Clase] como passo un array de estructuras a un cuadro de dialogo?

Steven Davidson steven en conclase.net
Lun Ene 8 09:46:06 CET 2007


Hola Francesc,

El pasado 2007-01-07 10:41:44, borubudur escribió:
 
b> hola de nuevo,
b> parece que el método universal para pasar información entre el procedimiento principal y un cuadro de dialogo es mediante una estrucutra, por ejemplo
b> typedef struct stDatos {
b>    char Nombre[80];
b>    int edad;
b> } DATOS;
b> claro que con esta estructura sólo hay capacidad para una persona, por lo tanto mas adelante defino
b> DATOS datos[100];
b> así ya tengo sitio para 100 personas, pero si pretendo comunicarme con un cuadro de dialogo tocaria usar.....
b> DialogBoxParam(hInst, "INFORMACIÓN", hwnd, DlgProc, (LPARAM)&Datos); 

Hasta aquí, vamos por buen camino.

b> para activar el control
b> y para rellenar los datos en el control (listbox, etc..)
b> for (a=0;a<10;a++)SendDlgItemMessage(hDlg,ID_LISTA,LB_ADDSTRING,0,(LPARAM);Datos[a]->Nom);
b> lo que pasa es que Datos[a] no es correcto;
b> me pregunto si la solució pasa por declarar
b> DATOS *datos
b> pero entonces me da la sensación que algo va a ir mal por otro sitio

Podrías declarar un puntero en lugar de un array, pero entonces tocaría crear memoria dinámicamente. Si sabes que vas a usar 100 estructuras, entonces sigue usando un array (estático).

Ahora bien, el bucle es incorrecto. Escribes:

for (a=0;a<10;a++)
  SendDlgItemMessage(hDlg,ID_LISTA,LB_ADDSTRING,0,(LPARAM);Datos[a]->Nom);

Al tratarse de 100 estructuras, supongo que en este caso, la cabecera del bucle debería ser:

for( a=0; a<100; a++ )

En cuanto al uso de 'Datos', tienes que tener en cuenta que el procedimiento del diálogo acepta un valor de tipo 'LPARAM'. Por lo tanto, debemos cambiar su tipo a la hora de usar tal valor; o sea, necesitamos hacer un cásting. Esto es,

BOOL CALLBACK DlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  switch( msg )
  {
    case WM_INITDIALOG:
      for( a=0; a<100; a++ )
        SendDlgItemMessage( hDlg, ID_LISTA, LB_ADDSTRING, 0,
                 (LPARAM) (((DATOS *)lParam)[a]->Nom) );
      return TRUE;
  }
  ...
}

Lo que hacemos es realizar un cásting a 'lParam' para que vuelva a ser el tipo 'DATOS *' para poder operar con tal valor. Luego el valor de la expresión pasa a ser un 'LPARAM', para no tener complicaciones con la concordancia de tipos.

Como puedes ver, lo anterior es algo engorroso con tantos cástings y paréntesis. Además, tendrías que hacer algo parecido cada vez que quieras usar el array de estructuras. Por lo tanto, sugiero crear un puntero estático y local al procedimiento del diálogo, para que no tengas que estar haciendo tantos cástings. Esto sería,

BOOL CALLBACK DlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  static DATOS *Datos;

  switch( msg )
  {
    case WM_INITDIALOG:
      Datos = (DATOS *) lParam;
      for( a=0; a<100; a++ )
        SendDlgItemMessage( hDlg, ID_LISTA, LB_ADDSTRING, 0,
                 (LPARAM) (Datos[a]->Nom) );
      return TRUE;
  }
  ...
}

Ahora podemos usar 'Datos' donde queramos, dentro de 'DlgProc()'.


Espero que haya aclarado la duda.

Steven


Más información sobre la lista de distribución Cconclase