我想繪製一段TEdit.Text使用Font.Color不同於默認。有沒有例子如何做到這一點?我如何自定義繪製的TEdit控制文本?
我試圖做這樣的事情:
注:這張截圖的圖片是什麼僅僅是一個毛茸茸的草案,但它使我相信有什麼問題可以解決。
我想繪製一段TEdit.Text使用Font.Color不同於默認。有沒有例子如何做到這一點?我如何自定義繪製的TEdit控制文本?
我試圖做這樣的事情:
注:這張截圖的圖片是什麼僅僅是一個毛茸茸的草案,但它使我相信有什麼問題可以解決。
Edit
控件沒有所有者繪製支持,但由子類它和處理WM_PAINT
(許多其他消息中),您可以自定義繪製。這是可行的,但實際上實現100%是一個痛苦的世界。從文檔:Developing Custom Draw Controls in Visual C++:
注意,所有者繪製將大部分控制工作。但是,它不適用於編輯控件;與問候列表控件,它僅適用於報告視圖風格
我也有興趣瞭解兔子洞有多深,所以,
下面是使用一箇中介類代碼示例(還需要落實的選擇,但是當插入符號是自定義繪製工作在控制):
type
TEdit = class(StdCtrls.TEdit)
private
FCanvas: TCanvas;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
protected
procedure WndProc(var Message: TMessage); override;
procedure Paint; virtual;
procedure PaintWindow(DC: HDC); override;
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
...
constructor TEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;
destructor TEdit.Destroy;
begin
FCanvas.Free;
inherited Destroy;
end;
procedure TEdit.Paint;
var
R: TRect;
I: Integer;
S: String;
begin
R := ClientRect;
Inc(R.Left, 1);
Inc(R.Top, 1);
Canvas.Brush.Assign(Self.Brush);
Canvas.Font.Assign(Self.Font);
for I := 1 to Length(Text) do
begin
if Text[I] in ['0'..'9'] then
Canvas.Font.Color := clRed
else
Canvas.Font.Color := clGreen;
S := Text[I];
DrawText(Canvas.Handle, PChar(S), -1, R, DT_LEFT or DT_NOPREFIX or
DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly);
Inc(R.Left,Canvas.TextWidth(S));
end;
end;
procedure TEdit.PaintWindow(DC: HDC);
begin
FCanvas.Lock;
try
FCanvas.Handle := DC;
try
TControlCanvas(FCanvas).UpdateTextFlags;
Paint;
finally
FCanvas.Handle := 0;
end;
finally
FCanvas.Unlock;
end;
end;
procedure TEdit.WMPaint(var Message: TWMPaint);
begin
ControlState := ControlState+[csCustomPaint];
inherited;
ControlState := ControlState-[csCustomPaint];
end;
procedure TEdit.WndProc(var Message: TMessage);
begin
inherited WndProc(Message);
with Message do
case Msg of
CM_MOUSEENTER, CM_MOUSELEAVE, WM_LBUTTONUP, WM_LBUTTONDOWN,
WM_KEYDOWN, WM_KEYUP,
WM_SETFOCUS, WM_KILLFOCUS,
CM_FONTCHANGED, CM_TEXTCHANGED:
begin
Invalidate;
end;
end;
end;
謝謝,這個例子實際上推動我在我的研究,並指出了我無數的細微差別我完全錯過了(例如,csCustomPaint)。 – OnTheFly 2012-03-19 20:37:49
由於您沒有使用控件本身的表面,因此必須考慮所有可能的顯示情況。例如,除了選擇之外,還必須考慮何時應該以不同於第一個字符的字符顯示文本 - 當文本較大以適合控件並且用戶已將其滾動通過末尾時。實際上,你要做的是開發你的編輯控件,而不是使用一個! – 2012-03-19 21:16:36
@SertacAkyuz我剛剛使用了kobik提供的代碼,只改變了文本的繪製方式,並且您提到的所有情況都得到了正確處理。當然,這是5年後,在不同的操作系統和Delphi版本中,但作爲參考,上面的代碼對我所要做的事情非常有用。 – 2017-08-23 20:14:13
號標準TEDIT不具有自定義繪製或文本有多種顏色的支持。作爲替代,你可以使用tRichEdit和WantReturns = False。
一些改進,kobik solusion:
procedure TMyEdit.Paint;
var
R: TRect;
I: Integer;
NewColor : TColor;
NewBackColor : TColor;
procedure DrawEx(S: String);
begin
if ((i-1)>=Self.SelStart) and ((i-1)<=(Self.SelStart+(Self.SelLength-1)))
and (Self.SelLength>0) and (Self.focused)
then begin
Canvas.Font.Color := clWhite;
Canvas.Brush.Color := NewColor;
end else begin
Canvas.Font.Color := NewColor;
Canvas.Brush.Color := NewBackColor;
end;
Canvas.Brush.Style := bsSolid;
DrawText(Canvas.Handle, PChar(S), -1, R, DT_LEFT or DT_NOPREFIX or
DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly);
end;
begin
R := ClientRect;
Inc(R.Left, 1);
Inc(R.Top, 1);
Canvas.Brush.Assign(Self.Brush);
Canvas.Font.Assign(Self.Font);
if Self.Focused then begin
NewBackColor := clYellow;
Canvas.Brush.Color := NewBackColor;
Canvas.Brush.Style := bsSolid;
Canvas.FillRect(ClientRect);
Canvas.DrawFocusRect(ClientRect);
end else NewBackColor := clWhite;
for I:=1 to Length(Text) do begin
if PasswordChar=#0 then begin
if Text[I] in ['0'..'9'] then begin
NewColor := clRed;
DrawEx(Text[I]);
end else begin
NewColor := clGreen;
DrawEx(Text[I]);
end;
Inc(R.Left,Canvas.TextWidth(Text[I]));
end else begin //with passwordchar
NewColor := clBlack;
DrawEx(PasswordChar);
Inc(R.Left,Canvas.TextWidth(PasswordChar));
end;
end;
end;
歡迎你分享你的「解決方案」,所以我們可以討論,並提供飼料中後衛(截圖是不是一個解決方案)。 – kobik 2012-03-19 14:49:46
@ kobik,可能會有一系列簡單的問題致力於解決我偶然發現的特定問題。但是這可能會在稍後發生,目前我沒有被卡住。 – OnTheFly 2012-03-19 15:22:13