Newsgroup: it.comp.lang.vo-clipper
Titolo: Help on Combo Box

Ciao a tutti,
questa volta il mio problema è questo:
Ho un combo box, un server con due campi CODICE e DESCRIZIONE e devo
riempire il combo box in modo un po' particolare ossia quando apro la
tendina
mi deve comparire nell'elenco il CODICE assieme alla DESCRIZIONE però
quando seleziono una voce voglio che rimanga visualizzato solo il CODICE.
Come posso fare? Qualcuno ha qualche esempio da consigliarmi?
Ex.       ----------------
            | 000001 |V|
             ---------------------------------------------
            | 000001 - Rossi Antonio              |
            | 000002 - Mario Bianchi              |
            | 000003 - Aldo Marte                   |
            | 000005 - Andrea Colombo        |
            ----------------------------------------------
Spero di essermi spiegato... Grazie ancora, ciao
Alan D.G.

Caro Alan :
La combo (come la listbox) usa il metodo FILLUSING,il quale crea un array
con il quale riempire, tale combo, per fare ciň che vuoi tu  devi crearti
nel metodo postinit un array   in questo modo :
aClienti := {}
DO WHILE .not. oClienti:EOF    //  file dei clienti
     AAdd(aClienti,{oClienti:COGNOME+"  "+oClienti:NOME,oClienti:CODCLI})
     oClienti:Skip()
ENDDO
SELF:oDCComboCliente:FillUsing(aClienti)     //   riempie il combo
L'array usato per il fillusing č a due dimensioni il primo subarray č ciň
che devi visualizzare, il secondo č ciň che deve ritornare (il codice)
naturalmente devi dichiarare l'array come GLOBAL a nella finestra alle
proprieta' del combo devi dirgli di usare un array (appunto...questo)
Ok ?
Fammi sapere
Enio

 
oppure puoi usare un metodo della classe che contiene il combo es. 
METHOD MyFillCombo() class MIACLASSE
local aClienti as array
aClienti := {}
 DO WHILE .not. oClienti:EOF    //  file dei clienti
      AAdd(aClienti,{oClienti:COGNOME+"  "+oClienti:NOME,oClienti:CODCLI})
      oClienti:Skip()
 ENDDO
 
RETURN aClienti
e nella finestra delle proprietà del Combo scegliere il USE METHOD
MyFillCombo() così non
devi dichiarare l'  ARRAY come GLOBAL 
Saluti
Paolo Calzi

Ciao Enio,
scusa forse non mi sono spiegato correttamente, il mio problema non è
il valore di ritorno, so che esiste la possibilità di riempire un combo con
un array multidimensionale; cerco di spiegarmi meglio:
Supponiamo di avere una combo con dentro N items...
Testo visualizzato nella combo esplosa "CODICE - DESCRIZIONE"
Testo visualizzato (se selezionato) nella combo chiusa "CODICE"
Valore di ritorno "CODICE"
oppure
Testo visualizzato nella combo esplosa "nessuno" al suo posto un'icona
Testo visualizzato (se selezionato) nella combo chiusa "CODICE" riferito
all'icona
Valore di ritorno "CODICE"
oppure
Testo visualizzato nella combo esplosa "nessuno" al un elenco di colori
Testo visualizzato (se selezionato) nella combo chiusa "CODICE" riferito al
colore
Valore di ritorno "CODICE"
Spero di essermi spiegato... grazie comunque, ciao...

Valore di ritorno "CODICE"
[snip]
Beh, non e' difficle, basta che per riempire il combobox utilizzi un metodo e
come primo elemento dell'array metti CODICE + DESCRIZIONE e come secondo (
valore di ritorno e quindi quello visualizzato ) CODICE.
Di seguito ti riporto il codice del metodo da usare nel FillUsing()
METHOD GetCodice() CLASS MyWindow
	LOCAL oServer AS DBServer
	LOCAL aValue AS ARRAY
 
	aValue := {} // array a 2 dimensioni
 
	oServer := NomeTuoServer{} 
	oServer:GoTop()
	WHILE !( oServer:Eof )
	   AAdd( aValues, { oServer:CODICE +" " + oServer:DESCRIZIONE,
	    	            oServer:CODICE } )
	   oServer:Skip()
	ENDDO
	oServer:Close()	
 
	RETURN aValues
----------------------------------------------
SySTEMA di Stefano Costagli
Soluzioni per professionisti
Email : 
stec...@promix.it
EMail : 
vo...@usa.net
----------------------------------------------

Non ci siamo ancora...
Ho già usato questo metodo, ho usato il metodo GetLookUpTable combinato
con un CodeBlock per riempire, tramite FillUsing, il combo...
La differenza è questa:
Con questi metodi ho:
- Combo CHIUSA con ITEM selezionato-> 00001 - Mario Rossi
- Combo APERTA:
   ITEM selezionato -> 00001 - Mario Rossi
   LISTA items         -> 00001 - Mario Rossi
                                      00002 - Bianchi Aldo
                                      0000X - Mia Verdi
