Newsgroup: it.comp.programmare.win32
Titolo: Come creare un button grafico?

Ciao,
si, sono di nuovo io.
Volendo fare i buttons grafici come da norton system works 2000, ho cercato
nel msdn, dove ho trovato che dovrei scrivere della classe CButton una nuova
funzione OnDraw. Io, hehe, peró non so da dove iniziare, dato che non so
come sia la funzione originale. Qualcuno mi puó spiegare come diavolo posso
fare?
Grazie
Lukas Demetz

 funzione OnDraw.
Sei sicuro che non sia invece DrawItem...?  CButton non ha nessuna
funzione OnDraw, ma ha una funzione virtuale DrawItem che serve
proprio allo scopo che dici (immagino -- l'applicazione che porti ad
esempio non la conosco).  Se il bottone viene creato con il bit di
stile BS_OWNERDRAW, ogni volta che deve disegnare se stesso ne
viene chiamata appunto la funzione DrawItem, passando una struttura
che contiene tutti gli elementi necessari per il disegno stesso.
La logica e` la stessa che ho mostrato nel mio tutorial, che e`
sempre a 
http://aleax.supereva.it/
, in termini di nude API.  Con
il framework e` piu` facile, certo:
In pippo.h:
    class CPippo: public CButton {
    public:
        virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
        BOOL Create( LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect,
            CWnd* pParentWnd, UINT nID );
    };
In pippo.cpp:
    BOOL CPippo::Create( LPCTSTR lpszCaption, DWORD dwStyle, const RECT&
rect,
            CWnd* pParentWnd, UINT nID )
    {
        return CButton::Create(lpszCaption, dwStyle|BS_OWNERDRAW, rect,
            pParentWnd, nID);
    }
    void CPippo::DrawItem(  LPDRAWITEMSTRUCT lpDrawItemStruct )
    {
        // disegna come desideri sul contesto lpDrawItemStruct->hDC
        // secondo i campi itemAction e itemState, ad esempio...:
        CDC dc; dc.Attach(lpDrawItemStruct->hDC); dc.SaveDC();
        CBrush brush;
        if(lpDrawItemStruct->itemState & ODS_SELECTED) {
            brush.CreateSolidBrush(0x00FF00);
        } else {
            brush.CreateSolidBrush(0x0000FF);
        }
        dc.SelectObject(&brush);
        dc.Ellipse(&lpDrawItemStruct->itemRect);
        dc.RestoreDC(-1); dc.Detach();
    }
Insomma, si disegna come sempre con i device context ed ammennicoli
vari, come spero sia chiaro.
Puo` darsi che la documentazione che hai visto relativamente ad OnDraw
si riferisse specificamente a un "OLE Control" (o "controllo Active/X" che
dir si voglia), visto che l'implementazione MFC di questi controlli usa
appunto una funzione membro cosi` denominata.  Non mi e` chiaro se
tu abbia bisogno di fare controlli Active/X, ma se cosi` e` suggerisco
caldamente di lasciar perdere MFC e usare invece il framework ATL, che
pure e` supportato da Visual C++...
Alex

che contiene tutti gli elementi necessari per il disegno stesso.
Non c'entra con il problema in questione, ma c'entra con ownerdraw.
Giusto oggi ho perso quattro ore a risolvere questo problema: ho una matrice
di 180 bottoni (di tipo checkbox), e devo cambiargli i colori perche' il
committente dice che "non si vede bene".
Sul petzold ho letto di WM_CTLCOLOR, e in particolare che non e' possibile
utilizzare questo msg per i bottoni (perche' si deve dichiararli
BS_OWNERDRAW, ma a quel punto...).
Quindi ho dovuto usare BS_OWNERDRAW. Ma non funzionava mai. Su MSDN ho
scoperto che BS_OWNERDRAW non puo' essere usato in contemporanea a
BS_AUTOCHECKBOX (ad esempio, ma anche altri).
Quindi quando metto BS_OWNERDRAW devo avere dei bottoni semplici, e ho
dovuto gestire "a mano" tutte le funzioni di scambio tra bottoni e dati
(tipo DDX, per capirci) intercettando il click sui bottoni ecc. ecc.
Domanda: non c'e' un modo piu' elegante? O mettendo BS_OWNERDRAW devo poi (a
meno di button "semplici") gestire per forza tutto a mano, compresa la
comunicazione tra stato dei bottoni e dati?
Grazie,
Marco