pngextra.pas 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. unit pngextra;
  2. interface
  3. uses
  4. Windows, Graphics, Messages, SysUtils, Classes, Controls, pngimage, Buttons,
  5. ExtCtrls;
  6. type
  7. TPNGButtonStyle = (pbsDefault, pbsFlat, pbsNoFrame);
  8. TPNGButtonLayout = (pbsImageAbove, pbsImageBellow, pbsImageLeft,
  9. pbsImageRight);
  10. TPNGButtonState = (pbsNormal, pbsDown, pbsDisabled);
  11. TPNGButton = class(TGraphicControl)
  12. private
  13. {Holds the property values}
  14. fButtonStyle: TPNGButtonStyle;
  15. fMouseOverControl: Boolean;
  16. FCaption: String;
  17. FButtonLayout: TPNGButtonLayout;
  18. FButtonState: TPNGButtonState;
  19. FImageDown: TPNGObject;
  20. fImageNormal: TPNGObject;
  21. fImageDisabled: TPNGObject;
  22. fImageOver: TPNGObject;
  23. fOnMouseEnter, fOnMouseExit: TNotifyEvent;
  24. {Procedures for setting the property values}
  25. procedure SetButtonStyle(const Value: TPNGButtonStyle);
  26. procedure SetCaption(const Value: String);
  27. procedure SetButtonLayout(const Value: TPNGButtonLayout);
  28. procedure SetButtonState(const Value: TPNGButtonState);
  29. procedure SetImageNormal(const Value: TPNGObject);
  30. procedure SetImageDown(const Value: TPNGObject);
  31. procedure SetImageOver(const Value: TPNGObject);
  32. published
  33. {Published properties}
  34. property Font;
  35. property Visible;
  36. property ButtonLayout: TPNGButtonLayout read FButtonLayout write SetButtonLayout;
  37. property Caption: String read FCaption write SetCaption;
  38. property ImageNormal: TPNGObject read fImageNormal write SetImageNormal;
  39. property ImageDown: TPNGObject read FImageDown write SetImageDown;
  40. property ImageOver: TPNGObject read FImageOver write SetImageOver;
  41. property ButtonStyle: TPNGButtonStyle read fButtonStyle
  42. write SetButtonStyle;
  43. property Enabled;
  44. property ParentShowHint;
  45. property ShowHint;
  46. {Default events}
  47. property OnMouseDown;
  48. property OnClick;
  49. property OnMouseUp;
  50. property OnMouseMove;
  51. property OnDblClick;
  52. property OnMouseEnter: TNotifyEvent read fOnMouseEnter write fOnMouseEnter;
  53. property OnMouseExit: TNotifyEvent read fOnMouseExit write fOnMouseExit;
  54. public
  55. {Public properties}
  56. property ButtonState: TPNGButtonState read FButtonState write SetButtonState;
  57. protected
  58. {Being painted}
  59. procedure Paint; override;
  60. {Clicked}
  61. procedure Click; override;
  62. {Mouse pressed}
  63. procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  64. X, Y: Integer); override;
  65. procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  66. X, Y: Integer); override;
  67. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  68. {Mouse entering or leaving}
  69. procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  70. procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  71. {Being enabled or disabled}
  72. procedure CMEnabledChanged(var Message: TMessage);
  73. message CM_ENABLEDCHANGED;
  74. public
  75. {Returns if the mouse is over the control}
  76. property IsMouseOver: Boolean read fMouseOverControl;
  77. {Constructor and destructor}
  78. constructor Create(AOwner: TComponent); override;
  79. destructor Destroy; override;
  80. end;
  81. procedure Register;
  82. procedure MakeImageHalfTransparent(Source, Dest: TPNGObject);
  83. implementation
  84. procedure Register;
  85. begin
  86. RegisterComponents('Samples', [TPNGButton]);
  87. end;
  88. procedure MakeImageHalfTransparent(Source, Dest: TPNGObject);
  89. var
  90. i, j: Integer;
  91. begin
  92. Dest.Assign(Source);
  93. Dest.CreateAlpha;
  94. if (Dest.Header.ColorType <> COLOR_PALETTE) then
  95. for j := 0 to Source.Height - 1 do
  96. for i := 0 to Source.Width - 1 do
  97. Dest.AlphaScanline[j]^[i] := Dest.AlphaScanline[j]^[i] div 3;
  98. end;
  99. {TPNGButton implementation}
  100. {Being created}
  101. constructor TPNGButton.Create(AOwner: TComponent);
  102. begin
  103. {Calls ancestor}
  104. inherited Create(AOwner);
  105. {Creates the TPNGObjects}
  106. fImageNormal := TPNGObject.Create;
  107. fImageDown := TPNGObject.Create;
  108. fImageDisabled := TPNGObject.Create;
  109. fImageOver := TPNGObject.Create;
  110. {Initial properties}
  111. ControlStyle := ControlStyle + [csCaptureMouse];
  112. SetBounds(Left, Top, 23, 23);
  113. fMouseOverControl := False;
  114. fButtonLayout := pbsImageAbove;
  115. fButtonState := pbsNormal
  116. end;
  117. destructor TPNGButton.Destroy;
  118. begin
  119. {Frees the TPNGObject}
  120. fImageNormal.Free;
  121. fImageDown.Free;
  122. fImageDisabled.Free;
  123. fImageOver.Free;
  124. {Calls ancestor}
  125. inherited Destroy;
  126. end;
  127. {Being enabled or disabled}
  128. procedure TPNGButton.CMEnabledChanged(var Message: TMessage);
  129. begin
  130. if not Enabled then MakeImageHalfTransparent(fImageNormal, fImageDisabled);
  131. if Enabled then ButtonState := pbsNormal else ButtonState := pbsDisabled
  132. end;
  133. {Returns the largest number}
  134. function Max(A, B: Integer): Integer;
  135. begin
  136. if A > B then Result := A else Result := B
  137. end;
  138. {Button being painted}
  139. procedure TPNGButton.Paint;
  140. const
  141. Slide: Array[false..true] of Integer = (0, 2);
  142. var
  143. Area: TRect;
  144. TextSize, ImageSize: TSize;
  145. TextPos, ImagePos: TPoint;
  146. Image: TPNGObject;
  147. Pushed: Boolean;
  148. begin
  149. {Prepares the canvas}
  150. Canvas.Font.Assign(Font);
  151. {Determines if the button is pushed}
  152. Pushed := (ButtonState = pbsDown) and IsMouseOver;
  153. {Determines the image to use}
  154. if (Pushed) and not fImageDown.Empty then
  155. Image := fImageDown
  156. else if IsMouseOver and not fImageOver.Empty and Enabled then
  157. Image := fImageOver
  158. else if (ButtonState = pbsDisabled) and not fImageDisabled.Empty then
  159. Image := fImageDisabled
  160. else
  161. Image := fImageNormal;
  162. {Get the elements size}
  163. ImageSize.cx := Image.Width;
  164. ImageSize.cy := Image.Height;
  165. Area := ClientRect;
  166. if Caption <> '' then
  167. begin
  168. TextSize := Canvas.TextExtent(Caption);
  169. ImageSize.cy := ImageSize.Cy + 4;
  170. end else FillChar(TextSize, SizeOf(TextSize), #0);
  171. {Set the elements position}
  172. ImagePos.X := (Width - ImageSize.cx) div 2 + Slide[Pushed];
  173. TextPos.X := (Width - TextSize.cx) div 2 + Slide[Pushed];
  174. TextPos.Y := (Height - TextSize.cy) div 2;
  175. ImagePos.Y := (Height - ImageSize.cy) div 2;
  176. case ButtonLayout of
  177. pbsImageAbove: begin
  178. ImagePos.Y := (Height - ImageSize.cy - TextSize.cy) div 2;
  179. TextPos.Y := ImagePos.Y + ImageSize.cy;
  180. end;
  181. pbsImageBellow: begin
  182. TextPos.Y := (Height - ImageSize.cy - TextSize.cy) div 2;
  183. ImagePos.Y := TextPos.Y + TextSize.cy;
  184. end;
  185. pbsImageLeft: begin
  186. ImagePos.X := (Width - ImageSize.cx - TextSize.cx) div 2;
  187. TextPos.X := ImagePos.X + ImageSize.cx + 5;
  188. end;
  189. pbsImageRight: begin
  190. TextPos.X := (Width - ImageSize.cx - TextSize.cx) div 2;;
  191. ImagePos.X := TextPos.X + TextSize.cx + 5;
  192. end
  193. end;
  194. ImagePos.Y := ImagePos.Y + Slide[Pushed];
  195. TextPos.Y := TextPos.Y + Slide[Pushed];
  196. {Draws the border}
  197. if ButtonStyle = pbsFlat then
  198. begin
  199. if ButtonState <> pbsDisabled then
  200. if (Pushed) then
  201. Frame3D(Canvas, Area, clBtnShadow, clBtnHighlight, 1)
  202. else if IsMouseOver or (ButtonState = pbsDown) then
  203. Frame3D(Canvas, Area, clBtnHighlight, clBtnShadow, 1)
  204. end
  205. else if ButtonStyle = pbsDefault then
  206. DrawButtonFace(Canvas, Area, 1, bsNew, TRUE, Pushed, FALSE);
  207. {Draws the elements}
  208. Canvas.Brush.Style := bsClear;
  209. Canvas.Draw(ImagePos.X, ImagePos.Y, Image);
  210. if ButtonState = pbsDisabled then Canvas.Font.Color := clGrayText;
  211. Canvas.TextRect(Area, TextPos.X, TextPos.Y, Caption)
  212. end;
  213. {Changing the button Layout property}
  214. procedure TPNGButton.SetButtonLayout(const Value: TPNGButtonLayout);
  215. begin
  216. FButtonLayout := Value;
  217. Repaint
  218. end;
  219. {Changing the button state property}
  220. procedure TPNGButton.SetButtonState(const Value: TPNGButtonState);
  221. begin
  222. FButtonState := Value;
  223. Repaint
  224. end;
  225. {Changing the button style property}
  226. procedure TPNGButton.SetButtonStyle(const Value: TPNGButtonStyle);
  227. begin
  228. fButtonStyle := Value;
  229. Repaint
  230. end;
  231. {Changing the caption property}
  232. procedure TPNGButton.SetCaption(const Value: String);
  233. begin
  234. FCaption := Value;
  235. Repaint
  236. end;
  237. {Changing the image property}
  238. procedure TPNGButton.SetImageNormal(const Value: TPNGObject);
  239. begin
  240. fImageNormal.Assign(Value);
  241. MakeImageHalfTransparent(fImageNormal, fImageDisabled);
  242. Repaint
  243. end;
  244. {Setting the down image}
  245. procedure TPNGButton.SetImageDown(const Value: TPNGObject);
  246. begin
  247. FImageDown.Assign(Value);
  248. Repaint
  249. end;
  250. {Setting the over image}
  251. procedure TPNGButton.SetImageOver(const Value: TPNGObject);
  252. begin
  253. fImageOver.Assign(Value);
  254. Repaint
  255. end;
  256. {Mouse pressed}
  257. procedure TPNGButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  258. Y: Integer);
  259. begin
  260. {Changes the state and repaints}
  261. if (ButtonState = pbsNormal) and (Button = mbLeft) then
  262. ButtonState := pbsDown;
  263. {Calls ancestor}
  264. inherited
  265. end;
  266. {Being clicked}
  267. procedure TPNGButton.Click;
  268. begin
  269. if ButtonState = pbsDown then ButtonState := pbsNormal;
  270. inherited Click;
  271. end;
  272. {Mouse released}
  273. procedure TPNGButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  274. Y: Integer);
  275. begin
  276. {Changes the state and repaints}
  277. if ButtonState = pbsDown then ButtonState := pbsNormal;
  278. {Calls ancestor}
  279. inherited
  280. end;
  281. {Mouse moving over the control}
  282. procedure TPNGButton.MouseMove(Shift: TShiftState; X, Y: Integer);
  283. begin
  284. {In case cursor is over the button}
  285. if (X >= 0) and (X < ClientWidth) and (Y >= 0) and (Y <= ClientHeight) and
  286. (fMouseOverControl = False) and (ButtonState <> pbsDown) then
  287. begin
  288. fMouseOverControl := True;
  289. Repaint;
  290. end;
  291. {Calls ancestor}
  292. inherited;
  293. end;
  294. {Mouse is now over the control}
  295. procedure TPNGButton.CMMouseEnter(var Message: TMessage);
  296. begin
  297. if Enabled then
  298. begin
  299. if Assigned(fOnMouseEnter) then fOnMouseEnter(Self);
  300. fMouseOverControl := True;
  301. Repaint
  302. end
  303. end;
  304. {Mouse has left the control}
  305. procedure TPNGButton.CMMouseLeave(var Message: TMessage);
  306. begin
  307. if Enabled then
  308. begin
  309. if Assigned(fOnMouseExit) then FOnMouseExit(Self);
  310. fMouseOverControl := False;
  311. Repaint
  312. end
  313. end;
  314. end.