- Valore di RITORNO (nel caso di questa selezione) -> 00001
io voglio arrivare ad avere:
- Combo CHIUSA con ITEM selezionato->  00001
- Combo APERTA:
    ITEM selezionato -> 00001
    LISTA items         -> 00001 - Mario Rossi
                                       00002 - Bianchi Aldo
                                       0000X - Mia Verdi
- Valore di RITORNO (nel caso di questa selezione) -> 00001
La differenza è nella COMBO chiusa con un ITEM selezionato, la selezione
deve essere solo ed esclusivamente il codice mentre se esplodo devo poter
vedere il tutto.
Spero di essere stato chiaro... non mandatemi a quel paese.
Grazie ancora, ciao


Saluti,
Antonello
*------------------------------------------------*
* Oggi è domani, ieri è passato
*------------------------------------------------*

Antonello sei un grande!
Finalmente qualcuno mi ha capito...
Io ho visto queste ComboBox in MxW (Mago x Windows), sviluppato
in Visual Studio e quindi un modo ci deve essere...
Anch'io sto indagando, proverò anche sul MSDN On Line...
Se trovo qualcosa ti faccio sapere...
Grazie
Ciao

Ehilà,
Sono riuscito a cambiare il testo della Combo aperta ma non
riesco a ridimensionare il rettangolo di clip ?!? (mi tronca il testo)
Come devo fare? Qualcuno sa aiutarmi?
Ciao...

Bingo!!!
Ce l'ho fatta... riesco a gestire tutto...
Grazie ad Antonello per l'indizio fornitomi...
Ciao a tutti

,

Estrapolato dal Win32SDK:
An application sends the CB_SETDROPPEDWIDTH message to set the maximum
allowable width, in pixels, of the list box of a combo box with the
CBS_DROPDOWN or CBS_DROPDOWNLIST style. 
CB_SETDROPPEDWIDTH 
wParam = (WPARAM) wWidth,     // width of list box, in pixels 
lParam = 0,                   // not used, must be zero 
 
quindi...
SendMessage( Combo:Handle(), CB_SETDROPPEDWIDTH, <larghezza>, 0l )
dovrebbe funzionare,
Antonello.



Bene, me ne rallegro.
Peccato che non sia di alcuna utilita' per gli altri saperlo,
visto che non dici come.
Pensavo che questo fosse un newsGroup ...
Ciao
-- 
Sergio Tugnoli  
EMail Address: 
ser...@bologna.enea.it

Scusa hai ragione,
ma ero preso e volevo solo far sapere ad Antonello di
non sprecare tempo per cercare di risolvere un problema
che non era il suo.
Ecco come fare:
1. Innanzitutto bisogna eseguire l'override della __FORMDIALOGWINDOW
altrimenti non arrivano i messaggi utili:
METHOD Dispatch( oEvent ) CLASS __FORMDIALOGWINDOW
    // Devo fare l'override per gestire il disegno degli item
    LOCAL oObject AS OBJECT
    LOCAL hHandle AS PTR
    LOCAL uRet    AS USUAL
    IF oEvent:Message = WM_DRAWITEM
        // Handle del controllo
        hHandle := GetDlgItem(oEvent:Window:Handle(), oEvent:wParam)
        // Oggetto VO
        oObject := GetObjectByHandle(hHandle)
        // Controllo se esiste il metodo
        IF IsMethod( oObject, #DrawItem )
            RETURN oObject:DrawItem( oEvent )
        ENDIF
    ENDIF
    uRet := SUPER:Dispatch(oEvent)
    RETURN uRet
2. Bisogna assegnare al controllo i seguenti STILI:
 (Io ho creato una nuova entry nel MIOWED.INF richiamato da
  CAVOWED.INF, altrimenti sono settabili dai Tab Styles e
  ExtStyles delle proprietà del COMBOBOX)
- WS_TABSTOP
- WS_CHILD
- CBS_DROPDOWN
- WS_VSCROLL
- CBS_DISABLENOSCROLL
- CBS_HASSTRINGS
- CBS_OWNERDRAWFIXED
- WS_CLIPCHILDREN
- WS_CLIPSIBLINGS
- CBS_NOINTEGRALHEIGHT
3. A questo punto ho definito il metodo DRAWITEM nella
    mia classe COMBOBOX
METHOD DrawItem( oEvent ) CLASS myCOMBO
    LOCAL lpdis  AS _winDRAWITEMSTRUCT
    LOCAL uValue AS USUAL
    LOCAL dwPos  AS DWORD
    LOCAL cText  AS STRING
    // lParam contiene la struttura
    lpdis := PTR( _CAST, oEvent:lParam )
    IF lpdis.ItemAction == ODA_DRAWENTIRE .OR. ;
        lpdis.ItemAction == ODA_SELECT
        // Rettangolo di selezione
        IF _AND( lpdis.itemState, ODS_SELECTED ) > 0
            SetBkColor( lpdis.hDC, GetSysColor( COLOR_HIGHLIGHT ))
            SetTextColor( lpdis.hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ))
      ELSE
            SendMessage( GetParent( SELF:Handle() ), WM_CTLCOLORLISTBOX, ;
                                        DWORD(_CAST,lpdis.hDC),
                                        DWORD(_CAST,SELF:Handle()))
        ENDIF
        // Solo se ho un item da disegnare
        IF lpdis.ItemID != -1
            // Valore assegnato
            uValue := SELF:GetItemValue( lpdis.ItemID + 1 )
            // Ricerco il Codice aValues è una variabile di classe
            // utilizzata per riempire la combo
            dwPos := AScan( SELF:aValues, { | aVal | aVal[1] == uValue })
            IF dwPos > 0
                // CODICE + DESCRIZIONE
                cText := SELF:aValues[dwPos,1] + " - " + ;
                               SELF:aValues[dwPos,2]
                // Scrivo l'item nel COMBO
                ExtTextOut(lpdis.hDC, lpdis.rcItem.Left, lpdis.rcItem.Top,;
                ETO_CLIPPED + ETO_OPAQUE, @lpdis.rcItem, ;
                AsPsz( cText ), SLen( cText ), NULL_PTR )
            ENDIF
        ENDIF
        // Rettangolo di Focus
        IF _AND( lpdis.itemState, ODS_FOCUS ) > 0
            DrawFocusRect( lpdis.hDC, @lpdis.rcItem )
        ENDIF
    ELSEIF lpdis.ItemAction == ODA_FOCUS
        // Rettangolo di Focus
        DrawFocusRect(lpdis.hDC, @lpdis.rcItem)
    ENDIF
    RETURN 1L
