2011-08-10 36 views
7

Trong Delphi tôi muốn vẽ văn bản bên trong một TRect. Tôi hy vọng cho các chức năng sau:Delphi - Vẽ văn bản nhiều dòng ở chính giữa của một rect

  1. Vẽ văn bản làm trung tâm theo chiều dọc trong TRect
  2. Vẽ văn bản làm trung tâm theo chiều ngang trong TRect
  3. Nếu có không gian cho hơn 1 dòng văn bản (sử dụng TRect của chiều cao), vẽ văn bản nhiều dòng
  4. Nếu văn bản không vừa trong TRect (trên một hoặc nhiều dòng) thì hãy thêm dấu chấm lửng vào văn bản.

Tôi có thể thấy hàm Windows.DrawText() gần như bao gồm chức năng này, tuy nhiên khi viết văn bản, đa dòng và theo chiều dọc được loại trừ lẫn nhau.

Tôi đã tự hỏi liệu chức năng này có được tích hợp trong các cửa sổ (2000+) không? Nếu không có cách nào để làm điều này mà không cần viết chức năng của riêng tôi?

+2

Bạn không thể sử dụng TLabel? Tôi nghĩ rằng nó có tất cả các chức năng cần thiết. –

+1

Có thể nó có, nhưng tôi không muốn sử dụng một nhãn, tôi có một bức vẽ để vẽ. – Simon

Trả lời

16

Xin lỗi, đây là sự kết hợp của tất cả câu trả lời và nhận xét trước đó. Nhưng có vẻ như OP cần hỗ trợ nhiều hơn.

function DrawTextCentered(Canvas: TCanvas; const R: TRect; S: String): Integer; 
var 
    DrawRect: TRect; 
    DrawFlags: Cardinal; 
    DrawParams: TDrawTextParams; 
begin 
    DrawRect := R; 
    DrawFlags := DT_END_ELLIPSIS or DT_NOPREFIX or DT_WORDBREAK or 
    DT_EDITCONTROL or DT_CENTER; 
    DrawText(Canvas.Handle, PChar(S), -1, DrawRect, DrawFlags or DT_CALCRECT); 
    DrawRect.Right := R.Right; 
    if DrawRect.Bottom < R.Bottom then 
    OffsetRect(DrawRect, 0, (R.Bottom - DrawRect.Bottom) div 2) 
    else 
    DrawRect.Bottom := R.Bottom; 
    ZeroMemory(@DrawParams, SizeOf(DrawParams)); 
    DrawParams.cbSize := SizeOf(DrawParams); 
    DrawTextEx(Canvas.Handle, PChar(S), -1, DrawRect, DrawFlags, @DrawParams); 
    Result := DrawParams.uiLengthDrawn; 
end; 

procedure TForm1.FormPaint(Sender: TObject); 
const 
    S = 'This is a very long text as test case for my paint routine.'; 
var 
    R: TRect; 
begin 
    SetRect(R, 100, 100, 200, 140); 
    Canvas.Rectangle(R); 
    InflateRect(R, -1, -1); 
    Caption := Format('%d characters drawn', [DrawTextCentered(Canvas, R, S)]); 
end; 
+0

Tôi không thể thấy sự khác biệt giữa deamon_x và phiên bản này nhưng công trình này !!!!Cảm ơn :) – Simon

+0

Dòng này là chìa khóa: DT_END_ELLIPSIS hoặc DT_NOPREFIX hoặc DT_WORDBREAK hoặc DT_EDITCONTROL hoặc DT_CENTER; – Simon

+2

tôi biết hóa ra là một cái gì đó đơn giản, nhưng bất kỳ sự kết hợp khác của những lá cờ không làm việc! Woul chia các điểm nếu tôi có thể :) – Simon

5

Đo văn bản trước tiên bằng cách sử dụng DT_CALCRECT. Vượt qua DT_WORDBREAK để chỉ định gói từ được bật. Điều này sẽ cho phép bạn tìm chiều cao yêu cầu cho văn bản của bạn. Sau đó, bạn có thể, trong mã của bạn, tính toán bù đắp theo chiều dọc cung cấp cho bạn văn bản được căn giữa theo chiều dọc và vẽ đến độ lệch đó.

+0

Tôi đã thử phương pháp này, nhưng có vẻ vì lý do nào đó mà DT_WORD_ELLIPSIS bị bỏ qua khi DT_WORDBREAK được chỉ định. Thói quen này hiện không vẽ văn bản bên ngoài của rect (và không hiển thị '...') – Simon

+0

Có cách nào tôi có thể nhận được chính xác mà văn bản (hoặc chiều dài) đã được rút ra? – Simon

+0

@Simon Với 'DT_WORDBREAK' tất cả văn bản được vẽ. Bạn không nhìn thấy nó có lẽ là do cắt. –

Các vấn đề liên quan