Solved

Using THintInfo/THitWindow

Posted on 2000-02-20
16
997 Views
Last Modified: 2010-05-18
Hi all,

I'm programming a component to control a applications hint window. And thats no problem. But then i read something in the help file that i dont understand.
See THintInfo.CursorRect :
"The rectangle the user's mouse pointer must be in for the hint window to appear. The default value for CursorRect is the client rectangle of the control. Change this value so that a single control can be divided into several hint regions. When the user moves the mouse pointer outside the rectangle, the hint window disappears."

If it should be possible to "divide the control into several hint regions" it must also be possible to create several THintInfo records at create-time, right ??
That would be very useful - e.g. in a TStringGrid - to show different hint to the columns.

Today i'm using TApplication.OnShowHint to change the hint text.

Does anyone know or understand how to use/create additional THintInfo records ??

Regards
Peter
0
Comment
Question by:PeterLarsen
  • 6
  • 3
  • 3
  • +4
16 Comments
 
LVL 2

Author Comment

by:PeterLarsen
ID: 2539821
Well, I ment "Using THintInfo/THintWindow"
0
 
LVL 2

Expert Comment

by:rene100
ID: 2539987
listening.....
0
 
LVL 8

Accepted Solution

by:
ZifNab earned 200 total points
ID: 2540205
mmm, don't know what you mean exactly, but is this what you want?


Specifically, the code:
1) Checks to see if the control in question is a TListBox using the is
operator

2) Determines which item the mouse is over using ItemAtPos. This is
used to exreact the string for the hint. The TopIndex is use to
determine the position of the cursor relative to the first item
displayed.

3) Checks the length of the string to see if a hint is necessary, using
the TextWidth method and the ClientWidth property of the TListBox.

4) Positions the hint over the item

5) Sets the CursorRect so the hint appears and disappears as necessary
when the mouse moves between items


{ .. In the form declaration ... }
procedure ShowCustomHint(var HintStr: string; var CanShow: Boolean; var HintInfo:
THintInfo);


{ In the implementation section }
procedure TForm1.ShowCustomHint(var HintStr: string; var CanShow: Boolean; var
HintInfo: THintInfo);
var
  cp : TPoint;
  lb : TListBox;
  item_num, item_height : integer;
begin
  if (HintInfo.HintControl is TListBox) then begin
    lb := TListBox(HintInfo.HintControl);
    cp := HintInfo.CursorPos;

    item_num := TListbox(HintInfo.HintControl).ItemAtPos(cp,true);
    if item_num = -1 then
      Exit;
    if lb.Canvas.TextWIdth(lb.Items[item_num]) < lb.ClientWidth then
begin
      CanShow := False;
      Exit;
    end;
    HintStr := lb.Items[item_num];

    item_num := item_num - lb.TopIndex;
    item_height := lb.ItemHeight;
    HintInfo.HintPos := lb.ClientToScreen(Point(0,item_num *
item_height));
    HintInfo.CursorRect := Rect(0,item_num *
item_height,lb.Width,(item_num + 1) * item_height);
  end;
end;

{ Remember to install the handler when the form is created }
{ The handler applies to all forms however }
procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnShowHint := ShowCustomHint;
end;

Regards, Zif
0
 
LVL 17

Expert Comment

by:inthe
ID: 2540272
hello ,
example for stringgrid.
if you drop a stringgrid on a form and fill some cells with text the hint of each cell is the text of the current cell the mouse is over :

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure FormShowHint(var HintStr: String;
  var CanShow: Boolean; var HintInfo: THintInfo);

  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormShowHint(var HintStr: String;
  var CanShow: Boolean; var HintInfo: THintInfo);
var ACol, ARow : integer;
begin
with HintInfo do
  if (HintControl is TStringGrid) then
    with (HintControl as TStringGrid) do begin
     CanShow := false;
     MouseToCell(CursorPos.X, CursorPos.Y, ACol, ARow);
    HintInfo.CursorRect := stringgrid1.CellRect(ACol, ARow);
   HintInfo.HintStr := stringgrid1.Cells[acol,arow];
  CanShow := true;
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Application.OnShowHint := self.FormShowHint;
end;

end.

Regards Barry
0
 
LVL 2

Author Comment

by:PeterLarsen
ID: 2540518
Thank you for your comments !!

This is not what i asked for. This is the way i'm doing it today.

If you take a button - lets say in a size of 100x100 pixels, and you want the hint box to appear when you move the mouse over the left side of the button (x:0-50, y:0-100).

When the OnShowHint event is called you change CursorRect to 0,0,50,100. That should make the hint box to disappear if you move the mouse in the range from x:51 to 100, right ??

What if it was possible to create two THintInfo records and assign the left side of the button to the first THintinfo and the right side of the button to the second THintInfo record. That would be an easy way to control the hint box.

I dont know if thats possible, but ... THintInfo is a record, thats makes it possible to create multiple instance of it. I can see that if i change CursorRect, THintInfo points to a different record in the system.

THintInfo also have the field HintData. But it is not in use anywhere - except if i override "function CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect; override;".
Why is it there (HintData) if i'm not allowed to create my own THintInfo and save a pointer there - like in TTreeWiew ??

Regards
Peter
0
 
LVL 2

Expert Comment

by:hubdog
ID: 2540796
listening
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2541674
Hi Peter,

if you wanna make it right you need a different approach. I have written a control called TColorPickerButton (see my homepage at www.lischke-online.de) which does what you want here too. Instead of having 50 or so buttons for each color, I just maintain a list of rectangles and set the hint rect accordingly. The main question is WHERE to set it :-) Here's the code:

procedure TColorPopup.CMHintShow(var Message: TMessage);

// determine hint message (tooltip) and out-of-hint rect

