2010-03-01 15 views
7

Sì, questo è ancora una volta questa domanda:Come è possibile modificare il colore del carattere di un controllo abilitato per il tema?

Come posso cambiare il colore del carattere di un TCheckBox (o qualsiasi trattati di controllo) con Delphi7-> Delphi2007 su temi un'applicazione abilitata?

Dopo aver letto molto su internet e su questo sito, ho trovato 4 tipi di risposta:

  1. e Most populare (anche da QC): Non è possibile, è progettato come quello da Microsoft.
  2. Creare un componente che consente di disegnarlo come si desidera.
  3. Acquista un set di componenti costosi che si disegna come vuoi.
  4. Non utilizzare temi.

OK, ma sono ancora insoddisfatto di quello.

Fornire un feedback colorato all'utente per lo stato di una proprietà/dati che ha su un modulo, mi sembra legittimo.

Quindi ho appena installato l'edizione MSVC# 2008 Express e quale sorpresa possono cambiare il colore del carattere (proprietà ForeColor della casella di controllo) E allora?

Non sembra essere un "è progettato in questo modo, da Microsoft". quindi ora la domanda di nuovo:

Come posso cambiare il colore del carattere di un TCheckBox (o qualsiasi controllo gestito) con Delphi 7 tramite Delphi 2007 su un'applicazione abilitata per il tema?

+0

Cosa ti fa pensare gli sviluppatori di Visual Studio non utilizzavano semplicemente l'opzione 2? –

+0

Beh, non dovevo, mentre cercavo di riprodurre "è progettato in questo modo, da Microsoft". su C#. Ho impostato ForeColor su Rosso e ottengo una didascalia rossa per la mia casella di controllo. –

risposta

0

Opzione 5. Usa il controllo come opzione di base e sostituisci tutti i messaggi di disegno nel controllo (sì, puoi chiamarlo componente ma il controllo è il nome dei componenti visibili, quindi dovresti usarlo). Basta prendere il WM_PAINT, possibilmente il WM_NCPAINT puoi disegnare il controllo nel tuo stile. Almeno puoi riutilizzare l'intera funzionalità dal controllo. Finché non cambierai il lay-out, solo i colori non ti serviranno per cambiare i cappuccini. mosse ecc. ecc.

Nota: ho l'esperienza con l'override di TCustomEdit per consentire tutti i tipi di colori, testo di sfondo, pulsanti aggiuntivi ecc. Ci è voluto del tempo per farlo bene e leggere tutti i documenti da MSDn e KB per assicurarsi che il controllo abbia fatto ciò che volevo che facesse.

+0

Capisco che non come opzione 5, ma come opzione 2a e mia opzione 2 come opzione 2b; ^)! Ma perché C# non ha bisogno di sovrascrivere il metodo wm_paint per cambiare il colore del colore del carattere di un componente Checkbox? –

+0

@ Edouard. Quello che c'è in un nome .. sul C# non ne ha bisogno: C# ha il proprio livello di controllo (Microsoft inventa uno nuovo per l'ambiente .NET ogni tanti anni), Delphi usa gli stessi controlli che esistono da Windows 95. Di qui molto più stabilità ma a volte si paga perché qualcosa di semplice diventa più difficile; GDI è vecchio ma penso che in 10 anni GDi è ancora in circolazione e cosa dovresti fare con la tua app WinForms? Pensaci! –

+0

So che il GDI è piuttosto vecchio, ho iniziato a lavorarci, quando ho fatto il mio primo passo su Borland Object pascal su "windows 2" qualcosa come il 1988. Quello che stai dicendo è: C# può farlo, perché sta usando un gruppo di controlli completamente diverso da quello utilizzato da Delphi mentre i temi sono abilitati? Dato che la cosa del tema è responsabile del disegno delle nuove cose, suppongo che Delphi stia usando gli stessi componenti (ort almeno una libreria) di C#. –

2

Oh, ma è possibile!

Il posto giusto questo prima la dichiarazione del modulo:

TCheckBox = class(StdCtrls.TCheckBox) 
public 
    procedure CNCtlColorStatic(var Message: TWMCtlColorStatic); message CN_CTLCOLORSTATIC; 
end; 

Questa nuova dichiarazione di TCheckBox è ora utilizzato in fase di esecuzione come il tipo in streaming dal DFM della form. Ora l'attuazione del messaggio come questo:

procedure TCheckBox.CNCtlColorStatic(var Message: TWMCtlColorStatic); 
begin 
    SetTextColor(Message.ChildDC, ColorToRGB(clRed)); // or RGB(255,0,0)); 
    SetBkMode(Message.ChildDC, TRANSPARENT); 
    Message.Result := GetStockObject(NULL_BRUSH); 
end; 

Questo intrappola il messaggio WM_CTLCOLORSTATIC e cambia il colore del testo rosso. Questo funziona in modalità non a tema per me (utilizzando WinXP classic), ma non in modalità a tema.

È necessario sapere che per consentire ai controlli a tema di inviare questo messaggio, il controllo deve fornire il flag DTPB_USECTLCOLORSTATIC alle API di disegno del tema. Purtroppo, questo non è un comportamento predefinito, e non so nemmeno come farlo. Guarda anche la domanda this.

1

Ecco come ho risolto questo nella mia app:

  1. Rimuovere la didascalia della casella di controllo e renderlo più piccolo - grande quanto basta per mostrare la casella di controllo reale, senza la didascalia.
  2. Mettere un TLabel accanto alla casella di controllo per agire come didascalia.
  3. Nell'evento OnClick dell'etichetta, attivare lo stato della casella di controllo.
  4. Se l'etichetta ha un acceleratore tastiera Alt + lettera, fare in modo che il modulo gestisca il messaggio CM_DIALOGCHAR. Copia il gestore dei messaggi dal codice sorgente di TLabel e aggiungi una linea per attivare lo stato della casella di controllo.

Non è una casella di controllo vero e proprio, ed è un po 'più lavoro di quanto mi piacerebbe, ma funziona abbastanza bene nella mia app (che ha solo una casella di controllo che ha bisogno di questo trattamento).

4

Questo ha bisogno di qualche ritocco per essere una soluzione perfetta, ma ha funzionato per me:

Aggiungi 2 metodo per il componente casella di controllo

FOriginalCaption: string; 
    _MySetCap: Boolean; 
    procedure WMPaint(var msg: TWMPaint); message WM_PAINT; 
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; 

e realizzare in questo modo:

procedure TMyCheckbox.CMTextChanged(var Message: TMessage); 
begin 
    inherited; 
    if _MySetCap then Exit; 
    FOriginalCaption := Caption; 
end; 

procedure TMyCheckbox.WMPaint(var msg: TWMPaint); 
var 
    BtnWidth: Integer; 
    canv: TControlCanvas; 
begin 
    BtnWidth := GetSystemMetrics(SM_CXMENUCHECK); 

    _MySetCap := True; 
    if not (csDesigning in ComponentState) then 
    Caption := ''; 
    _MySetCap := False; 
    inherited; 
    canv := TControlCanvas.Create; 
    try 
    canv.Control := Self; 
    canv.Font := Font; 
    SetBkMode(canv.Handle, Ord(TRANSPARENT)); 
    canv.TextOut(BtnWidth + 1, 2, FOriginalCaption); 
    finally 
    canv.Free; 
    end; 
end; 
+0

Credo che questo dovrebbe essere contrassegnato come risposta, bel lavoro! –

Problemi correlati