View Issue Details

IDProjectCategoryView StatusLast Update
0021307LazarusLCLpublic2017-10-08 15:38
ReportermalcomeAssigned ToBart Broersma 
PrioritynormalSeverityfeatureReproducibilityalways
Status resolvedResolutionfixed 
Product Version0.9.31 (SVN)Product Build 
Target Version1.6Fixed in Version1.6 
Summary0021307: TextHint support
DescriptionDelphi 2009 adds TextHint support to edit controls, a nice feature that lets you show a grayed out text watermark.
http://docwiki.embarcadero.com/VCL/XE2/en/StdCtrls.TCustomEdit.TextHint
But Lazarus does not have.
TagsNo tags attached.
Fixed in Revisionr48931
LazTarget1.6
WidgetsetWin32/Win64
Attached Files
  • editinduction.pas (4,406 bytes)
    unit EditInduction;
    
    {$mode objfpc}{$H+}
    
    interface
    
    uses
      Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
    
    type
    
      { TEditInduction }
    
      TEditInduction = class(TEdit)
      private
        { Private declarations }
        FInduction: TEdit;
        FInductionText: TCaption;
        FVisible: Boolean;
        function GetTextInduction: TCaption;
        procedure OnInductionEnter(Sender: TObject);
        procedure OnInductionExit(Sender: TObject);
        procedure SetTextInduction(const AValue: TCaption);
      protected
        { Protected declarations }
        procedure DoEnter; override;
        procedure DoExit; override;
        procedure SetVisible(Value: Boolean); override;
        procedure RealSetText(const AValue: TCaption); override;
        procedure ShowInduction(const aValue: Boolean);
        procedure Loaded; override;
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        function  IsVisible: Boolean; override;
      published
        { Published declarations }
        property TextInduction: TCaption read GetTextInduction write SetTextInduction;
      end;
    
    procedure Register;
    
    implementation
    
    procedure Register;
    begin
      RegisterComponents('Misc',[TEditInduction]);
    end;
    
    { TEditInduction }
    
    procedure TEditInduction.OnInductionEnter(Sender: TObject);
    begin
      FInduction.Visible:=false;
      inherited SetVisible(true);
      Self.SetFocus;
    end;
    
    function TEditInduction.GetTextInduction: TCaption;
    begin
      Result:=FInductionText;
    end;
    
    procedure TEditInduction.OnInductionExit(Sender: TObject);
    begin
    //
    end;
    
    procedure TEditInduction.SetTextInduction(const AValue: TCaption);
    begin
      if FInductionText=AValue then exit;
      FInductionText:=aValue;
      if not (csDesigning in Self.ComponentState) then begin
        if Assigned(FInduction) then FInduction.Text:=FInductionText;
      end;
    end;
    
    procedure TEditInduction.DoEnter;
    begin
      if not (csDesigning in Self.ComponentState) then begin
        FInduction.Hide;
      end;
      inherited DoEnter;
    end;
    
    procedure TEditInduction.DoExit;
    begin
      inherited DoExit;
      if not (csDesigning in Self.ComponentState) then begin
        ShowInduction(true);
      end;
    end;
    
    procedure TEditInduction.SetVisible(Value: Boolean);
    begin
      FVisible:=Value;
      if not (csDesigning in Self.ComponentState) then begin
        if FVisible and (Self.Text<>'') then begin
          FInduction.Visible:=false;
        end else if FVisible and (Self.Text='') then begin
          ShowInduction(true);
        end else begin
          FInduction.Visible:=false;
          inherited SetVisible(FVisible);
        end;
      end else begin
        inherited SetVisible(Value);
      end;
    end;
    
    procedure TEditInduction.RealSetText(const AValue: TCaption);
    begin
      inherited RealSetText(AValue);
      if not (csDesigning in Self.ComponentState) then begin
        if (AValue<>'') then begin
          FInduction.Visible:=false;
          inherited SetVisible(true);
        end else begin
          ShowInduction(true);
        end;
      end;
    end;
    
    procedure TEditInduction.ShowInduction(const aValue: Boolean);
    begin
      if (Self.Text='') and (aValue=true) then begin
        FInduction.Parent:=Self.Parent;
        FInduction.BoundsRect:=Self.BoundsRect;
        FInduction.Font:=Self.Font;
        FInduction.Font.Color:=clGrayText;
        FInduction.Font.Style:=[];
        FInduction.Alignment:=Self.Alignment;
        FInduction.Anchors:=Self.Anchors;
        FInduction.TabStop:=Self.TabStop;
        FInduction.ReadOnly:=true;
        FInduction.BorderStyle:=Self.BorderStyle;
        FInduction.BorderWidth:=Self.BorderWidth;
        FInduction.Text:=FInductionText;
        inherited SetVisible(false);
        FInduction.Visible:=true;
      end;
    end;
    
    procedure TEditInduction.Loaded;
    begin
      inherited Loaded;
      if not (csDesigning in Self.ComponentState) then begin
        if (Self.Text='') then begin
          ShowInduction(true);
        end;
      end;
    end;
    
    function TEditInduction.IsVisible: Boolean;
    begin
      Result:=FVisible;
    end;
    
    constructor TEditInduction.Create(AOwner: TComponent);
    begin
      FVisible:=true;
      inherited Create(AOwner);
      if not (csDesigning in Self.ComponentState) then begin
        FInduction:=TEdit.Create(AOwner);
        FInduction.TabOrder:=Self.TabOrder;
        FInduction.Visible:=false;
        FInduction.OnEnter:=@OnInductionEnter;
        FInduction.Text:=FInductionText;
      end;
    end;
    
    initialization
      {$I editinduction.lrs}
    
    end.
    
    editinduction.pas (4,406 bytes)
  • lcl.patch (2,049 bytes)
    Index: extctrls.pp
    ===================================================================
    --- extctrls.pp	(revision 49057)
    +++ extctrls.pp	(working copy)
    @@ -958,6 +958,9 @@
         property TabOrder;
         property TabStop;
         property Text;
    +    property TextHint;
    +    property TextHintFontColor;
    +    property TextHintFontStyle;
         property Visible;
         property OnChange;
         property OnClick;
    Index: include/customedit.inc
    ===================================================================
    --- include/customedit.inc	(revision 49057)
    +++ include/customedit.inc	(working copy)
    @@ -618,7 +618,7 @@
       Result:=fCaretPos;
     end;
     
    -procedure TCustomEdit.SetTextHint(AValue: String);
    +procedure TCustomEdit.SetTextHint(AValue: TTranslateString);
     begin
       if (FTextHint = AValue) then Exit;
       FTextHint := AValue;
    Index: stdctrls.pp
    ===================================================================
    --- stdctrls.pp	(revision 49057)
    +++ stdctrls.pp	(working copy)
    @@ -707,7 +707,7 @@
         FSelLength: integer;
         FSelStart: integer;
         FTextChangedByRealSetText: Boolean;
    -    FTextHint: String;
    +    FTextHint: TTranslateString;
         FTextHintShowing: Boolean;
         FSettingTextHint: Boolean;
         FTextHintFontColor: TColor;
    @@ -715,7 +715,7 @@
         FSavedFontColor: TColor;
         FSavedFontStyle: TFontStyles;
         FSavedParentFont: Boolean;
    -    procedure SetTextHint(AValue: String);
    +    procedure SetTextHint(AValue: TTranslateString);
         procedure ShowTextHint;
         procedure HideTextHint;
         procedure SetAlignment(const AValue: TAlignment);
    @@ -794,7 +794,7 @@
         property TabOrder;
         property TabStop default true;
         property Text;
    -    property TextHint: String read FTextHint write SetTextHint;
    +    property TextHint: TTranslateString read FTextHint write SetTextHint;
         property TextHintFontColor: TColor read FTextHintFontColor write FTextHintFontColor default clGrayText;
         property TextHintFontStyle: TFontStyles read FTextHintFontStyle write FTextHintFontStyle default [fsItalic];
       end;
    
    lcl.patch (2,049 bytes)

