2009-05-28 12 views
19

Avevo bisogno di un'etichetta con un font grande su un modulo Delphi e ho notato che le sue curve erano ancora leggermente seghettate. Ho confrontato questo con la stessa dimensione e il carattere in MSWord che era molto più agevole. Dopo la ricerca ho trovato il codice che mi ha permesso di smussare i miei caratteri ma è disordinato e mi chiedevo se ci fosse un modo migliore? Guardando nella sorgente VCL, TFont sembra sposata a NONANTIALIASED_QUALITY che è piuttosto frustrante ...Font smoothing in Delphi

Grazie Bri

procedure TForm1.SetFontSmoothing(AFont: TFont); 
var 
    tagLOGFONT: TLogFont; 
begin 
    GetObject(
    AFont.Handle, 
    SizeOf(TLogFont), 
    @tagLOGFONT); 
    tagLOGFONT.lfQuality := ANTIALIASED_QUALITY; 
    AFont.Handle := CreateFontIndirect(tagLOGFONT); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    I : integer; 
begin 
    For I :=0 to ComponentCount-1 do 
    If Components[I] is TLabel then 
     SetFontSmoothing(TLabel(Components[I]).Font); 
end; 
+3

Quindi questo codice funziona (e vuoi solo pulirlo e trovare un modo semplice) o non è ancora abbastanza fluido o non funziona? – schnaader

+0

Quale parte di questo codice consideri disordinata? –

+0

Sembra inutile che io debba colpire ogni carattere su ogni etichetta quando il VCL lo ha già fatto. Ho cercato qualcosa che potessi escludere o sottoclasse, ma senza fortuna. Immagino che questo sia l'unico modo per ottenere ciò che voglio. Bri –

risposta

29

È possibile ingannare VCL creando la propria classe che eredita da TLabel. Questo è un codice proof-of-concept, testato con Delphi 4, che dovrebbe iniziare.

creare una nuova unità per il proprio TLabel classe:

unit AntiAliasedLabel; 

interface 

uses 
    Windows, Messages, SysUtils, Controls, StdCtrls, Graphics; 

type 
    TLabel = class(StdCtrls.TLabel) 
    private 
    fFontChanged: boolean; 
    public 
    procedure Paint; override; 
    end; 

implementation 

procedure TLabel.Paint; 
var 
    LF: TLogFont; 
begin 
    if not fFontChanged then begin 
    Win32Check(GetObject(Font.Handle, SizeOf(TLogFont), @LF) <> 0); 
    LF.lfQuality := ANTIALIASED_QUALITY; 
    Font.Handle := CreateFontIndirect(LF); 
    fFontChanged := TRUE; 
    end; 
    inherited; 
end; 

end. 

Ora modificare l'unità modulo che contiene l'etichetta, aggiungendo il AntiAliasedLabel unità dopoStdCtrls. Ciò si traduce nella creazione della classe AntiAliasedLabel.TLabel in cui verrà creato normalmente StdCtrls.TLabel.

+0

+1 soluzione molto interessante! – jpfollenius

+4

+1 Woah - Non avevo idea che tu potessi cavartela con trucchi del genere. Grazie per aver aperto gli occhi! – robsoft

+0

Molto, molto, molto, molto, molto, molto, molto .... BELLO! Grazie per questo facile trucco. – Codebeat

3

Il modo più semplice è quello di creare un componente personalizzato in base a TLabel, come ad esempio TSmoothLabel o TAntiAliasedLabel e aggiungi il tuo codice di smoothing. Quindi si utilizza il componente al posto del TLabel standard.

+0

Vero, ma sto caricando un DFM esistente che specifica la classe TLabel, quindi il tuo suggerimento potrebbe funzionare se c'è un modo di ri-registrare TLAbel. Bri –

+1

C'è un modo, ma richiede la sostituzione della voce VMT TLabel.NewInstance con un metodo proprio in fase di esecuzione. Il JCL (libreria di codici JEDI) ha delle funzioni per farlo. –

+3

@Brian: Perché non puoi semplicemente correggere i file DFM e PAS (dall'esterno dell'IDE) per utilizzare la nuova classe? Alternativa: se si utilizza una versione di Delphi che li supporta, è possibile utilizzare un helper di classe per TLabel. (Specificare quale Delphi in futuro.) Non raccomando la route helper di classe se c'è un altro modo, però, perché interesserà qualsiasi TLabel che è nel suo scope. –

7

IMHO, il VCL deve controllare il carattere di default del sistema che livella e applicarlo come predefinito in fase di esecuzione. In caso contrario, almeno dovrebbe essere impostato su un livellamento più ragionevole. Si potrebbe sostenere, in questo caso, che ClearType sarebbe un valore predefinito migliore, considerando che> il 50% dei monitor in questi giorni è LCD (e più del 50% delle macchine utilizza XP o superiore).

Questo è un trucco riconosciuto (e come cita Ken bianco, non l'approccio migliore se non ci sono alternative), ma ho bisogno di un modo per risolvere questo problema a livello globale per le forme che contengono letteralmente centinaia di tipi di componenti 3rd-party (facendo componente eredità irrealistico).

ho cambiato il default qualità dei caratteri nel Graphics.pas, TFont.GetHandle come segue:

// lfQuality: = DEFAULT_QUALITY;

lfQualità: = 5; // (hack) CLEARTYPE_QUALITY, forze ClearType

5

Da:. http://objectmix.com/delphi/725245-tlabel-antialiasing-possibile-3.html

"semplicemente usando un tipo di carattere che supporta la smussatura dei caratteri dovrebbe risolvere questo Delphi usi (o almeno usato per usare) MS Sans Serif come predefinito, che non supporta smoothing (ClearType o altro). Se si imposta il font su Tahoma (migliore per XP) o Segoe UI (migliore per Vista), si otterrà automaticamente in base alle impostazioni di sistema in la tua app Delphi ".

Confermato, funziona magnificamente con Delphi XE e Win7.Occupato cambiando tutti i miei font in questo momento ;-)