歡迎光臨 Code²

Code Square, CodeSqaure, Pascal, Javascript

2008年12月17日星期三

完整範例 - 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_CHARSETCHINESEBIG5_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,它需要一個TCanvasHandle,我們使用了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的對應是十分复雜問題,但是只是要印出幾行定的樣本文字並不難,我們只是加入了約二十行的代碼而已,看來卻好多了。

沒有留言:

發佈留言