Relationships

related to 0028066 resolvedBart Broersma TextHint of edit: need "Show even if focused" 
related to 0030682 new [FEATURE REQUEST] Add TextHint to TComboBox and TMemo 

Activities

Zeljan Rikalo

2012-02-17 08:37

developer   ~0056873

Feature: target 1.2

José Mejuto

2012-02-17 13:43

reporter   ~0056879

Meanwhile you can try my home made TEdit descendant with a hint/induction. It has been tested only in windows and it works only in my needed cases, so some functionalities may be not present, fail, etc...

2012-02-17 13:44

 

editinduction.pas (4,406 bytes)
unit EditInduction;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TEditInduction }

  TEditInduction = class(TEdit)
  private
    { Private declarations }
    FInduction: TEdit;
    FInductionText: TCaption;
    FVisible: Boolean;
    function GetTextInduction: TCaption;
    procedure OnInductionEnter(Sender: TObject);
    procedure OnInductionExit(Sender: TObject);
    procedure SetTextInduction(const AValue: TCaption);
  protected
    { Protected declarations }
    procedure DoEnter; override;
    procedure DoExit; override;
    procedure SetVisible(Value: Boolean); override;
    procedure RealSetText(const AValue: TCaption); override;
    procedure ShowInduction(const aValue: Boolean);
    procedure Loaded; override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    function  IsVisible: Boolean; override;
  published
    { Published declarations }
    property TextInduction: TCaption read GetTextInduction write SetTextInduction;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Misc',[TEditInduction]);
