Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1044
  • Last Modified:

Using THintInfo/THitWindow

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
PeterLarsen
Asked:
PeterLarsen
  • 6
  • 3
  • 3
  • +4
1 Solution
 
PeterLarsenAuthor Commented:
Well, I ment "Using THintInfo/THintWindow"
0
 
rene100Commented:
listening.....
0
 
ZifNabCommented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
intheCommented:
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
 
PeterLarsenAuthor Commented:
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
 
hubdogCommented:
listening
0
 
LischkeCommented:
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
 
gandalf_the_whiteCommented:
listening...
0
 
PeterLarsenAuthor Commented:
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
 
LischkeCommented:
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
 
PeterLarsenAuthor Commented:
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
 
LischkeCommented:
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
 
PeterLarsenAuthor Commented:
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
 
ZifNabCommented:
I don't mind :-). You could also restart a new q'n.
0
 
PeterLarsenAuthor Commented:
Nee ZifNab, I dont think i get closer to the answer by forming the lines into a new question.
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 6
  • 3
  • 3
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now