4. Inizializzare la combo come segue
METHOD InitCombo() CLASS myCombo
    LOCAL uValue   AS USUAL
    LOCAL hDC      AS PTR
    LOCAL cText    AS STRING
    LOCAL tSIZE    IS _winSIZE
    LOCAL I, dwLen AS DWORD
    // CODICE + DESCRIZIONE
    SELF:aValues := SELF:oServerRel:GetLookUpTable( 1000, ;
                                   AsSymbol( SELF:cNomeCampo ), ;
                                   AsSymbol( SELF:cNomeCampo2 )
    dwLen := ALen( SELF:aValues )
    SELF:Clear()
    // Ridimensiono il rettangolo di Drop
    cText := NULL_STRING
    FOR I := 1 UPTO dwLen
        IF SLen(SELF:aValues[I,1]+" - "+SELF:aValues[I,2])>SLen(cText)
            cText := SELF:aValues[I,1] + " - " + SELF:aValues[I,2]
        ENDIF
        SELF:AddItem( SELF:aValues[I,1],, SELF:aValues[I,1] )
    NEXT
    // Calcolo la dimensione massima per il Combo Dropper
    hDC  := GetDC( SELF:Handle() )
    GetTextExtentPoint32( hDC, String2Psz( cText ), SLen( cText ), @tSIZE )
    ReleaseDC( hDC, SELF:Handle() )
    SendMessage( SELF:Handle() , CB_SETDROPPEDWIDTH, tSIZE.cx, 0 )
    RETURN NIL
E il gioco è fatto.
L'unica pecca è che il Combo ha un altezza rispetto alle normali combo
un pocchettino più alta, non ho ancora capito come fare a metterlo apposto,
anzi se qualcuno ha qualche idea...
Una combo normale (no ownerdraw) ha un'altezza di 20 pixel mentre quella
con lo stile OwnerFixed è alta 24 ?!?
Ciao a tutti e buon lavoro...
P.S. scusate l'impaginazione ma non potevo far di meglio.

 Ti ringrazio...
Ciao Sergio,
    ho risolto anche il problema relativo all'altezza del controllo...
    I nostri amici americani mi hanno aiutato su come fare a
    cambiare l'altezza di una combo, si può fare RunTime,
    basta definire e usare:
ACCESS EditHeight CLASS MyCombo
    IF SELF:ValidateControl()
        RETURN SendMessage( SELF:Handle(), CB_GETITEMHEIGHT, ;
                                                     DWORD(_CAST, -1L ),
0L )
    ENDIF
    RETURN 0
ASSIGN EditHeight( uValue ) CLASS MyCombo
    IF SELF:ValidateControl()
        SendMessage( SELF:Handle(), CB_SETITEMHEIGHT, ;
                                    DWORD(_CAST, -1L), uValue )
        RETURN uValue
    ENDIF
    RETURN 0
Forse sono già definiti all'interno della GUI comunque io li ho
ridefiniti, provati, usati e funzionano...
Ciao a tutti...