6

Basically, I want the TextHint of my TEdits to disappear when the first character is entered and not when they receive focus, like the Edits on this Microsoft page: Sign in to your Microsoft account. Can someone please walk me through on how to achieve this?

Thank you in advance.

Danilo Casa
  • 506
  • 1
  • 9
  • 18

2 Answers2

8

The built-in TEdit behavior doesn't allow this, but you can derive a new control from TEdit and override DoSetTextHint. The implementation should be similar to the internal method, but provide a value of 1 for wParam instead of 0.

This is a solution using an interceptor class:

unit EditInterceptor;

uses
  Vcl.StdCtrls, System.SysUtils, Winapi.Messages, Windows;

type
  TEdit = class(Vcl.StdCtrls.TEdit)
  protected
    procedure DoSetTextHint(const Value: string); override;
  end;

implementation

uses
  Vcl.Themes, Winapi.CommCtrl;

procedure TEdit.DoSetTextHint(const Value: string);
begin
  if CheckWin32Version(5, 1) and StyleServices.Enabled and HandleAllocated then
    SendTextMessage(Handle, EM_SETCUEBANNER, WPARAM(1), Value);
end;

end.  

Make sure to place this unit in the interface uses clause after Vcl.StdCtrls.

William
  • 467
  • 1
  • 6
  • 19
Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
4

Based on Uwe Raabe's answer, here is a procedure (for Delphi 2007, should work for newer versions of Delphi as well):

type
  TCueBannerHideEnum = (cbhHideOnFocus, cbhHideOnText);

procedure TEdit_SetCueBanner(_ed: TEdit; const _s: WideString; _WhenToHide: TCueBannerHideEnum = cbhHideOnFocus);
const
  EM_SETCUEBANNER = $1501;
var
  wParam: Integer;
begin
  case _WhenToHide of
    cbhHideOnText: wParam := 1;
  else //    cbhHideOnFocus: ;
    wParam := 0;
  end;
  SendMessage(_ed.Handle, EM_SETCUEBANNER, wParam, Integer(PWideChar(_s)));
end;

You call it like this:

constructor TForm1.Create(_Owner: TComponent);
begin
  inherited;
  TEdit_SetCueBanner(ed_HideOnFocus, 'hide on focus', cbhHideOnFocus);
  TEdit_SetCueBanner(ed_HideOnText, 'hide on text', cbhHideOnText);
end;

It doesn't check for the Windows version though, you might want to add the if statement Uwe provided:

if CheckWin32Version(5, 1) and StyleServices.Enabled and _ed.HandleAllocated then

I just tested it with a project where I disabled runtime theming: It didn't work.

dummzeuch
  • 10,975
  • 4
  • 51
  • 158
  • Regarding your edit to my answer: SendMessage doesn't compile as Value is a string. That is why SendTextMessage is used (at least in D2009+). – Uwe Raabe Jul 22 '15 at 13:21
  • Ooops, sorry. I looked up SendTextMessage and couldn't find anything apart from sending SMS. Where is SendTextMessage declared? Is it an RTL function or Windows API? – dummzeuch Jul 22 '15 at 14:34
  • It is declared in (Winapi.)Messages since D2009 and wraps the ugly casting. Quite handy when LPARAM must point to a string. – Uwe Raabe Jul 22 '15 at 14:56
  • Thanks a lot @Uwe and dummzeuch for submitting your answers! I really appreciate it. After some research on creating components I was finally able to create my own (sorry, I don’t know how to highlight text) THintEdit and THintLabeledEdit, which worked perfectly! – Reginald Greyling Jul 22 '15 at 22:26
  • Will this work with `TComboBox` as well dummzeach and @UweRaabe? – Reginald Greyling Feb 21 '16 at 12:54
  • 1
    @LuiP3rd I haven't tested it, but it might. Did you try it? – dummzeuch Feb 22 '16 at 10:22