首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi Canvas.TextOut 文字輸出實戰:逐字繪製古詩與度量應用

     編輯:Delphi

TextOut、TextWidth、TextHeight 結合實現逐字精確排版

Canvas.TextOut 是最基礎的文字輸出函數,配合 TextWidth/TextHeight 度量,能實現字元級的精確定位控制。本文通過逐字繪製古詩範例,展示如何計算每個字元的寬高並實現等寬/非等寬字體的精確排版。

核心函數簽名


procedure TextOut(X, Y: Integer; const Text: string);
function TextWidth(const Text: string): Integer;
function TextHeight(const Text: string): Integer;

完整範例:逐字繪製古詩 (支援 WideString)


unit Unit1;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
const
  Arr: array[0..3] of WideString = (
    '白日依山盡',
    '黃河入海流',
    '欲窮千裡目',
    '更上一層樓'
  );
  A = 20;  // 橫向間距
  B = 20;  // 縱向間距
var
  S: string;
  X, Y: Integer;
  I, J: Integer;
begin
  X := 20;
  Y := 20;
  for I := 0 to Length(Arr) - 1 do
  begin
    // 注意:WideString 索引從 1 開始,Length 返回字元數
    for J := 1 to Length(Arr[I]) do
    begin
      S := Arr[I][J];                    // 取單字元
      Canvas.TextOut(X, Y, S);           // 繪製
      X := X + Canvas.TextWidth(S) + A;  // 移動到下一字元位置
    end;
    X := 20;                              // 換行回行首
    Y := Y + Canvas.TextHeight(S) + B;   // 移動到下一行
  end;
end;

end.

關鍵技術細節解析

WideString 索引特性

  • WideString 索引從 1 開始 (同 string)
  • Length(WideString) 返回 字元數 (非位元組數)
  • Arr[I][J] 返回 WideChar,隱式轉為 string 給 TextOut

度量函數行為

進階應用:非等寬字體逐字定位


procedure DrawTextCharByChar(ACanvas: TCanvas; const Text: string; X, Y: Integer; CharSpacing: Integer);
var
  I: Integer;
  Ch: string;
  CharWidth: Integer;
begin
  for I := 1 to Length(Text) do
  begin
    Ch := Text[I];
    CharWidth := ACanvas.TextWidth(Ch);
    ACanvas.TextOut(X, Y, Ch);
    X := X + CharWidth + CharSpacing;
  end;
end;

效能優化建議

  • 大量文字:避免逐字 TextOut,改用 TextRect + tfWordBreak 或 DrawTextEx
  • 重複度量:快取 TextWidth/TextHeight 結果,尤其等寬字體
  • 批次繪製:組裝完整行字串一次 TextOut,減少 GDI 呼叫

常見陷阱

  1. TextHeight 固定值:同 Font 下所有字串高度相同 (含下延部預留),逐字 Y 定位可用固定行高
  2. WideString vs string 索引:兩者均從 1 起,但 AnsiString 在 D2007 可能不同
  3. Canvas 狀態殘留:繪製前確認 Font/Brush/Pen 狀態
  4. 座標系統:TextOut(X,Y) 以視窗客戶區左上角為原點,Y 向下遞增

現代替代:TextRect 格式化版


// 同樣效果,更簡潔
Canvas.TextRect(Rect(20,20,ClientWidth,ClientHeight), 
  '白日依山盡'#13#10'黃河入海流'#13#10'欲窮千裡目'#13#10'更上一層樓',
  [tfWordBreak, tfExpandTabs]);

掌握 TextOut 配合度量函數的逐字控制技術,是實現自定義排版引擎、語法高亮編輯器、圖文混排的基礎功力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
函數返回值受 Font 影響典型用途
TextWidth字串像素寬度是水平定位、換行判斷
TextHeight字串像素高度 (含行距)是垂直定位、行高計算
TextExtentTSize(cx, cy)是一次獲取寬高