Solved

Flickerless coloured text

Posted on 1997-08-30
5
221 Views
Last Modified: 2010-05-18
I want to display a text (Tlabel) and part of letters must have one colour (e.g. blue) and part must have
another colour (e.g. red).

Example:
Situation 1: all letters are red
Situation 2: the leftmost letter is blue, the rest is red
Situation 3: the 2 most left letters are blue, the rest is red
Situation 4: all letters are blue.

About 20 times every second a letter must change its colour, WITHOUT any flickering.
So far, I have tried the following with and without
REPAINT, REDRAW.

I tried using 2 labels (the left label initially empty,
and then growing with 1 letter at the time, while the
second label initially is full, and looses 1 letter at
the time): FLICKERING occurs.

I tried using 1 label with a shape over it, colouring
the letters. The shape initially has a width of zero,
and grows the width of a letters every time:
FLICKERING occurs.

I tried using 1 label with up to ten shapes colouring the
letters (initially all shapes have a width of zero,
and then grow in turn with 1,2,3,4,..or 10 letters width): FLICKERING occurs).


Due to the target of the program: I can't use Canvas.Paint
or at least I rather wouldn't want to do this, because
the label can be anywhere on the screen, and be moved
around at runtime.

I'm totally out of idears.
0
Comment
Question by:Willem083097
  • 3
5 Comments
 
LVL 2

Accepted Solution

by:
icampbe1 earned 200 total points
ID: 1343080
I guess that the best approach would be to set csOpaque in the ControlStyle property.  You can further explore the use of invalidate on changes.  Finally, you can process the WM_ERASEBKGND message and return a non zero (although I'm not sure that descendants of TGraphicControl get that message).  

I believe that setting csOpaquw will do it though.  Hope this helps.

Ian C.

PS:  I think I will write a little component this afternoon to play with the idea.  If it works... its yours.

0
 
LVL 2

Expert Comment

by:icampbe1
ID: 1343081
Ok, ignnore my previous comment.  here is a lable that I named TStateLabel (you can change its state ).  It is a TLabel with two new properties:  HiliteColor and HiliteState.

Hilite color is default Blue but you can change it with this property.
The default text color is Red, but you can change that (Font.Color).
The HiliteState property has the following values:
 hsNone - No hilited characters
 hsOne - the first character
 hsTwo - the first two characters
 hsAll - all hilited.

Just install it on your palette and drop it on your form.  You can set the properties in the IDE or from your program.  I assume that you will mostly want to change the HiliteState property.

NO FLICKER!!!

If I had your E-Mail I would send it that way... Oh well, here it is.

UNIT StateLabel;

INTERFACE

USES
 Windows, Messages, Classes, Controls, Graphics, StdCtrls;

TYPE
  THiliteState = ( hsNone, hsOne, hsTwo, hsAll );

  TStateLabel = CLASS( TLabel )
  PRIVATE
    FHiliteState: THiliteState;
    FHiliteFont:  TFont;
    PROCEDURE SetHiliteColor( AValue: TCOlor );
    FUNCTION  GetHiliteColor: TColor;
    PROCEDURE SetHiliteState( AValue: THiliteState );
    PROCEDURE CMFontChanged( VAR Message: TMessage ); Message CM_FONTCHANGED;
  PROTECTED
    PROCEDURE Paint;  Override;
  PUBLIC
    CONSTRUCTOR Create( AOwner: TComponent );  Override;
    DESTRUCTOR Destroy;  Override;
  PUBLISHED
    PROPERTY HiliteColor: TColor  read GetHiliteColor write SetHiliteColor;
    PROPERTY HiliteState: THiliteState  read FHiliteState write SetHiliteState;
  END;

PROCEDURE Register;


IMPLEMENTATION


CONSTRUCTOR TStateLabel.Create( AOwner: TComponent );
BEGIN
   Inherited Create( AOwner );
   FHiliteFont := TFont.Create;
   FHiliteFont.Assign(Font);
   FHiliteFont.Color := clBlue;

   Font.Color := clRed;
   FHiliteState := hsNone;
END;

DESTRUCTOR TStateLabel.Destroy;
BEGIN
   FHiliteFont.Free;
   Inherited Destroy;
END;

FUNCTION TStateLabel.GetHiliteColor: TColor;
BEGIN
   Result := FHiliteFont.Color;
END;

PROCEDURE TStateLabel.SetHiliteColor( AValue: TCOlor );
BEGIN
   IF FHiliteFont.Color <> AValue THEN BEGIN
      FHiliteFont.Color := AValue;
      Invalidate;
      END;
END;

PROCEDURE TStateLabel.CMFontChanged( VAR Message: TMessage );
VAR Temp: TColor;
BEGIN
   Inherited;
   Temp := FHiliteFont.Color;
   FHiliteFont.Assign(Font);
   FHiliteFont.Color := Temp;
   Invalidate;
END;

PROCEDURE TStateLabel.SetHiliteState( AValue: THiliteState );
BEGIN
   IF FHiliteState <> AValue THEN BEGIN
      FHiliteState := AValue;
      Invalidate;
      END;
END;

PROCEDURE TStateLabel.Paint;
VAR
  Rect: TRect;
  DrawStyle: Integer;
  Text: String;
BEGIN
   Inherited Paint;
   Text := GetLabelText;
   IF FHiliteState <> hsNone THEN
      WITH Canvas DO BEGIN
         Brush.Style := bsClear;
         Rect := ClientRect;
         DrawStyle := DT_EXPANDTABS;
         IF WordWrap THEN DrawStyle := DrawStyle OR DT_WORDBREAK;
         CASE Alignment OF
           taLeftJustify:  DrawStyle := DrawStyle OR DT_LEFT;
           taRightJustify: DrawStyle := DrawStyle OR DT_RIGHT;
           taCenter:       DrawStyle := DrawStyle OR DT_CENTER;
           END;
         IF Layout <> tlTop THEN BEGIN
            DrawText(Handle,PChar(Text),Length(Text), Rect, DrawStyle OR DT_CALCRECT);
            IF Layout = tlBottom THEN
               OffsetRect( Rect, 0, Height-Rect.Bottom )
            ELSE
               OffsetRect( Rect, 0, (Height-Rect.Bottom) DIV 2 );
            END;
         CASE FHiliteState OF
           hsOne:  Text := Copy( Text, 1, 1 );
           hsTwo:  Text := Copy( Text, 1, 2 );
           END;
         Canvas.Font := FHiliteFont;
         DrawText( Canvas.Handle, PChar(Text), Length(Text), Rect, DrawStyle );
         END;
END;


PROCEDURE Register;
BEGIN
  RegisterComponents('Samples', [TStateLabel]);
END;

end.


Have fun  :)

