How do I ensure a balloon hint that I want to associate with a listview item is properly positioned so that it is next to the item in question, and always shows the full ballon text on screen?
For example, if I enter an invalid character when editing a file name in Windows Explorer, a balloon pops up saying what the invalid characters are. The entire balloon is always on screen even if the list item is near a screen edge or partially off screen. The tail is always positioned at the middle bottom of the list item. The bubble is usually to the bottom right of the tail, but may be above it or to the left if the list item is near the bottom and/or right edges of the screen.
Primarily, I am unable to get the bubble and tail to stay close to the list item.
procedure TForm1.ListEdited(Sender: TObject; Item: TListItem;
var S: string);
var
AHint: string;
R: TRect;
B : TBalloonHint;
begin
if TRegEx.IsMatch(S, '[\\/:*?"<>|]') then
begin
AHint := 'A file name cannot contain any of the following' + sLineBreak +
'characters: \/:*?"<>|';
R := Item.DisplayRect(drBounds);
R.TopLeft := ClientToScreen(R.TopLeft);
R.BottomRight := ClientToScreen(R.BottomRight);
B := TBalloonHint.Create(Self);
B.Description := AHint;
B.HideAfter := 5000;
B.ShowHint(R);
S := TRegEx.Replace(S, '[\\/:*?"<>|]', '');
end;
end;
I've tried the various overloads of ShowHint, as well as the JEDI balloon hint component. I've also adjusted the Top property of the rectangle, which may position the balloon better when the item is in a certain area of the screen, but the ballon is then off position when the item is on some other part of the screen.
Delphi 10.3 Rio, Win 7 x64.
DisplayRect
gives client coordinates relative to the listview containing the item, not the form. Hence when converting to screen coordinates, you have to use the listview as the base, not the form:
R := Item.DisplayRect(drBounds);
R.TopLeft := ListView1.ClientToScreen(R.TopLeft); // <--
R.BottomRight := ListView1.ClientToScreen(R.BottomRight); // <--