Newsgroup: it.comp.lang.c++
Titolo: Ancora sui controlli Dialog

 scritte [cioe` static], ecc ecc).
A me non funziona neanche su questi controlli!
Con VC++ 5.0 ho creato un progetto Dialog-based, intercettando il
messaggio WM_CTLCOLOR con la funzione:
HBRUSH CProvaColorDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
        HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
        // TODO: Change any attributes of the DC here
        TRACE("OnCtlColor %d\n",nCtlColor);
        pDC->SetTextColor(RGB(0,0xFF,0));
        pDC->SetBkColor(RGB(0,0,0xFF));
        CBrush myRedBrush;
        myRedBrush.CreateSolidBrush(RGB(255,0,0));
        return myRedBrush;
        // TODO: Return a different brush if the default is not desired
        return hbr;
}
Sulla dialog ho inserito un paio di static text, un radiobutton, un
check button e un bottone normale (tutti creati col resource editor).
Non avendo specificato nessun ID di risorsa nella OnCtlColor, io mi
aspetterei di vedere colorati tutti questi elementi, cosa che non e'.
Non riesco a modificare il colore di nessuno.
La OnCtlColor viene eseguita diverse volte, e in Debug il TRACE me ne
fornisce conferma.
Ho provato anche ad inserire un oggetto CStatic MyStatic "al volo",
cioe' da codice invece che dal resource editor, inserendo la linea
MyStatic.Create("pippo",SS_BITMAP|SS_SUNKEN|WS_VISIBLE|SS_NOTIFY,CRect(20,20,100,100),this);
nella CProvaColorDlg::OnInitDialog(). La finestra viene disegnata
correttamente ma di colori custom neanche a parlarne.
Ho provato il codice suggerito da Alex ed il bottone colorato funziona
perfettamente.
Altra questione. Su 
http://www.codeguru.com
 ho trovato il seguente
suggerimento per cambiare il colore background ed il text color:
BOOL CMyApp::InitInstance()
{
        ...
        // lets set red background and green text for our dialogs
        SetDialogBkColor(RGB(255,0,0),RGB(0,255,0));
        ...
}
Ho inserito la riga nella InitInstance() della mia classe
CProvaColorApp, ma senza ottenere alcun risultato.
Grazie a tutti quelli che vorranno dare un suggerimento.
Saluti
Lorenzo

Il problema potrebbe risiedere nel fatto che crei un CBrush locale alla tua
funzione e che quindi dovrebbe non essere piu' valido quando il controllo
torna al framework.
Prova ad allocarlo con <new> (naturalmente andrebbe fatto una sola volta
all'inizio del programma per poi liberare la memoria correttamente).
Ciao.
--
Antonio Donatiello

all'inizio del programma per poi liberare la memoria correttamente).
Molto piu` semplicemente, si puo` provare a cambiare
il return da "return myRedBrush;" a
    return myRedBrush.Detach();
La funzione membro "Detach()" (del CBrush, come di tutte le
varie altre classi MFC che hanno lo scopo nella vita di "vestire"
una handle di windows) ritorna la handle _e_ azzera la handle
dell'oggetto MFC, cosi` che il suo distruttore non abbia piu`
effetti su di essa -- insomma, appunto, "distacca" la handle
dal suo "rivestitore".
In questo caso molto semplice, si potrebbe anche fare semplicemente
    return ::CreateSolidBrush(RGB(255,0,0));
evitando completamente l'uso di MFC (che tanto qui non fa
appunto null'altro che "rivestire" l'API e le handle...).
Alex

     return myRedBrush.Detach();
[...]
Occorre scrivere
     return (HBRUSH)myRedBrush.Detach();
cioe' forzare l'handle di ritorno dalla Detach() da HGDIOBJ a HBRUSH,
altrimenti il compilatore torna un errore.
Grazie ancora di nuovo per la disponibilita' e la cortesia.
Saluti
Lorenzo

altrimenti il compilatore torna un errore.
Giusto, in C++ (o in C con #define STRICT) le HANDLE non
si trasformano "automaticamente" l'una nell'altra, bensi` puo`
occorrere un cast come questo (Detach e` un metodo del
generico wrapper degli GDI object, non del solo CBrush,
quindi torna l'handle di un generico GDI object e non quella
di un brush specificamente).
Alex