Ian C.
0
 
LVL 2

Expert Comment

by:icampbe1
ID: 1343082
Hi again,

I did a little cleanup on the label.  It now works exactly as it should (including alignments of left, right, center, and enabled etc).  My E-Mail is iancamp@interlog.com, send me a note with your E-Mail address, and I mail it to you instead of posting it.  I've tested it thoroughly and it works just fine.

Ian C.

0
 

Author Comment

by:Willem083097
ID: 1343083
Superb! There are no other words to describe the fast answer
of Ian Campbel.

Using both Delphi 2.0 and since shortly Delphi 3.0, his component
gave a compiler error: stupid me: I was running it under
Delphi 2.0. By the time I found out the reason, Ian had already
send me an email including a 2.0 version.

Thanks a lot Ian!. Excellent answer!.
I will use your component as soon as I figure out how I
can use a integerparameter for setting the number of letters
to be coloured in stead of a predefined hsOne, hsTwo state-
definition (which is not very useful of course when
I want to change the colour of the 134th letter).

BTW: I already discovered that a (loosy) alternative approach is
to use a transparent Tlabel for every letter with a
caption ' x ' where x = the letter. Precalc the width of
solely the x and start the following letter there, minus
the leading space (necessary because e.g. the f and j can
share the same x-coordinates)
Before changing the color, the original width must be retained because the width of e.g. an f in Arial 100 points is wrongly returned when measered on another (invisible) label.
This is both fast and not flickering. It is also not
a very good approach.

Willem
0
 

Expert Comment

by:Shakil
ID: 3332612
If u could write a code to color 134th Char only.

Shakil
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now