3

i would like to change to gray color of the Texthint of my TEdits.

I allready found this https://stackoverflow.com/a/31550017/1862576 and tried to change to color via SendMessage like this

procedure TEdit.DoSetTextHint(const Value: string);
var
  Font: TFont;
begin
  if CheckWin32Version(5, 1) and StyleServices.Enabled and HandleAllocated then
  begin
    Font := TFont.Create;
    try
      Font.Assign(self.Font);
      Font.Color := clGreen;
      Font.Size := 20;

      SendTextMessage(Handle, EM_SETCUEBANNER, WPARAM(1), Value);
      SendMessage(Handle, WM_SETFONT, Integer(Font.Handle), Integer(True));
    finally
//      Font.Free;
    end;
  end;    
end;

It changes the size of the font but not the color. Thanks for your help.

Community
  • 1
  • 1
Philipp H.
  • 552
  • 1
  • 3
  • 19
  • The problem is that with your code you are changing color for TEdit text and not HintText. Now I'm not even sure if VCL exposes TextHint color or if it is perhaps hardcoded. – SilverWarior Oct 12 '15 at 17:26
  • There is no cue banner color functionality exposed by the underlying Win32 API, so it not possible to apply custom colors to the cue banner text. – Remy Lebeau Oct 12 '15 at 21:02

2 Answers2

4

The cue banner is a feature built in to the underlying Win32 EDIT control that TEdit wraps. It is not managed by the VCL at all. There is no Win32 API exposed to manage the coloring of the cue banner text. If you want custom coloring, you will have to stop using the native cue banner functionality and custom-draw the edit control manually by handling its WM_ERASEBKGND and/or WM_PAINT messages directly (see How do i custom draw of TEdit control text?). Otherwise, you will have to find a third-party Edit control that supports custom coloring. Or use TRichEdit instead of TEdit so you can set text colors as needed.

Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
4

Definition:

Type
    HitColor = class helper  for tEdit
      private
        procedure SetTextHintColor(const Value: TColor);
        function GetTextHintColor: TColor;
        procedure fixWndProc(var Message: TMessage);
    published
       property TextHintColor : TColor  read GetTextHintColor write SetTextHintColor;
     end;

Implementation:

procedure HitColor.fixWndProc(var Message: TMessage);
var
  dc : HDC ;
  r : TRect ;
  OldFont: HFONT;
  OldTextColor: TColorRef;
  Handled : boolean;
begin
     Handled := false;
     if   (Message.Msg = WM_PAINT)  and (Text  = '') and not Focused then
                  begin

                    self.WndProc(Message);
                    self.Perform(EM_GETRECT, 0, LPARAM(@R));
                    dc := GetDC(handle);
                   try
                      OldFont := SelectObject(dc,  Font.Handle );
                      OldTextColor := SetTextColor(DC,  ColorToRGB(GetTextHintColor));

                      FillRect(dc,r,0);
                      DrawText(DC, PChar(TextHint), Length(TextHint), R, DT_LEFT or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX);
                    finally
                       SetTextColor(DC, OldTextColor);
                       SelectObject(DC, OldFont);
                       ReleaseDC(handle,dc);
                    end;
                  Handled := true;
                end;




    if not Handled then WndProc(Message);

end;

function HitColor.GetTextHintColor: TColor;
begin
  result := tag;
end;

procedure HitColor.SetTextHintColor(const Value: TColor);
begin
  tag :=  Value;
  WindowProc := fixWndProc ;
end;

Usage:

edit1.TextHintColor := clred;
Egor
  • 41
  • 3
  • This answer complements well that of @Remy Lebeau, although I had to change it to work for me: I replaced the line `FillRect(dc,r,0);` by `SetBKColor(DC,ColorToRGB(Color));`. Also, the use of `Tag` to store the property value may not be compatible with your existing code (my case, I used a global private variable instead). – Marcelo Bergweiler Jun 04 '21 at 15:42