Page 1 of 1

Falla creacion de controles diámicos dentro de un diálogo

Posted: Fri Aug 31, 2007 1:53 pm
by gsabattino
Saludos a Todos...

Estoy migrando a FW+xH una aplicación de Laboratorio que esta hecha con FoxPro 2.6 (viejito solo texto)...
El primer problema que se me presentó fue que el autor de la aplicación en Fox utilizó indices IDX a los cuales no pude acceder con xHarbour, pero con la ayuda de algo de documentación que aun se consigue me enteré que FP2.6 también puede manejar indices CDX compatibles con xHarbour, y luego de dedicarle algún tiempo retocando programas hice la migración de IDX a CDX y tengo ambas aplicaciones conviviendo sin problemas a nivel de DBF's...

Ahora se me presenta otro problemita, y es que para tomar los datos de los resultados de los análisis el autor de la aplicación en Fox utilizó una DBF para generar las pantallas (leyendas y get's incluidos) ... cosa que en un principio lo vi como algo absurdo, pero luego de involucrarme mas con la actividad de laboratorio le encontré el sentido al método... son muchas pantallas... de haberse ido por el método convencional tendría que haber hecho no menos de 80 módulos los cuales resolvió solo con uno apoyado en la DBF... Y no solo eso, sino que añadir un examen mas a la aplicación es cuestión de solo añadir los records necesarios a la DBF y listo...

Porque digo que se me presenta el problemita???... pues se trata de migrar una aplicación en Texto a Gráfico... Ya he dibujado 10 diálogos y me falta un montón... Cada diálogo que dibujo tengo que hacer su respectiva asociación a nivel de Prg... Entonces se me ocurrió la idea... Porque no aplicar la misma técnica de tener una DBF y dibujar los controles dinamicamente??? Y es aquí donde se me trancó la cosa... Los controles say's y get's (que es por donde estoy comenzando) que trato de dibujar en forma dinámica dentro del dialogo entran en conflicto con los controles estáticos...

A continuación parte de lo que estoy intentando...

Code: Select all

  ConfResult->( DBSeek( RenglFact->Examen ) )
  do while ( .not. ConfResult->( EOF() ) ) .and. ( ConfResult->Examen=RenglFact->Examen )
    cControl  :=alltrim( ConfResult->Control )
    do case
      case cControl='WTITLE'
        // Este funciona perfecto... claro... actúa sobre un control estático
        aAdd( oSay, NIL )
        nItem     :=len( oSay )
        _cItem    :=strtrim( nItem, 2 )
        bSay      :={ ||  alltrim( ConfResult->Leyenda ) }
        oSay[ &_cItem ]   :=TSay():ReDefine( 501, bSay, oResult:oDlg, '',,,, oControl:oFontSS9 )

      case cControl='WSAY'
        // Este no funciona...
        aAdd( oSay, NIL )
        nItem     :=len( oSay )
        _cItem    :=strtrim( nItem, 2 )
        bSay      :={ ||  alltrim( ConfResult->Leyenda ) }
        oSay[ &_cItem ]   :=TSay():New( ConfResult->Row, ConfResult->Col, bSay, oResult:oDlg, '',;
                                        oControl:oFontSS9, ( ConfResult->Align=='C' ), ( ConfResult->Align=='R' ),,,,,;
                                        ConfResult->Width, 12 )

        /*
Copiado solo para referencia de los parámetros que debo pasar.
METHOD New( nRow, nCol, bText, oWnd, cPicture, oFont,;
            lCentered, lRight, lBorder, lPixels, nClrText, nClrBack,;
            nWidth, nHeight, lDesign, lUpdate, lShaded, lBox, lRaised ) CLASS TSay
        */
    endcase
    ConfResult->( DBSkip() )
  enddo
se produce este error...
Application
===========
Path and name: D:\Sistemas\CVF\Lab32.EXE (32 bits)
Size: 1,522,176 bytes
Time from start: 0 hours 0 mins 4 secs
Error ocurred at: 31/08/2007, 09:18:08
Error description: Error FiveWin/2 Duplicated Id: No: 111

Stack Calls
===========
Called from TDIALOG:DEFCONTROL(326)
Called from TSAY:NEW(127)
Called from GENERICO1P(58)
Called from (b)RESULTADOS(85)
Called from (b)RESULTADOS(170)
Called from TCONTROL:LDBLCLICK(1692)
Called from TWBROWSE:LDBLCLICK(1583)
Called from TWINDOW:HANDLEEVENT(0)
Called from TWBROWSE:HANDLEEVENT(1267)
Called from _FWH(3001)
Called from DIALOGBOX(0)
Called from TDIALOG:ACTIVATE(254)
Called from RESULTADOS(212)
Called from (b)MAINBUTTBAR(290)
Called from TBTNBMP:CLICK(311)
Called from TBTNBMP:LBUTTONUP(479)
Called from TWINDOW:HANDLEEVENT(0)
Called from TBTNBMP:HANDLEEVENT(1267)
Called from _FWH(3001)
Called from WINRUN(0)
Called from TWINDOW:ACTIVATE(860)
Called from MAIN(163)


Ciertamente el control 111 existe en el diálogo y corresponde a un combobox dibujado estáticamente.
A continuación el código del diálogo en el RC.

Code: Select all

Resultados_TomaDatos DIALOG 10, 20, 510, 280
STYLE DS_MODALFRAME | 0x4L | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dlg_Edit"
FONT 6, "MS Sans Serif"
{
 GROUPBOX "", 5001, 1, 24, 508, 256, BS_GROUPBOX
 COMBOBOX 111, 50, 34, 120, 140, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
 COMBOBOX 112, 231, 34, 120, 140, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
 CONTROL 0, 201, "EDIT", ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP, 473, 34, 30, 12
 RTEXT "Temperatura (\xBAC) _:", -1, 405, 36, 64, 8
 RTEXT "Tecnica _:", -1, 188, 36, 40, 8
 RTEXT "Muestra _:", -1, 6, 36, 40, 8
 CTEXT "Titulo", 501, 145, 56, 220, 10
}
Lo que no termino de entender es porque si estoy intentando crear un objeto Say por el método New() el mismo intenta montarse sobre el combobox???

O es que no se pueden combinar controles dinámicos y estáticos en un diálogo???

O es que los diálogos solo funcionan con controles estáticos???

O es que debo ir pensando seriamente en la posibilidad de buscarme otro oficio???

1GB de Gracias de antemano por los comentarios...

Giancarlo J. Sabattino S.
Valencia, Venezuela

Posted: Fri Aug 31, 2007 3:48 pm
by karinha
Error FiveWin/2 Duplicated Id: No: 111

CREA UN LOOPING PARA INCREMENTAR LOS ID´S.

ID := 101

ID := ID + 1

Y asi se va...

Regards, saludos.

Posted: Fri Aug 31, 2007 5:28 pm
by Antonio Linares
La clase TControl usa un dato de clase:
CLASSDATA nInitID INIT 100

Auméntala para que no entre en conflicto con los IDs del recurso: <oCualquierControl>:nInitID := 800

solo es necesario que lo modifiques una vez

Posted: Mon Sep 03, 2007 12:47 pm
by gsabattino
Antonio, no me funciono tu sugerencia...

* Modifique la clase en la linea donde me indicastes y ::GetNewId() devuelve valores relacionados con la modificación.
* Modifique la clase Say para que ::New() admitiera como un ultimo parámetro el identificador y colocando por defecto la llamada a ::GetNewId()... DEFAULT nId :=::GetNewId() y luego asignarlo a la variable de instancia ::nId
* Probé cambiando directamente en el código a ::nId luego de haber declarado el control.

En todos _ el error que se produce es por que no existe el Id, y lo curioso es que justo antes de la activación de diálogo coloqué una parada que me mostrara los Id's de todos los controles del diálogo, y la cantidad de controles como la Id de cada uno corresponde con lo que se le ha asignado bien por recurso (que ya vienen pre-definidos), bien por asignación automática (llamada a ::GetNewId()), o por asignación manual modificando el método New de la clase.

Application
===========
Path and name: D:\Sistemas\CEVALFES\Lab32.EXE (32 bits)
Size: 1,525,760 bytes
Time from start: 0 hours 0 mins 7 secs
Error ocurred at: 02/09/2007, 09:35:59
Error description: Error FiveWin/1 Non defined Id: No: 201

Stack Calls
===========
Called from TCONTROL:INITIATE(364)
Called from TGET:INITIATE(355)
Called from __OBJSENDMSG(0)
Called from OSEND(220)
Called from ASEND(171)
Called from TDIALOG:INITIATE(588)
Called from TDIALOG:HANDLEEVENT(766)
Called from CREATEDLG(0)
Called from TDIALOG:ACTIVATE(283)
Called from TPAGES:DEFAULT(146)
Called from (b)TPAGES(27)
Called from TPAGES:INITIATE(0)
Called from __OBJSENDMSG(0)
Called from OSEND(220)
Called from ASEND(171)
Called from TDIALOG:INITIATE(588)
Called from TDIALOG:HANDLEEVENT(766)
Called from DIALOGBOX(0)
Called from TDIALOG:ACTIVATE(254)
Called from TESTHIPOOSMOTICO(38)
Called from (b)RESULTADOS(85)
Called from (b)RESULTADOS(170)
Called from TCONTROL:LDBLCLICK(1692)
Called from TWBROWSE:LDBLCLICK(1583)
Called from TWINDOW:HANDLEEVENT(0)
Called from TWBROWSE:HANDLEEVENT(1287)
Called from _FWH(3001)
Called from DIALOGBOX(0)
Called from TDIALOG:ACTIVATE(254)
Called from RESULTADOS(212)
Called from (b)MAINBUTTBAR(290)
Called from TBTNBMP:CLICK(311)
Called from TBTNBMP:LBUTTONUP(479)
Called from TWINDOW:HANDLEEVENT(0)
Called from TBTNBMP:HANDLEEVENT(1287)
Called from _FWH(3001)
Called from WINRUN(0)
Called from TWINDOW:ACTIVATE(860)
Called from MAIN(163)

En el primer post olvide colocar que estoy utilizando FW2.4 con xH0.993 por si acaso eso tiene algo que ver.

Por lo pronto he seguido dibujando pantallas a nivel de recursos...

Gracias de antemano por los comentarios,

Giancarlo J. Sabattino S.
Valencia, Venezuela.

Re: Falla creacion de controles diámicos dentro de un diálog

Posted: Mon Sep 03, 2007 2:04 pm
by FiveWiDi
[quote="gsabattino"]Saludos a Todos...

Code: Select all

  ConfResult->( DBSeek( RenglFact->Examen ) )
  do while ( .not. ConfResult->( EOF() ) ) .and. ( ConfResult->Examen=RenglFact->Examen )
    cControl  :=alltrim( ConfResult->Control )
    do case
      case cControl='WTITLE'
        // Este funciona perfecto... claro... actúa sobre un control estático
        aAdd( oSay, NIL )
        nItem     :=len( oSay )
        _cItem    :=strtrim( nItem, 2 )
        bSay      :={ ||  alltrim( ConfResult->Leyenda ) }
        oSay[ &_cItem ]   :=TSay():ReDefine( 501, bSay, oResult:oDlg, '',,,, oControl:oFontSS9 )

      case cControl='WSAY'
        // Este no funciona...
        aAdd( oSay, NIL )
        nItem     :=len( oSay )
        _cItem    :=strtrim( nItem, 2 )
        bSay      :={ ||  alltrim( ConfResult->Leyenda ) }
        oSay[ &_cItem ]   :=TSay():New( ConfResult->Row, ConfResult->Col, bSay, oResult:oDlg, '',;
                                        oControl:oFontSS9, ( ConfResult->Align=='C' ), ( ConfResult->Align=='R' ),,,,,;
                                        ConfResult->Width, 12 )

    endcase
    ConfResult->( DBSkip() )
  enddo
Ya que le metes mano, porque no nombras casa variable segun su tipo (notación úngara le llaman creo)? Para mi oSay sería un objeto no un array, ahora bien aoSay si sería para mi una array de objetos Say.

Que se supone que valor debe retornar:
_cItem :=strtrim( nItem, 2 )
entiendo que sería una cadena de 2 y 'n' decimales (creo que _SET_DECIMALS() o algo así definiría 'n').
yo preferiría _cItem :=strtrim( nItem, 2, 0 )

Si _cItem será una cadena y oSay una array, entonces oSay[ &_cItem ] debería reventar no?

Bueno y todo esto con todo mi respeto, yo he sufrido mis propias barbarides en cuanto a código despues de años de modificaciones.
Saludos
Carlos G.

Re: Falla creacion de controles diámicos dentro de un diálog

Posted: Mon Sep 03, 2007 2:07 pm
by FiveWiDi
[quote="gsabattino"]Saludos a Todos...

Code: Select all

  ConfResult->( DBSeek( RenglFact->Examen ) )
  do while ( .not. ConfResult->( EOF() ) ) .and. ( ConfResult->Examen=RenglFact->Examen )
    cControl  :=alltrim( ConfResult->Control )
    do case
      case cControl='WTITLE'
        // Este funciona perfecto... claro... actúa sobre un control estático
        aAdd( oSay, NIL )
        nItem     :=len( oSay )
        _cItem    :=strtrim( nItem, 2 )
        bSay      :={ ||  alltrim( ConfResult->Leyenda ) }
        oSay[ &_cItem ]   :=TSay():ReDefine( 501, bSay, oResult:oDlg, '',,,, oControl:oFontSS9 )

      case cControl='WSAY'
        // Este no funciona...
        aAdd( oSay, NIL )
        nItem     :=len( oSay )
        _cItem    :=strtrim( nItem, 2 )
        bSay      :={ ||  alltrim( ConfResult->Leyenda ) }
        oSay[ &_cItem ]   :=TSay():New( ConfResult->Row, ConfResult->Col, bSay, oResult:oDlg, '',;
                                        oControl:oFontSS9, ( ConfResult->Align=='C' ), ( ConfResult->Align=='R' ),,,,,;
                                        ConfResult->Width, 12 )

        /*
Copiado solo para referencia de los parámetros que debo pasar.
METHOD New( nRow, nCol, bText, oWnd, cPicture, oFont,;
            lCentered, lRight, lBorder, lPixels, nClrText, nClrBack,;
            nWidth, nHeight, lDesign, lUpdate, lShaded, lBox, lRaised ) CLASS TSay
        */
    endcase
    ConfResult->( DBSkip() )
  enddo
No será
oSay[ nItem ] := ...
en vez de
oSay[ &_cItem ] := ...

Saludos
Carlos G.

Posted: Tue Sep 04, 2007 2:58 pm
by gsabattino
El problema de crear controles dinámicamente en un diálogo ha quedado resuelto...

El asunto está que no se pueden crear controles en forma dinámica si el diálogo viene como un recurso en lugar de crearse por programa...
O sea... para poder crear controles a punta de código el diálogo también tiene que haberse creado a punta de código...
Sería interesante que Antonio nos comentara algo acerca del porqué esa limitación...


Saludos a todos...

Giancarlo J. Sabattno S.
Valencia, Venezuela

Posted: Tue Sep 04, 2007 3:10 pm
by Antonio Linares
Giancarlo,

No existe tal limitación. Aquí tienes un ejemplo funcionando correctamente:

test.prg

Code: Select all

#include "FiveWin.ch"

function Main()

   local oDlg

   DEFINE DIALOG oDlg RESOURCE "test"

   REDEFINE BUTTON ID 120 OF oDlg ACTION MsgInfo( "resource" )

   ACTIVATE DIALOG oDlg ;
      ON INIT AddControl( oDlg )

return nil

function AddControl( oDlg )

   @ 5, 3 BUTTON "source" OF oDlg ACTION MsgInfo( "source" ) SIZE 72, 23
   
return nil   
test.rc

Code: Select all

test DIALOG 70, 67, 194, 119
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Test"
FONT 8, "MS Sans Serif"
{
 DEFPUSHBUTTON "resources", 120, 11, 25, 50, 14
}

Posted: Tue Sep 04, 2007 4:20 pm
by gsabattino
Antonio, es probable que la versión de FW que estoy utilizando sea la que me este dando problemas (FW2.4+xH0.993)...
El ejemplo que colocastes no funciona... igual revienta dando el mensaje
Error FiveWin/1 Non defined Id: No: 801

Por lo pronto ya sustituí en el programa la declaración del diálogo desde recursos por su creación desde código y con una prueba con 1 combobox, 1 group, 3 says y 2 gets, todos con parámetros tomados desde una DBF, está funcionando como esperaba...

1GB de Gracias


Giancarlo J. Sabattino S.
Valencia, Venezuela.