var Index: Integer;
    r, g, b: Byte;
    Colors: TCombArray;

begin
  Colors := nil;
  with TCMHintShow(Message) do
  begin
    if not TColorPickerButton(Owner).ShowHint then Message.Result := 1
                                              else
    begin
      with HintInfo^ do
      begin
        // show that we want a hint
        Result := 0;
        // predefined colors always get their names as tooltip
        if FHoverIndex >= 0 then
        begin
          GetCellRect(FHoverIndex, CursorRect);
          if FHoverIndex < DefaultColorCount then HintStr := DefaultColors[FHoverIndex].Name
                                             else HintStr := SysColors[FHoverIndex - DefaultColorCount].Name;
        end
        else
          // both special cells get their hint either from the application by
          // means of the OnHint event or the hint string of the owner control
          if (FHoverIndex = DefaultCell) or
             (FHoverIndex = CustomCell) then
          begin
            HintStr := GetHint(FHoverIndex);
            if HintStr = '' then HintStr := TColorPickerButton(Owner).Hint
                            else
            begin
              // if the application supplied a hint by event then deflate the cursor rect
              // to the belonging button
              if FHoverIndex = DefaultCell then CursorRect := FDefaultTextRect
                                           else CursorRect := FCustomTextRect;
            end;
          end
          else
          begin
            // well, mouse is not hovering over one of the buttons, now check for
            // the ramp and the custom color areas
            if PtInRect(FSliderRect, Point(CursorPos.X, CursorPos.Y)) then
            begin
              // in case of the intensity slider we show the current intensity
              HintStr := Format('Intensity: %d%%', [Round(100 * FCenterIntensity)]);
              CursorRect := Rect(FSliderRect.Left, CursorPos.Y - 2,
                                 FSliderRect.Right, CursorPos.Y + 2);
              HintPos := ClientToScreen(Point(FSliderRect.Right, CursorPos.Y - 8));
              HideTimeout := 5000;
              CursorRect := Rect(FSliderRect.Left, CursorPos.Y,
                                 FSliderRect.Right, CursorPos.Y);
            end
            else
            begin
              Index := -1;
              if PtInRect(FBWCombRect, Point(CursorPos.X, CursorPos.Y)) then
              begin
                // considering black&white area...
                if csLButtonDown in ControlState then Index := -(FCustomIndex + 1)
                                                 else Index := FindBWArea(CursorPos.X, CursorPos.Y);
                Colors := FBWCombs;
              end
              else
                if PtInRect(FColorCombRect, Point(CursorPos.X, CursorPos.Y)) then
                begin
                  // considering color comb area...
                  if csLButtonDown in ControlState then Index := FCustomIndex - 1
                                                   else Index := FindColorArea(CursorPos.X, CursorPos.Y);
                  Colors := FColorCombs;
                end;

              if (Index > -1) and (Colors <> nil) then
              begin
                with Colors[Index] do
                begin
                  r := GetRValue(Color);
                  g := GetGValue(Color);
                  b := GetBValue(Color);
                end;
                HintStr := Format('red: %d, green: %d, blue: %d', [r, g, b]);
                HideTimeout := 5000;
              end
              else HintStr := GetHint(NoCell);

              // make the hint follow the mouse
              CursorRect := Rect(CursorPos.X, CursorPos.Y,
                                 CursorPos.X, CursorPos.Y);
            end;
          end;
      end;
    end;
  end;
end;


This way you don't need to store several hint records but just retrieve what's need on demand (and here also an application callback is provided to get a specific hint string or the code uses the control's hint string if needed).

The hint data pointer can only be used in descentants of THintWindow. I used this stuff for my virtual tree control which needs to show wide string (Unicode) hints and I can't pass these via the normal hint string (so I do it via the hint data pointer).

Ciao, Mike
0
 
LVL 3

Expert Comment

by:gandalf_the_white
ID: 2542324
listening...
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 2

Author Comment

by:PeterLarsen
ID: 2545668
Thank you for your time.

Your samples are very fine but i already know how to do that.
Maybe there are no answer to my question.

In exchange for your time i can offer you a hint component - if you like.

When this component i placed on a form, it will take control over the applications hint window - re-shape it or what else you like to do with it. It also include the possibilities to add a picture to the hint window.

Regards and again - thanks for participating.
Peter
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2545715
Mmh, your question was how to create several hint records at run time. As this is without true sense I showed you how to use the hint stuff correctly. If you know all this, then why have you asked your original question, although it is obvious that this makes no sense?

Time wasted... :-/

Ciao, Mike
0
 
LVL 2

Author Comment

by:PeterLarsen
ID: 2545807
Hi Mike,

Again - i'm very sorry. Please dont say that you have wasted your time - i dont think you'r doing this for the points.

If you think something is possible, and it turns out that it is not - i may seem that it is a waste of time - but i dont think it is.

I know that you (and the others experts) have spent some time with this and therefore i also want to give something back to you.

Regards
Peter
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2545832
When I say I wasted my time then I mean that I made the wrong assumptions and put my working power/time into this without true interest of you (or any other, for that matter).

Don't care about sending your hint control. I prefer the system standard and if I need more information about a particular item then I consult the help file (usually, if there's one ;-)).

Ciao, Mike

0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2546015
0
 
LVL 2

Author Comment

by:PeterLarsen
ID: 2549901
I would like to keep this discussion at EE. To do that i have to accept one of your comments.

ZifNab was there first, so if you all can agree with this i will accept he's answer.

/Peter
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2550165
I don't mind :-). You could also restart a new q'n.
0
 
LVL 2

Author Comment

by:PeterLarsen
ID: 2557110
Nee ZifNab, I dont think i get closer to the answer by forming the lines into a new question.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.

920 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

16 Experts available now in Live!

Get 1:1 Help Now