Solved

Accelerated characters with Canvas.Textout()???

Posted on 2004-10-17
12
352 Views
Last Modified: 2013-12-03
I'm making my own buttoncomponent, derived from TCustomControl. Now I want to be able to create a shortcut for the button, using accelerated characters (underlined characters, the ones with an & in front of them in the Caption). How would I do that? And how do I connect a shortcut to the button once I can display the accelerated characters??

I'm using Canvas.TextOut() to display the caption on the button. Tried using a TCustomLabel on top of the button, but there are problems with mousecapture and stuff with that solution, so if itäs possible to use Canvas.TextOut() I'd prefer that...

0
Comment
Question by:mmmMange
  • 4
  • 3
  • 2
  • +3
12 Comments
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 12332151
Play around with DT_NOPREFIX in the DrawText function.
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 12332184
if your component is named CustomControlXP:

declare in the class definition:
      procedure      Paint; override;

//........

implementation

procedure   TCustomControlXP.Paint;
var
  L:        Word;
  T:        Word;
  H:        Word;
  W:        Word;
begin
  Canvas.Font := Font;
  H := Canvas.TextHeight(Caption);
  W := Canvas.TextWidth(Caption);
  L := (Width - W) div 2;
  T := (Height - H) div 2;
  Canvas.TextOut(L, T, Caption);
end;
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 12332203
excuse me, I forgot a row into the procedure:

  Canvas.Brush.Color := Color;
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 12332261
procedure   TCustomControlXP.Paint;
var
  L:        Word;
  T:        Word;
  H:        Word;
  W:        Word;
begin
  Canvas.Font := Font;
  Canvas.Brush.Color := Color;
  H := Canvas.TextHeight(Caption);
  W := Canvas.TextWidth(Caption);
  L := (Width - W) div 2;
  T := (Height - H) div 2;
  Canvas.TextOut(L, T, Caption);
end;
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 12332286
procedure   TCustomControlXP.Paint;
var
  L:        Word;
  T:        Word;
  H:        Word;
  W:        Word;
begin
  inherited;
  Canvas.Font := Font;
  Canvas.Brush.Color := Color;
  H := Canvas.TextHeight(Caption);
  W := Canvas.TextWidth(Caption);
  L := (Width - W) div 2;
  T := (Height - H) div 2;
  Canvas.TextOut(L, T, Caption);
end;
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 12334861
It was problem to figure out the position on the X axis, so I used hardcoded numbers in this example. It is not very pretty code, but here is the idea...


procedure TForm1.PaintCaption(S: String);
var
  FirstPart     : String;  // text before the &
  UnderLined    : String;  // underlined character
  LastPart      : String;  // last part - no underline
  lc_pos        : Integer;
begin
  lc_pos      := Pos('&', S);
  FirstPart   := Copy(S, 1, lc_pos - 1);
  UnderLined  := Copy(S, lc_pos + 1, 1);
  LastPart    := Copy(S, lc_pos + 2, length(S) - lc_pos + 2);
  with Self.Canvas do
    begin
      // set color and remove underline (if set)
      Font.Color := clBlack;
      Font.Style := Font.Style - [fsUnderline];
      // output text
      TextOut(2, 2, FirstPart);
      // set underline

      // THIS LINE HERE SHOULD BE EXECUTED IF ALT IS PRESSED
      // ***************************************************
      Font.Style := Font.Style + [fsUnderline];
      // ***************************************************

      // underlined symbol
      TextOut(30, 2, UnderLined);
      // remove underline
      Font.Style := Font.Style - [fsUnderline];
      TextOut(42, 2, LastPart);
    end;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  PaintCaption('Hello &World!');
end;
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:mmmMange
ID: 12334874
Thanks DragonSLayer, I would never have found that method if you hadn't told me! But there are still problems - the font looks like FixedSys or Terminal, no matter what I set Canvas.Font to.... Weird.

Do you know how I can "connect" a shortcut to my key too?
0
 
LVL 3

Expert Comment

by:jpedef
ID: 12336266
Why you just don't use windows DrawText function.

procedure DrawCaption;
var
  R: TRect;
  s: string;
begin
  R.Left := 50;
  R.Right := 200;
  R.Top := 50;
  R.Bottom := 100;
  s := '&This is a line';
  DrawText(Canvas.Handle, PChar(s), Length(s), R, DT_VCENTER or DT_SINGLELINE or DT_CENTER);
end;

For shortcuts, take a look at TCustomLabel-component's source.
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 12336315
Delphi's TButton uses the CM_DIALOGCHAR message to capture the keystrokes and 'connect' the accelerator character to the button.

To change the font... well, does your component store its own Font values? If it does, then before drawing you would need to do a

Canvas.Font := Font;

or Canvas.Font.Assign(Font);

Or, you can manually select the font... e.g.

var
  FontHandle: HFont;

...

  FontHandle := CreateFont(0, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, PChar('Tahoma'));
  SelectObject(Canvas.Handle, FontHandle);

...

0
 

Author Comment

by:mmmMange
ID: 12337086
I can't find any info on CM_DIALOGCHAR in my helpfiles, is there some webpage that describes the message so I know what to do with it? (Tried Google'ing with no result)

About the font - problem solved. I thought I needed to do a GetDeviceContext(Canvas.Handle), but the Canvas.Handle is in fact already a device-context... So now the font works fine.
0
 
LVL 14

Assisted Solution

by:DragonSlayer
DragonSlayer earned 300 total points
ID: 12337331
Are you sure you did a google search? My first search revealed this:
http://www.undu.com/DN970601/00000021.htm
0
 
LVL 33

Accepted Solution

by:
Slick812 earned 200 total points
ID: 12348057
hello mmmMange ,  the TControl and it's decendents will automaticllay put an "Accelerated Charater" in a Control's Caption in to the accelerated charater list for the form. . .(to have an accelerated Charater you place a  &  infront of it when you assign the caption). . .

to get the accerated charater notify you get the delphi generated CM_DIALOGCHAR message and then test for the CharCode with the IsAccel function,
so you do not need any code to initialize an Accerated Character, TControl does that, but you will need to process the CM_DIALOGCHAR message


  private
  { Private declarations }
    procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;


procedure TTextBubble.CMDialogChar(var Message: TCMDialogChar);
begin
with Message do
  if IsAccel(CharCode, Caption) and Enabled and Visible and // also check for enabled and visible
      (Parent <> nil) and Parent.Showing then
    begin
    Click; // I just call this control's OnClick for accelerated charater event
    Result := 1; // have Result of message as one
    end else
    inherited;
end;


 = = = = = = = = = =  = = = = = = = = = = = = = =

you seem to already have the text draw, but here is some code I have used -


procedure TTextBubble.Paint;
var
cRect: TRect;
ColorO: TColor;
begin
inherited;
cRect := ClientRect;
if Height > 46 then
cRect.Bottom := cRect.Bottom- 10
else
cRect.Bottom := cRect.Bottom- 4;
with Canvas do
  begin
  ColorO := Brush.Color;
  if FDown then
    Brush.Color := $E0FFF8
    else
    Brush.Color := FColor;
  FillRect(GetClientRect);
  if Length(Caption) > 0 then
  DrawText(Handle, PChar(Caption), -1, cRect, DT_CENTER or DT_SINGLELINE or DT_VCENTER);
  Brush.Color := ColorO;
  end;
end;

 - - - - - - - - - - - - - -  -- - - - - - -  - - -
this may be helpful to you
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

708 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

18 Experts available now in Live!

Get 1:1 Help Now