end;

{ TEditInduction }

procedure TEditInduction.OnInductionEnter(Sender: TObject);
begin
  FInduction.Visible:=false;
  inherited SetVisible(true);
  Self.SetFocus;
end;

function TEditInduction.GetTextInduction: TCaption;
begin
  Result:=FInductionText;
end;

procedure TEditInduction.OnInductionExit(Sender: TObject);
begin
//
end;

procedure TEditInduction.SetTextInduction(const AValue: TCaption);
begin
  if FInductionText=AValue then exit;
  FInductionText:=aValue;
  if not (csDesigning in Self.ComponentState) then begin
    if Assigned(FInduction) then FInduction.Text:=FInductionText;
  end;
end;

procedure TEditInduction.DoEnter;
begin
  if not (csDesigning in Self.ComponentState) then begin
    FInduction.Hide;
  end;
  inherited DoEnter;
end;

procedure TEditInduction.DoExit;
begin
  inherited DoExit;
  if not (csDesigning in Self.ComponentState) then begin
    ShowInduction(true);
  end;
end;

procedure TEditInduction.SetVisible(Value: Boolean);
begin
  FVisible:=Value;
  if not (csDesigning in Self.ComponentState) then begin
    if FVisible and (Self.Text<>'') then begin
      FInduction.Visible:=false;
    end else if FVisible and (Self.Text='') then begin
      ShowInduction(true);
    end else begin
      FInduction.Visible:=false;
      inherited SetVisible(FVisible);
    end;
  end else begin
    inherited SetVisible(Value);
  end;
end;

procedure TEditInduction.RealSetText(const AValue: TCaption);
begin
  inherited RealSetText(AValue);
  if not (csDesigning in Self.ComponentState) then begin
    if (AValue<>'') then begin
      FInduction.Visible:=false;
      inherited SetVisible(true);
    end else begin
      ShowInduction(true);
    end;
  end;
end;

procedure TEditInduction.ShowInduction(const aValue: Boolean);
begin
  if (Self.Text='') and (aValue=true) then begin
    FInduction.Parent:=Self.Parent;
    FInduction.BoundsRect:=Self.BoundsRect;
    FInduction.Font:=Self.Font;
    FInduction.Font.Color:=clGrayText;
    FInduction.Font.Style:=[];
    FInduction.Alignment:=Self.Alignment;
    FInduction.Anchors:=Self.Anchors;
    FInduction.TabStop:=Self.TabStop;
    FInduction.ReadOnly:=true;
    FInduction.BorderStyle:=Self.BorderStyle;
    FInduction.BorderWidth:=Self.BorderWidth;
    FInduction.Text:=FInductionText;
    inherited SetVisible(false);
    FInduction.Visible:=true;
  end;
end;

procedure TEditInduction.Loaded;
begin
  inherited Loaded;
  if not (csDesigning in Self.ComponentState) then begin
    if (Self.Text='') then begin
      ShowInduction(true);
    end;
  end;
