TLabel.Colorize

Hi,

has been a time, well i am trying to make an OnCreate event that will make all the TLabel(s) on my form change color onMouseOver !!

Any Ideas ??
LVL 3
neostudioAsked:
Who is Participating?
 
Stuart_JohnsonConnect With a Mentor Commented:
Doing it the way Alan (forgive me if this isn't your name) suggested will cause problems.  Each component will need to have an OnMouseMove event (unless you use a mouse hook which I can give you), otherwise you wont be guarenteed of getting a "mouse off" event.

The other problem is, depending on the complexity of your application, this will REALLY slow down the program.  Everytime you move the mouse just one pixel, it will need to recheck each and every control on the form.

Sorry if I appeared mad.   I wasn't.  I just think that you'd be better off using a component.  I am usually reluctant to use third party components and like sticking with native controls, but in this instance, I'm sure it can be overlooked as the code is just so generic and wont change.

If you DO opt to go with a new TLabel descendant (I can give you a slightly better option than the one posted before), all you need to do is add the component to your palette, make sure each form in your app has the new component's unit name in it's uses clause, then simply right click on each form, go "View as Text" and do a search/replace for TLabel and change to TExtLabel (whatever you end up calling it).  When you recompile, Delphi will re-declare each component and you'll have coloured labels - all in a few minutes of work.  Much neater, and certainly a damn sight faster than using enumerated controls :)

Hope this helps,

Stu.
0
 
nnbbb09Commented:

This is a simple custom component that gives you an OnMouseEnter and OnMouseExit event handler, just install it into a package. You can then attach code to change the font color

unit ExtLabel;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TExtLabel = class(TLabel)
  private
    FOnMouseExit: TNotifyEvent;
    FOnMouseEnter: TNotifyEvent;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  published
    property OnMouseEnter : TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
    property OnMouseExit : TNotifyEvent read FOnMouseExit write FOnMouseExit;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Extended', [TExtLabel]);
end;

{ TExtLabel }

procedure TExtLabel.CMMouseEnter(var Message: TMessage);
begin
  if assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TExtLabel.CMMouseLeave(var Message: TMessage);
begin
  if assigned(FOnMouseExit) then
    FOnMouseExit(Self);
end;

Hope this helps

Jo
0
 
alanwhincupCommented:
You could do it like this:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
    procedure LabelMouseOver(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.LabelMouseOver(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  I : Integer;
begin
  for I := 0 to ControlCount - 1 do
    if (Controls[I] is TLabel) then
      TLabel(Controls[I]).Color := clRed;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I : Integer;
begin
  for I := 0 to ControlCount - 1 do
    if (Controls[I] is TLabel) then
      TLabel(Controls[I]).OnMouseMove := LabelMouseOver
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  I : Integer;
begin
  for I := 0 to ControlCount - 1 do
    if (Controls[I] is TLabel) then
      TLabel(Controls[I]).Color := clBtnFace;
end;

end.

For any other controls on the form you would have to point the OnMouseOver Event to FormMouseMove so that the labels color was put back to normal if the mouse went over them and not the form.

Cheers,

Alan.
0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
neostudioAuthor Commented:
nope, sorry .
i do not want components !!
0
 
neostudioAuthor Commented:
ok...

seems i forgot to mention an important thing..

all labels are on a tabsheet and not direct on form...
so, it didnt work !!
0
 
Stuart_JohnsonCommented:
I dont think that is possible to do without components.  Using alanwhincup's method will only work if the laels are owned by the form (so, if you drop a label on a TPanel, it won't change back to the old colour.  You would need to enumerate each "container" object on the form.

I think you are going to be stuck with a component, or use nnbbb09's code and modify the TLabel component directly (not recommended!).
0
 
neostudioAuthor Commented:
don't really know but i have seen this...

i'll  be waiting...
0
 
Stuart_JohnsonCommented:
Hi,

Can you ellaborate on your last post?  I'm not sure what you mean.

Cheers!

Stu.
0
 
neostudioAuthor Commented:
i mean i have seen some people doing this in delphi
and i wonder wheather it is a real hard task ??!!!
so i will be waiting for mre ideas ..

that's all folks


......</br>
0
 
SJohnsonCommented:
Try this for size.  Just open a new project and paste this over all the existing code.  Don't change the form name.  Save, compile, run:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type

TExtLabel = class(TLabel)
 private
   FOnMouseExit: TNotifyEvent;
   FOnMouseEnter: TNotifyEvent;
   procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
   procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
 published
   property OnMouseEnter : TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
   property OnMouseExit : TNotifyEvent read FOnMouseExit write FOnMouseExit;
 end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure MouseEnter(Sender: TObject);
    procedure MouseExit(Sender: TObject);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  with TExtLabel.Create(Self) do
    begin
      Parent := Form1;
      Top := 100;
      Left := 100;
      Caption := 'Hi!';
      OnMouseEnter := MouseEnter;
      OnMouseExit := MouseExit;
    end;
end;

procedure TForm1.MouseEnter(Sender: TObject);
begin
  TExtLabel(Sender).Font.Color := clRed;
end;

procedure TForm1.MouseExit(Sender: TObject);
begin
  TExtLabel(Sender).Font.Color := clBtnText;
end;

{ TExtLabel }

procedure TExtLabel.CMMouseEnter(var Message: TMessage);
begin
  if assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TExtLabel.CMMouseLeave(var Message: TMessage);
begin
 if assigned(FOnMouseExit) then
   FOnMouseExit(Self);
end;

end.


The code nnbbb09 posted is generic, but he was the first to put it up, so he should be recognised if you go with this option.

Please note, that you will HAVE to dynamically create ALL your labels this way.  If you do NOT want to do it this way, you'll have to make a new label component.

Stu.
0
 
Stuart_JohnsonCommented:
Dammit... My alterego has surfaced :)
0
 
neostudioAuthor Commented:
i understand...

your code is nice and neat, but i will need to make every label by myself, what am i looking for is something like hottracking the mouse when it is over the TLabels in all my program !!
0
 
Stuart_JohnsonCommented:
Yeah, which is why I said you'll need a component.  You can either do it yourself as mentioned above, or do it with a component like nnbbb09 posted.

Can someone else back me on this please?
0
 
neostudioAuthor Commented:
Don't get mad....

didn't you say ".  Using alanwhincup's method will only work if
the laels are owned by the form (so, if you drop a label on a TPanel, it won't change back to the old
colour.  You would need to enumerate each "container" object on the form.
"

???
0
 
neostudioAuthor Commented:
The best way yet...
i am convinced...


..</br> :-)
0
 
Stuart_JohnsonCommented:
Hi again,

Do you want me to post nnbbb09's code slightly modified so you dont have to worry about events?

Stu.
0
 
neostudioAuthor Commented:
if you'll have time...
0
 
Stuart_JohnsonCommented:
Hi Dude,

Try this component out.  I have added two new properties: FontMouseLeave and FontMouseOver.  FMO defaults to clRed.  You can change this before building the component if you want it to be anything other than clRed.

unit HoverLabel;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  THoverLabel = class(TLabel)
  private
    FFontMouseLeave: TFont;
    FFontMouseOver: TFont;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure CMMouseOver(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure SetFontMouseLeave(const Value: TFont);
    procedure SetFontMouseOver(const Value: TFont);
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    property FontMouseOver: TFont read FFontMouseOver write SetFontMouseOver;
    property FontMouseLeave: TFont read FFontMouseLeave write SetFontMouseLeave;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [THoverLabel]);
end;

{ THoverLabel }

procedure THoverLabel.CMMouseOver(var Message: TMessage);
begin
  Font := FFontMouseOver;
end;

procedure THoverLabel.CMMouseLeave(var Message: TMessage);
begin
  Font := FFontMouseLeave;
end;

procedure THoverLabel.SetFontMouseLeave(const Value: TFont);
begin
  FFontMouseLeave := Value;
end;

procedure THoverLabel.SetFontMouseOver(const Value: TFont);
begin
  FFontMouseOver := Value;
end;

constructor THoverLabel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FFontMouseLeave := TFont.Create;
  FFontMouseOver := TFont.Create;
  FFontMouseLeave.Assign(Font); {Duplicate current font}
  FFontMouseOver.Assign(Font); {Duplicate current font}
  FFontMouseOver.Color := clRed; {change these two lines to something else if required}
end;

destructor THoverLabel.Destroy;
begin
  FFontMouseOver.Free;
  FFontMouseLeave.Free;
  inherited Destroy;
end;

end.

Cheers,

Stu.
0
 
neostudioAuthor Commented:
Thanks a lot !
0
 
modderCommented:
Stuart,

I've suspended your duplicate account. I will not suspend your main Stuart Johnson account this time but please only use *one* account in Experts-Exchange.
0
 
modderCommented:
modder
Community Support
0
 
Stuart_JohnsonCommented:
Can I ask why?  I was told about 3 years ago that it would be OK to maintain two accounts because one was used for work related issues (it's actually used by our IT department), and the other one is my personal account which I use to ask/answer questions relating to topics that interest me.

I have open questions under SJohnson.  What happens with them?
0
 
modderCommented:
Post the URLs to those questions here and we'll ensure that they're brought to a satisfactory conclusion.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.