完整範例 - Fontlist (5/10)
在上篇中我們雖然成功地繪畫出字型的樣本,但是有部分字型顯示得並不正常,例如下圖,SimHei(簡體中文系統所用的黑體)出現了一些怪字,Shruti顯示的字型也成了亂碼。究其原因,是因為我們所寫的是Ansi的程序,而不是Unicode的程序。Unicode的程序通用性十分優越,但是一直到Windows 2000才得到直接的支持,加上代碼較复雜,所以目前大部分程序仍然是Ansi的。Ansi程序用到的所有文字,顯示時都要考慮Charset,在delphi中,即是tFont.Charset。
Delphi中所有的字型,Charset都設為DEFAULT_CHARSET,即系統內定的值(設定方法:控制台→國家及語言→進階→非Unicode程序語言),將之設為CHINESEBIG5_CHARSET便是繁體中文所用的大五碼(Big5),設為GB2312_CHARSET便是簡體系統所用的國家標準碼(GB/GBK)。
每一種字型,都有它支持的編碼,例如SimHei支持的是GB2312_CHARSET,將之以DEFAULT_CHARSET或CHINESEBIG5_CHARSET顯示便得到亂碼。因此,在繪畫時我們必須針對每一字型使用正確的Charset,為了方便,我們將之儲放在tFontData中:
type tFontData = record Filename, Fontname: string;Charset: integer;end;
然後在GetSystemFonts時求得Charset:
procedure TForm1.GetSystemFonts; var i, l: integer;OldFont: tFont; tm: tagTEXTMETRICA;begin SetLength(fSystemFonts,Screen.Fonts.Count); l:=0;OldFont:=tFont.Create; OldFont.Assign(Canvas.Font);try for i:=0 to Screen.Fonts.Count-1 do if Screen.Fonts[i][1]<>'@' then begin fSystemFonts[l].Fontname:=Screen.Fonts[i]; fSystemFonts[l].Filename:='';Canvas.Font.Name:=fSystemFonts[l].Fontname; GetTextMetrics(Canvas.Handle, tm); fSystemFonts[l].Charset:=tm.tmCharSet;inc(l); end; Finally SetLength(fSystemFonts,l);Canvas.Font.Assign(OldFont); OldFont.Free;end; end;
上面代碼中的GetTextMetrics,是用來求得Charset的Win API,它需要一個TCanvas的Handle,我們使用了Form的Canvas.Font。為了避免Form的外貌受到影響,我們保存了舊的字型設定,並在最後復原。
DrawCell改變得並不多,只是在設定字型的時把Charset也改變,然後印出文字時使用相應內碼的文字串。
procedure TForm1.DrawCell(Canvas: tCanvas; Rect: tRect; Row: integer; Selected: boolean); //Gridwidth changed to be 0 var s: string; begin with Canvas do begin if Selected then Brush.Color:=FontBgColorHl else if Row mod 2=0 then Brush.Color:=FontBgColor0 else Brush.Color:=FontBgColor1; FillRect(rect); if Row>=Length(fFonts^) then exit; if Selected then Font.Color:=FontColorHl else if Row mod 2=0 then Font.Color:=FontColor0 else Font.Color:=FontColor1; SetBkMode(Handle, TRANSPARENT); Font.Name:=fFonts^[Row].Fontname;Font.Charset:=fFonts^[Row].Charset; Font.Height:=Rect.Bottom-Rect.Top-4; case Font.Charset of CHINESEBIG5_CHARSET: s:='詩中天地闊。'; GB2312_CHARSET: s:='坅笢毞華屨﹝'; SHIFTJIS_CHARSET: s:=#$90#$9f''#$95#$97''#$8d#$81; HANGEUL_CHARSET: s:='憡臐夥塋擎'; else s:='A lazy fox.'; end;Textout(Rect.Left+2, Rect.Top+2, s+fFonts^[Row].Fontname); end; end;
內碼和Charset的對應是十分复雜問題,但是只是要印出幾行定的樣本文字並不難,我們只是加入了約二十行的代碼而已,看來卻好多了。
沒有留言:
發佈留言