end;

function TEditInduction.IsVisible: Boolean;
begin
  Result:=FVisible;
end;

constructor TEditInduction.Create(AOwner: TComponent);
begin
  FVisible:=true;
  inherited Create(AOwner);
  if not (csDesigning in Self.ComponentState) then begin
    FInduction:=TEdit.Create(AOwner);
    FInduction.TabOrder:=Self.TabOrder;
    FInduction.Visible:=false;
    FInduction.OnEnter:=@OnInductionEnter;
    FInduction.Text:=FInductionText;
  end;
end;

initialization
  {$I editinduction.lrs}

end.
editinduction.pas (4,406 bytes)

Derit Agustin

2014-12-22 20:11

reporter   ~0079940

I've seen parts lazsolution
there placeholder TLSCustomEdit

Bart Broersma

2015-02-25 17:27

developer   ~0081422

Not blocker, postponed.

Bart Broersma

2015-03-17 22:34

developer   ~0082045

They use a TStaticText descendant for the texthint.
I dabbled a little bit with a TCustomControl descendant, but ran into serious Z-order problems on (my) GTK2.

Juha Manninen

2015-03-18 00:12

developer   ~0082046

We could implement it like in the FilterEdit components now. A grey hint is put into the Text property when the control has no focus.

Zeljan Rikalo

2015-03-18 08:39

developer   ~0082047

Yes, it should be implemented like filter edit. Show TextHint when edit.Text = '' and when it's not focused. At LCL level.

Bart Broersma

2015-05-03 16:50

developer   ~0083432

If we implement is by actually setting the Text of the control to the value of TextHint, then there should be a (virtual, protected) funcion like CanShowTextHint which controls the behaviour (e.g. for TMaskEdit it should return False if IsMasked = True).

Implementation detail: should the font-color (and other font attributes) of the control, when showing the TextHint, be "protected" when font.color is set by code and TextHint is showing?

Bart Broersma

2015-05-03 17:23

developer   ~0083434

