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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
|
unit pngextra;
interface
uses
Windows, Graphics, Messages, SysUtils, Classes, Controls, pngimage, Buttons,
ExtCtrls;
type
TPNGButtonStyle = (pbsDefault, pbsFlat, pbsNoFrame);
TPNGButtonLayout = (pbsImageAbove, pbsImageBellow, pbsImageLeft,
pbsImageRight);
TPNGButtonState = (pbsNormal, pbsDown, pbsDisabled);
TPNGButton = class(TGraphicControl)
private
{Holds the property values}
fButtonStyle: TPNGButtonStyle;
fMouseOverControl: Boolean;
FCaption: String;
FButtonLayout: TPNGButtonLayout;
FButtonState: TPNGButtonState;
FImageDown: TPNGObject;
fImageNormal: TPNGObject;
fImageDisabled: TPNGObject;
fImageOver: TPNGObject;
fOnMouseEnter, fOnMouseExit: TNotifyEvent;
{Procedures for setting the property values}
procedure SetButtonStyle(const Value: TPNGButtonStyle);
procedure SetCaption(const Value: String);
procedure SetButtonLayout(const Value: TPNGButtonLayout);
procedure SetButtonState(const Value: TPNGButtonState);
procedure SetImageNormal(const Value: TPNGObject);
procedure SetImageDown(const Value: TPNGObject);
procedure SetImageOver(const Value: TPNGObject);
published
{Published properties}
property Font;
property Visible;
property ButtonLayout: TPNGButtonLayout read FButtonLayout write SetButtonLayout;
property Caption: String read FCaption write SetCaption;
property ImageNormal: TPNGObject read fImageNormal write SetImageNormal;
property ImageDown: TPNGObject read FImageDown write SetImageDown;
property ImageOver: TPNGObject read FImageOver write SetImageOver;
property ButtonStyle: TPNGButtonStyle read fButtonStyle
write SetButtonStyle;
property Enabled;
property ParentShowHint;
property ShowHint;
{Default events}
property OnMouseDown;
property OnClick;
property OnMouseUp;
property OnMouseMove;
property OnDblClick;
property OnMouseEnter: TNotifyEvent read fOnMouseEnter write fOnMouseEnter;
property OnMouseExit: TNotifyEvent read fOnMouseExit write fOnMouseExit;
public
{Public properties}
property ButtonState: TPNGButtonState read FButtonState write SetButtonState;
protected
{Being painted}
procedure Paint; override;
{Clicked}
procedure Click; override;
{Mouse pressed}
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
{Mouse entering or leaving}
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
{Being enabled or disabled}
procedure CMEnabledChanged(var Message: TMessage);
message CM_ENABLEDCHANGED;
public
{Returns if the mouse is over the control}
property IsMouseOver: Boolean read fMouseOverControl;
{Constructor and destructor}
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
procedure Register;
procedure MakeImageHalfTransparent(Source, Dest: TPNGObject);
implementation
procedure Register;
begin
RegisterComponents('Samples', [TPNGButton]);
end;
procedure MakeImageHalfTransparent(Source, Dest: TPNGObject);
var
i, j: Integer;
begin
Dest.Assign(Source);
Dest.CreateAlpha;
if (Dest.Header.ColorType <> COLOR_PALETTE) then
for j := 0 to Source.Height - 1 do
for i := 0 to Source.Width - 1 do
Dest.AlphaScanline[j]^[i] := Dest.AlphaScanline[j]^[i] div 3;
end;
{TPNGButton implementation}
{Being created}
constructor TPNGButton.Create(AOwner: TComponent);
begin
{Calls ancestor}
inherited Create(AOwner);
{Creates the TPNGObjects}
fImageNormal := TPNGObject.Create;
fImageDown := TPNGObject.Create;
fImageDisabled := TPNGObject.Create;
fImageOver := TPNGObject.Create;
{Initial properties}
ControlStyle := ControlStyle + [csCaptureMouse];
SetBounds(Left, Top, 23, 23);
fMouseOverControl := False;
fButtonLayout := pbsImageAbove;
fButtonState := pbsNormal
end;
destructor TPNGButton.Destroy;
begin
{Frees the TPNGObject}
fImageNormal.Free;
fImageDown.Free;
fImageDisabled.Free;
fImageOver.Free;
{Calls ancestor}
inherited Destroy;
end;
{Being enabled or disabled}
procedure TPNGButton.CMEnabledChanged(var Message: TMessage);
begin
if not Enabled then MakeImageHalfTransparent(fImageNormal, fImageDisabled);
if Enabled then ButtonState := pbsNormal else ButtonState := pbsDisabled
end;
{Returns the largest number}
function Max(A, B: Integer): Integer;
begin
if A > B then Result := A else Result := B
end;
{Button being painted}
procedure TPNGButton.Paint;
const
Slide: Array[false..true] of Integer = (0, 2);
var
Area: TRect;
TextSize, ImageSize: TSize;
TextPos, ImagePos: TPoint;
Image: TPNGObject;
Pushed: Boolean;
begin
{Prepares the canvas}
Canvas.Font.Assign(Font);
{Determines if the button is pushed}
Pushed := (ButtonState = pbsDown) and IsMouseOver;
{Determines the image to use}
if (Pushed) and not fImageDown.Empty then
Image := fImageDown
else if IsMouseOver and not fImageOver.Empty and Enabled then
Image := fImageOver
else if (ButtonState = pbsDisabled) and not fImageDisabled.Empty then
Image := fImageDisabled
else
Image := fImageNormal;
{Get the elements size}
ImageSize.cx := Image.Width;
ImageSize.cy := Image.Height;
Area := ClientRect;
if Caption <> '' then
begin
TextSize := Canvas.TextExtent(Caption);
ImageSize.cy := ImageSize.Cy + 4;
end else FillChar(TextSize, SizeOf(TextSize), #0);
{Set the elements position}
ImagePos.X := (Width - ImageSize.cx) div 2 + Slide[Pushed];
TextPos.X := (Width - TextSize.cx) div 2 + Slide[Pushed];
TextPos.Y := (Height - TextSize.cy) div 2;
ImagePos.Y := (Height - ImageSize.cy) div 2;
case ButtonLayout of
pbsImageAbove: begin
ImagePos.Y := (Height - ImageSize.cy - TextSize.cy) div 2;
TextPos.Y := ImagePos.Y + ImageSize.cy;
end;
pbsImageBellow: begin
TextPos.Y := (Height - ImageSize.cy - TextSize.cy) div 2;
ImagePos.Y := TextPos.Y + TextSize.cy;
end;
pbsImageLeft: begin
ImagePos.X := (Width - ImageSize.cx - TextSize.cx) div 2;
TextPos.X := ImagePos.X + ImageSize.cx + 5;
end;
pbsImageRight: begin
TextPos.X := (Width - ImageSize.cx - TextSize.cx) div 2;;
ImagePos.X := TextPos.X + TextSize.cx + 5;
end
end;
ImagePos.Y := ImagePos.Y + Slide[Pushed];
TextPos.Y := TextPos.Y + Slide[Pushed];
{Draws the border}
if ButtonStyle = pbsFlat then
begin
if ButtonState <> pbsDisabled then
if (Pushed) then
Frame3D(Canvas, Area, clBtnShadow, clBtnHighlight, 1)
else if IsMouseOver or (ButtonState = pbsDown) then
Frame3D(Canvas, Area, clBtnHighlight, clBtnShadow, 1)
end
else if ButtonStyle = pbsDefault then
DrawButtonFace(Canvas, Area, 1, bsNew, TRUE, Pushed, FALSE);
{Draws the elements}
Canvas.Brush.Style := bsClear;
Canvas.Draw(ImagePos.X, ImagePos.Y, Image);
if ButtonState = pbsDisabled then Canvas.Font.Color := clGrayText;
Canvas.TextRect(Area, TextPos.X, TextPos.Y, Caption)
end;
{Changing the button Layout property}
procedure TPNGButton.SetButtonLayout(const Value: TPNGButtonLayout);
begin
FButtonLayout := Value;
Repaint
end;
{Changing the button state property}
procedure TPNGButton.SetButtonState(const Value: TPNGButtonState);
begin
FButtonState := Value;
Repaint
end;
{Changing the button style property}
procedure TPNGButton.SetButtonStyle(const Value: TPNGButtonStyle);
begin
fButtonStyle := Value;
Repaint
end;
{Changing the caption property}
procedure TPNGButton.SetCaption(const Value: String);
begin
FCaption := Value;
Repaint
end;
{Changing the image property}
procedure TPNGButton.SetImageNormal(const Value: TPNGObject);
begin
fImageNormal.Assign(Value);
MakeImageHalfTransparent(fImageNormal, fImageDisabled);
Repaint
end;
{Setting the down image}
procedure TPNGButton.SetImageDown(const Value: TPNGObject);
begin
FImageDown.Assign(Value);
Repaint
end;
{Setting the over image}
procedure TPNGButton.SetImageOver(const Value: TPNGObject);
begin
fImageOver.Assign(Value);
Repaint
end;
{Mouse pressed}
procedure TPNGButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
{Changes the state and repaints}
if (ButtonState = pbsNormal) and (Button = mbLeft) then
ButtonState := pbsDown;
{Calls ancestor}
inherited
end;
{Being clicked}
procedure TPNGButton.Click;
begin
if ButtonState = pbsDown then ButtonState := pbsNormal;
inherited Click;
end;
{Mouse released}
procedure TPNGButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
{Changes the state and repaints}
if ButtonState = pbsDown then ButtonState := pbsNormal;
{Calls ancestor}
inherited
end;
{Mouse moving over the control}
procedure TPNGButton.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
{In case cursor is over the button}
if (X >= 0) and (X < ClientWidth) and (Y >= 0) and (Y <= ClientHeight) and
(fMouseOverControl = False) and (ButtonState <> pbsDown) then
begin
fMouseOverControl := True;
Repaint;
end;
{Calls ancestor}
inherited;
end;
{Mouse is now over the control}
procedure TPNGButton.CMMouseEnter(var Message: TMessage);
begin
if Enabled then
begin
if Assigned(fOnMouseEnter) then fOnMouseEnter(Self);
fMouseOverControl := True;
Repaint
end
end;
{Mouse has left the control}
procedure TPNGButton.CMMouseLeave(var Message: TMessage);
begin
if Enabled then
begin
if Assigned(fOnMouseExit) then FOnMouseExit(Self);
fMouseOverControl := False;
Repaint
end
end;
end.
|