2014-01-05 97 views
0

在我的Delphi應用程序中,我需要使用GDI和GDI +繪製多行文本。 我有這些項目:使用GDI和GDI繪製旋轉多行文本+

  1. 要畫的文本;
  2. 旋轉角度(文字可能會旋轉);
  3. 最大寬度(想象包含文本的矩形,我對矩形寬度有限制,但對於矩形高度沒有限制);
  4. 字體名稱和文字高度;

有沒有一種簡單的方法可以用GDI和GDI +繪製這個文本? 我找不到關於它的GDI和GDI +函​​數。

+2

我相信[這篇文章](http://stackoverflow.com/a/10633410/800214)會讓你開始... – whosrdaddy

回答

5

tl; dr

使用graphics32和GR32_Text。


對於GDI,最簡單的方法是使用字體的擒縱機構和定向性。例如:

procedure TForm1.PaintBox1Paint(Sender: TObject); 
const 
    Text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do ' 
    + 'eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ' 
    + 'ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ' 
    + 'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit ' 
    + 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur ' 
    + 'sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt ' 
    + 'mollit anim id est laborum.'; 
var 
    angle: Integer; 
    Canvas: TCanvas; 
    lf: LOGFONT; 
    R: TRect; 
begin 
    Canvas := PaintBox1.Canvas; 

    Canvas.Brush.Style := bsClear; // Set the brush style to transparent. 
    lf := Default(LOGFONT); 
    lf.lfHeight := 20; 
    lf.lfCharSet := DEFAULT_CHARSET; 
    lf.lfFaceName := 'Times New Roman'; 

    angle := 15; 
    lf.lfEscapement := 10*angle;//lfEscapement measured in 1/10th of degree 
    lf.lfOrientation := lf.lfEscapement; 
    Canvas.Font.Handle := CreateFontIndirect(lf); 
    R := PaintBox1.ClientRect; 
    inc(R.Top, 200); 
    DrawText(Canvas.Handle, Text, -1, R, DT_NOCLIP or DT_WORDBREAK); 
end; 

產生相當奇怪的佈局:

enter image description here

使用SetWorldTransform給出了不同的佈局,但質量仍然較差:

procedure TForm1.PaintBox1Paint(Sender: TObject); 
const 
    Text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do ' 
    + 'eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ' 
    + 'ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ' 
    + 'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit ' 
    + 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur ' 
    + 'sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt ' 
    + 'mollit anim id est laborum.'; 
var 
    angle: Integer; 
    Transform: TXForm; 
    Canvas: TCanvas; 
    lf: LOGFONT; 
    R: TRect; 
begin 
    Canvas := PaintBox1.Canvas; 

    angle := 15; 
    Transform := Default(TXForm); 
    SinCos(DegToRad(-angle), Transform.eM12, Transform.eM11); 
    Transform.eM22 := Transform.eM11; 
    Transform.eM21 := -Transform.eM12; 

    SetGraphicsMode(Canvas.Handle, GM_ADVANCED); 
    SetWorldTransform(Canvas.Handle, Transform); 

    Canvas.Brush.Style := bsClear; // Set the brush style to transparent. 
    lf := Default(LOGFONT); 
    lf.lfHeight := 20; 
    lf.lfCharSet := DEFAULT_CHARSET; 
    lf.lfFaceName := 'Times New Roman'; 
    Canvas.Font.Handle := CreateFontIndirect(lf); 
    R := PaintBox1.ClientRect; 
    inc(R.Top, 200); 
    inc(R.Left, Round(200*Transform.eM12)); 
    DrawText(Canvas.Handle, Text, -1, R, DT_NOCLIP or DT_WORDBREAK); 
end; 

enter image description here

坦率地說,我認爲你不會使用這兩種方法獲得好的結果。如果我是你,我會用一個好的圖書館,如與安格斯約翰遜的GR32_Text graphics32:

enter image description here


對於GDI +,結果是大致相同的GDI。示例代碼將是:

uses 
    GDIPAPI, GDIPOBJ; 

.... 

{$TYPEDADDRESS ON} 
procedure TForm1.PaintBox1Paint(Sender: TObject); 
const 
    Text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do ' 
    + 'eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ' 
    + 'ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ' 
    + 'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit ' 
    + 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur ' 
    + 'sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt ' 
    + 'mollit anim id est laborum.'; 
var 
    Graphics: TGPGraphics; 
    Font: TGPFont; 
    Brush: TGPBrush; 
    lf: LOGFONT; 
begin 
    Graphics := TGPGraphics.Create(PaintBox1.Canvas.Handle); 
    try 
    Graphics.SetTextRenderingHint(TextRenderingHintSystemDefault); 

    lf := Default(LOGFONT); 
    lf.lfHeight := 20; 
    lf.lfCharSet := DEFAULT_CHARSET; 
    lf.lfFaceName := 'Times New Roman'; 

    Font := TGPFont.Create(PaintBox1.Canvas.Handle, @lf); 
    try 
     Brush := TGPSolidBrush.Create(MakeColor(0, 0, 0)); 
     try 
     Graphics.RotateTransform(-15); 
     Graphics.DrawString(
      Text, 
      -1, 
      Font, 
      MakeRect(0.0, 150.0, 450.0, 600.0), 
      nil, 
      Brush 
     ); 
     finally 
     Brush.Free; 
     end; 
    finally 
     Font.Free; 
    end; 
    finally 
    Graphics.Free; 
    end; 
end; 

和輸出:

enter image description here

還是蠻蹩腳看在我看來。所以爲了獲得最好的質量,我會推薦使用GR32_Text的graphics32。

+0

...或反穀物幾何庫... – TLama

2

基礎知識似乎很簡單:

procedure TForm2.FormPaint(Sender: TObject); 
const 
    S = 'Multiline sample text with 50 degrees rotation'; 
    H = 20; 
    A = -50; 
var 
    R: TRect; 
    NewFont: HFONT; 
    OldFont: HFONT; 
    TextHeight: Integer; 
begin 
    R := ClientRect; 
    InflateRect(R, -20, -20); 
    NewFont := CreateFont(-H, 0, A * 10, A * 10, FW_NORMAL, 0, 0, 0, 
    DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 
    DEFAULT_PITCH, 'Tahoma'); 
    try 
    OldFont := SelectObject(Canvas.Handle, NewFont); 
    DrawText(Canvas.Handle, S, -1, R, DT_LEFT or DT_BOTTOM or 
     DT_WORDBREAK or DT_NOCLIP); 
    finally 
    DeleteObject(SelectObject(Canvas.Handle, OldFont)); 
    end; 
end; 

但它不是爲多行文本:

Screenshot

你需要做的是不要使用在字體的水平旋轉什麼,但在畫布級,與SetWorldTransform

+0

...將工作稍後再舉一個例子。 – NGLN