-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMaxLogic.BalloonHelper.pas
More file actions
186 lines (152 loc) · 4.82 KB
/
Copy pathMaxLogic.BalloonHelper.pas
File metadata and controls
186 lines (152 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
unit MaxLogic.BalloonHelper;
{
How to use the normal TBalloonHint
- put a Edit1 on form
- put Balloonhint1 on the form
- set Edit1 .hint to some text
- set Edit1.customhint := Ballonhint >> better set TForm.customHint to balloonhint1
- enable edit1.showhint := true; >> or better do it for the form itself
- add Timagelist
- add an image to timagelist
- add timagelist to balloonhint1
set the edit1.hint like this:
Hello|How are you today|5
will have
a title of "Hello"
body text of "How are you today"
and the 5th image in the list }
interface
uses
windows, classes, sysUtils, controls, ExtCtrls,
StdCtrls, generics.collections, maxWndSubClassing, messages, forms,
MaxLogic.BalloonDefaultImageList;
Type
TBalloonHelper = class(TComponent)
private const
cHideAfter = 5000;
private
FBalloonHint: TBalloonHint;
fFormSubClassing: TWndSubClass;
function GetBalloonHint: TBalloonHint;
function GetParentFormWnd(wc: TWinControl): hwnd;
class function GetParentForm(wc: TWinControl): TForm;
procedure MsgHideBalloon(var Msg: messages.TMessage; var PrevendDefaultHandler: boolean);
public
constructor Create(aOwner: TComponent);
destructor Destroy; override;
Procedure ShowBalloonHint(FocusOnControl: TWinControl; const atitle, adescription: string; HideAfter: integer = cHideAfter; aImageIndex: integer = 0);
class Procedure ShowBalloonHint2(FocusOnControl: TWinControl; const atitle, adescription: string; aImageIndex: integer = 0);
property BalloonHint: TBalloonHint read GetBalloonHint;
end;
implementation
{ TBalloonHelper }
constructor TBalloonHelper.Create(aOwner: TComponent);
begin
inherited;
end;
destructor TBalloonHelper.Destroy;
begin
if assigned(fFormSubClassing) then
freeAndNIL(fFormSubClassing);
if assigned(FBalloonHint) then
freeAndNIL(FBalloonHint);
inherited;
end;
function TBalloonHelper.GetBalloonHint: TBalloonHint;
begin
if not assigned(FBalloonHint) then
begin
FBalloonHint := TBalloonHint.Create(application.mainform);
// FBalloonHint.style := bhsBalloon;
// FBalloonHint.style := bhsStandard;
FBalloonHint.HideAfter := cHideAfter;
FBalloonHint.Delay := 0;
FBalloonHint.Images := TImageListForBalloonForm.Instance.ImageList1;
FBalloonHint.ImageIndex := 0;
end;
result := FBalloonHint;
end;
procedure TBalloonHelper.ShowBalloonHint(FocusOnControl: TWinControl; const atitle, adescription: string; HideAfter: integer; aImageIndex: integer);
var
r: TRect;
FormWnd: hwnd;
begin
r := rect(0, 0, FocusOnControl.width, FocusOnControl.height);
r.TopLeft := FocusOnControl.ClientToScreen(r.TopLeft);
r.BottomRight := FocusOnControl.ClientToScreen(r.BottomRight);
BalloonHint.Description := adescription + sLineBreak;
BalloonHint.Title := atitle;
BalloonHint.HideAfter := HideAfter;
BalloonHint.ImageIndex := aImageIndex;
if assigned(fFormSubClassing) then
freeAndNIL(fFormSubClassing);
FormWnd := GetParentFormWnd(FocusOnControl);
if FormWnd <> 0 then
begin
fFormSubClassing := TWndSubClass.Create(self);
fFormSubClassing.OnMessage := MsgHideBalloon;
fFormSubClassing.HookedWnd := FormWnd;
end;
FBalloonHint.ShowHint(r);
end;
class function TBalloonHelper.GetParentForm(wc: TWinControl): TForm;
var
c: TWinControl;
begin
result := nil;
c := wc;
while c <> nil do
begin
if (c.parent = nil) and (c is TForm) then
exit(c as TForm);
c := c.parent;
end;
end;
class procedure TBalloonHelper.ShowBalloonHint2(FocusOnControl: TWinControl; const atitle, adescription: string; aImageIndex: integer = 0);
const
cDefaultname = 'maxBalloonHelperDefaultInstance';
var
f: TForm;
x: integer;
bl: TBalloonHelper;
begin
// find the top level form
f := GetParentForm(FocusOnControl);
if f = nil then
raise Exception.Create('could not find parent form');
// find if there is an instance of a default balloon heler already
bl := nil;
for x := f.ComponentCount - 1 downto 0 do
if (f.Components[x] is TBalloonHelper) and (f.Components[x].Name = cDefaultname) then
begin
bl := f.Components[x] as TBalloonHelper;
break;
end;
// if there was none, then create it...
if bl = nil then
begin
bl := TBalloonHelper.Create(f);
bl.Name := cDefaultname;
end;
bl.ShowBalloonHint(FocusOnControl, atitle, adescription, cHideAfter, aImageIndex);
end;
function TBalloonHelper.GetParentFormWnd(wc: TWinControl): hwnd;
var
c: TWinControl;
begin
result := 0;
c := wc;
while c <> nil do
begin
if (c.parent = nil) and (c is TForm) then
exit(c.handle);
c := c.parent;
end;
end;
procedure TBalloonHelper.MsgHideBalloon(var Msg: messages.TMessage; var PrevendDefaultHandler: boolean);
begin
if Msg.Msg in [WM_WINDOWPOSCHANGED, WM_ACTIVATEAPP] then
if assigned(FBalloonHint) then
FBalloonHint.HideHint;
end;
end.