Hmm, the Greeks probably implement it using EM_SETCUEBANNER message (https://msdn.microsoft.com/en-us/library/windows/desktop/bb761639%28v=vs.85%29.aspx), which takes care of all the nasty details.

Zeljan Rikalo

2015-05-03 17:55

developer   ~0083435

@Bart: It should be simple (coloring). We should add CanShowTextHint also because of TMaskEdit ....
Probably color of textHint could be: disabled text color (syscolor).

Bart Broersma

2015-05-03 17:58

developer   ~0083436

> Probably color of textHint could be: disabled text color (syscolor).
Which is clGrayText I think?
I would also vote for the texthint having fsItalic fontstyle as well.

Bart Broersma

2015-05-03 18:05

developer   ~0083437

SearchEdit from Luiz' LuiControls could be used as an example for it (https://code.google.com/p/luipack/source/browse/trunk/luicontrols/searchedit.pas)

Bart Broersma

2015-05-05 16:21

developer   ~0083476

I started implementing TextHint support in r48931.
Please test.

The properies
 TextHint;
 TextHintFontColor;
 TextHintFontStyle;
 
most likely need to be published many other TCustomEdit derived controls.

Feel free to add patches for these, or list the affected components.

Nur Cholif Murtadho

2015-05-18 01:40

reporter   ~0083728

Change the property to TTranslateString would be useful for translation.
TLabelelEdit can also use TextHint.
I attach a patch.

Nur Cholif Murtadho

2015-05-18 01:41

reporter  

lcl.patch (2,049 bytes)
Index: extctrls.pp
===================================================================
--- extctrls.pp	(revision 49057)
+++ extctrls.pp	(working copy)
@@ -958,6 +958,9 @@
     property TabOrder;
     property TabStop;
     property Text;
+    property TextHint;
+    property TextHintFontColor;
+    property TextHintFontStyle;
     property Visible;
     property OnChange;
     property OnClick;
Index: include/customedit.inc
===================================================================
--- include/customedit.inc	(revision 49057)
+++ include/customedit.inc	(working copy)
@@ -618,7 +618,7 @@
   Result:=fCaretPos;
 end;
 
-procedure TCustomEdit.SetTextHint(AValue: String);
+procedure TCustomEdit.SetTextHint(AValue: TTranslateString);
 begin
   if (FTextHint = AValue) then Exit;
   FTextHint := AValue;
Index: stdctrls.pp
===================================================================
--- stdctrls.pp	(revision 49057)
+++ stdctrls.pp	(working copy)
@@ -707,7 +707,7 @@
     FSelLength: integer;
     FSelStart: integer;
     FTextChangedByRealSetText: Boolean;
-    FTextHint: String;
+    FTextHint: TTranslateString;
     FTextHintShowing: Boolean;
     FSettingTextHint: Boolean;
     FTextHintFontColor: TColor;
@@ -715,7 +715,7 @@
     FSavedFontColor: TColor;
     FSavedFontStyle: TFontStyles;
     FSavedParentFont: Boolean;
-    procedure SetTextHint(AValue: String);
+    procedure SetTextHint(AValue: TTranslateString);
     procedure ShowTextHint;
     procedure HideTextHint;
     procedure SetAlignment(const AValue: TAlignment);
@@ -794,7 +794,7 @@
     property TabOrder;
     property TabStop default true;
     property Text;
-    property TextHint: String read FTextHint write SetTextHint;
+    property TextHint: TTranslateString read FTextHint write SetTextHint;
     property TextHintFontColor: TColor read FTextHintFontColor write FTextHintFontColor default clGrayText;
     property TextHintFontStyle: TFontStyles read FTextHintFontStyle write FTextHintFontStyle default [fsItalic];
   end;
lcl.patch (2,049 bytes)

Pavol S

2015-12-08 22:16

reporter   ~0087846

With this implementation there can be published TextHint* for TMemo control (based on TCustomEdit).

Delphi use EM_SETCUEBANNER message which work only with TEdit (https://msdn.microsoft.com/en-us/library/bb761639%28VS.85%29.aspx).

Bart Broersma

2015-12-09 10:53

developer   ~0087851

Please open a new ticket for textHint support for TCustomMemo.

malcome

2015-12-17 05:01

reporter   ~0088023

Of cause the TComboBox, too.

malcome

2015-12-17 05:44

reporter   ~0088024

And...
I'd like to order the same one in Windows if you can.

SendMessage(Edit1.Handle, EM_SETCUEBANNER, WPARAM(1), LPARAM(PChar('It is a Hint.')));

Thank you.

Bart Broersma

2015-12-17 16:44

developer   ~0088039

Obviously I was not clear enough.
This issue was about TextHint support for TCustomEdit.
This was implemented.
I will close this ticket now.

Please put new requests for TextHint support for other controls in a new ticket.

malcome

2015-12-18 05:15

reporter   ~0088056

Last edited: 2015-12-18 05:18

View 2 revisions

Hi, Bart. Thanks always.

To keep the component's balance is your work, not ours.
Actually, that doesn't give us any problem,
because we already did it in our own applications.
(For example, sending EM_SETCUEBANNER message. Of cause it is not the muliti platforms)

Bart Broersma

2015-12-18 18:48

developer   ~0088069

@malcome:

> To keep the component's balance is your work, not ours.

Excuse me?
I have no obligation to you what so ever.
Why would you think so?

Yes, I implemented TCustomEdit.TextHint, and I'm willing to look into bugs.
But, I cannot emphasize this enough, I DO NOT OWE YOU ANYTHING AT ALL.

This is the last time I tell you.

TCustomEdit.TextHint is implemented now.
Please put new requests for TextHint support for other controls in a new ticket.

And, as always, possible solutions to the request should be cross-platform.

On Windows it's probably easy to use things like EM_SETCUEBANNER, and NOBODY stops you from doing so in your own programs.


Do NOT, I repeat, NOT re-open this issue again.

malcome

2015-12-19 02:57

reporter   ~0088082

Hi, Bart. Thanks always.

I have not requests now, because I am not troubled.
But I have a question so please approve reopen.

By the way, Why is italic font default?
Maybe Delphi compatibility?
That is poor taste especially in East Asian characters.

Bart Broersma

2015-12-19 18:12

developer   ~0088088

> Maybe Delphi compatibility?
Because "a native implementation" (using Windows API) looks like that, hence I emulated it.
At least you can remove the Italic from the style if wanted.

Can you please now close this isse.

Questions can and will be answered (by me or others) on the foum or mailinglist.

Issue History

Date Modified Username Field Change
2012-02-17 03:48 malcome New Issue
2012-02-17 03:48 malcome Widgetset => Win32/Win64
2012-02-17 08:37 Zeljan Rikalo LazTarget => 1.2
2012-02-17 08:37 Zeljan Rikalo Note Added: 0056873
2012-02-17 08:37 Zeljan Rikalo Status new => acknowledged
2012-02-17 13:43 José Mejuto Note Added: 0056879
2012-02-17 13:44 José Mejuto File Added: editinduction.pas
2014-01-14 15:16 Martin Friebe LazTarget 1.2 => 1.4
2014-12-22 20:11 Derit Agustin Note Added: 0079940
2015-02-25 17:27 Bart Broersma LazTarget 1.4 => 1.6
2015-02-25 17:27 Bart Broersma Note Added: 0081422
2015-03-17 22:34 Bart Broersma Note Added: 0082045
2015-03-18 00:12 Juha Manninen Note Added: 0082046
2015-03-18 08:39 Zeljan Rikalo Note Added: 0082047
2015-05-03 16:50 Bart Broersma Note Added: 0083432
2015-05-03 17:23 Bart Broersma Note Added: 0083434
2015-05-03 17:55 Zeljan Rikalo Note Added: 0083435
2015-05-03 17:58 Bart Broersma Note Added: 0083436
2015-05-03 18:05 Bart Broersma Note Added: 0083437
2015-05-05 16:15 Bart Broersma Assigned To => Bart Broersma
2015-05-05 16:15 Bart Broersma Status acknowledged => assigned
2015-05-05 16:21 Bart Broersma Note Added: 0083476
2015-05-09 14:07 Bart Broersma Fixed in Revision => r48931
2015-05-09 14:07 Bart Broersma Status assigned => resolved
2015-05-09 14:07 Bart Broersma Fixed in Version => 1.6
2015-05-09 14:07 Bart Broersma Resolution open => fixed
2015-05-09 14:07 Bart Broersma Target Version => 1.6
2015-05-10 12:57 Bart Broersma Relationship added related to 0028066
2015-05-18 01:40 Nur Cholif Murtadho Note Added: 0083728
2015-05-18 01:41 Nur Cholif Murtadho File Added: lcl.patch
2015-12-08 22:16 Pavol S Note Added: 0087846
2015-12-09 10:53 Bart Broersma Note Added: 0087851
2015-12-09 10:53 Bart Broersma Status resolved => feedback
2015-12-17 05:01 malcome Note Added: 0088023
2015-12-17 05:01 malcome Status feedback => assigned
2015-12-17 05:44 malcome Note Added: 0088024
2015-12-17 16:44 Bart Broersma Note Added: 0088039
2015-12-17 16:44 Bart Broersma Status assigned => resolved
2015-12-17 16:44 Bart Broersma Status resolved => closed
2015-12-18 05:15 malcome Note Added: 0088056
2015-12-18 05:15 malcome Status closed => assigned
2015-12-18 05:15 malcome Resolution fixed => reopened
2015-12-18 05:18 malcome Note Edited: 0088056 View Revisions
2015-12-18 18:48 Bart Broersma Note Added: 0088069
2015-12-18 18:49 Bart Broersma Status assigned => resolved
2015-12-18 18:49 Bart Broersma Resolution reopened => fixed
2015-12-18 18:49 Bart Broersma Status resolved => closed
2015-12-19 02:57 malcome Note Added: 0088082
2015-12-19 02:57 malcome Status closed => assigned
2015-12-19 02:57 malcome Resolution fixed => reopened
2015-12-19 18:12 Bart Broersma Note Added: 0088088
2015-12-19 18:12 Bart Broersma Status assigned => resolved
2015-12-19 18:12 Bart Broersma Resolution reopened => fixed
2017-10-08 15:38 Juha Manninen Relationship added related to 0030682