Newsgroup: it.comp.lang.c++
Titolo: Dove sta l'errore?

Salve a tutti,
dopo varie richieste, ho saputo che per cambiare il colore di un bottone
bisogna intercettare il messaggio WM_CTLCOLOR del dialog che lo contiene. Io
ho fatto così, ma il seguente codice non cambia assolutamente nulla a video
(in teoria, dovrebbe mettere scritte nere su sfondo nero, ovviamente è solo
per un esempio...).
Qualcuno mi può dire dov'è l'errore?
*** BEGIN CODICE ***
HBRUSH CRadiomaticDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd->GetDlgCtrlID()==IDC_BTNQUIT)
{
  hbr=::CreateSolidBrush(0x000000);
  pDC->SetTextColor(0x000000);
  pDC->SetBkColor(0x000000);
};
// TODO: Return a different brush if the default is not desired
return hbr;
}
*** END CODICE ***
Grazie mille in anticipo :-)
Saluti,
Marco Zanon (
m.z...@usa.net
)
http://www.geocities.com/SiliconValley/Peaks/6455
(Zamorano fan page, free MIDI mailing list, Music db...)



bisogna intercettare il messaggio WM_CTLCOLOR del dialog che lo contiene. 
Hmmm... gia`, ma, in effetti, provando il tuo codice, vediamo
che non ha effetto sui soli bottoni _in stile pushbutton_ (su
quelli in stile radiobutton, ecc, funziona, cosi` pure come su
scritte [cioe` static], ecc ecc).  Temo che il problema sia
legato a quella parte della window procedure della classe
Button che si occupa di dare un "look 3D" al pushbutton;
che essa, cioe`, ignori i colori settati dalla finestra-padre
e recuperi comunque invece il "settaggio di sistema" per i
propri colori (compresi i toni "scuri" e "chiari" che usa per
darsi un look 3D).
Questo sembra legato a una oscura nota nella documentazione
di WM_CTLCOLORBUTTON, dove spiega in dettaglio come
si usano i vari colori per i vari tipi di bottoni (radio, check, ecc
ecc): "The text color of a push button applies only to its focus 
rectangle; it does not affect the color of the text."  Penso che
questo significhi che, per un pushbutton, puoi cambiare solo
le caratteristiche cromatiche del "focus rectangle", mentre le
altre non sono controllate dal messaggio stesso.
Altri oscuri appunti in merito si trovano in:
Platform SDK
    User Interface Services
        Windows Base Services
            Windows 95 Features
                About Windows 95
                    Version Differences
                        Button Differences
e anche li` ci sono tangenziali riferimenti a "(except push
buttons)" ed elenchi come "check boxes, radio buttons, and 
group buttons" (ancora una volta, ogni sottotipo di bottone
eccetto i pushbuttons).
Insomma, pare proprio che, per i pushbutton, l'unica
sia gestirseli interamente, come owner-drawn, se si
vuole controllare i loro colori.  Dunque, segna nel
resource editor "owner drawn" fra le proprieta` di
stile del bottone, col class wizard aggiungi alla tua
classe-dialogo la gestione di WM_DRAWITEM, e
fai ad esempio qualcosa del tipo:
void CVasDlg::OnDrawItem(int nIDCtl, 
    LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
    CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
    if(nIDCtl == IDC_BUTTON2) {
        COLORREF base = RGB(200,100,80);
        COLORREF dark = RGB(90,40,30);
        COLORREF lite = RGB(230,130,110);
        COLORREF text = RGB(40,40,130);
        CDC* pdc = CDC::FromHandle(lpDrawItemStruct->hDC);
        dc->SaveDC();
        CWnd* pcw = CWnd::FromHandle(lpDrawItemStruct->hwndItem);
        CRect rec;
        pcw->GetClientRect(&rec);
        pdc->FillSolidRect(&rec, base);
        if(lpDrawItemStruct->itemState & ODS_SELECTED)
            pdc->Draw3dRect(&rec, dark, lite);
        else
            pdc->Draw3dRect(&rec, lite, dark);
        pdc->SetTextColor(text);
        pdc->SetBkColor(base);
        pdc->DrawText("Ciao!", 5, &rec, 
            DT_SINGLELINE|DT_CENTER|DT_VCENTER);
        pdc->RestoreDC(-1);
    }
}
od altre finezze di tua scelta per disegnare esattamente
quello che desideri, simulare il discendere-e-risalire del
pushbutton quando viene cliccato (bit ODS_SELECTED
a 1 quando dev'essere "giu`"), eccetera.
Puoi fare esattamente le stesse cose in una tua classe
derivata da CButton (praticamente un "subclassing" del
bottone in oggetto), ma farlo del dialogo proprietario del
bottone puo` spesso essere piu` pratico.
Alex

Sempre a proposito di questo thread, suggerisco
anche di consultare in merito "codeguru", un sito
che e` un'intera collezione di preziose risorse per
MFC (e altri ambienti, ma soprattutto MFC).
In particolare,
http://www.codeguru.com/buttonctrl/color_button.shtml
offre una piccola classe che facilita il compito di
fare pushbutton colorati.
Alex

 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