PngSpeedButton.pas 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. unit PngSpeedButton;
  2. interface
  3. uses
  4. Windows, Classes, Buttons, pngimage, PngFunctions;
  5. type
  6. TPngSpeedButton = class(TSpeedButton)
  7. private
  8. FPngImage: TPngImage;
  9. FPngOptions: TPngOptions;
  10. FImageFromAction: Boolean;
  11. function PngImageStored: Boolean;
  12. procedure SetPngImage(const Value: TPngImage);
  13. procedure SetPngOptions(const Value: TPngOptions);
  14. procedure CreatePngGlyph;
  15. function HasValidPng: Boolean;
  16. protected
  17. procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
  18. procedure Paint; override;
  19. procedure Loaded; override;
  20. public
  21. constructor Create(AOwner: TComponent); override;
  22. destructor Destroy; override;
  23. published
  24. property PngImage: TPngImage read FPngImage write SetPngImage stored PngImageStored;
  25. property PngOptions: TPngOptions read FPngOptions write SetPngOptions default [pngBlendOnDisabled];
  26. property Glyph stored False;
  27. property NumGlyphs stored False;
  28. end;
  29. implementation
  30. uses
  31. Graphics, ActnList, PngButtonFunctions, PngImageList;
  32. { TPngSpeedButton }
  33. constructor TPngSpeedButton.Create(AOwner: TComponent);
  34. begin
  35. inherited Create(AOwner);
  36. FPngImage := TPngImage.Create;
  37. FPngOptions := [pngBlendOnDisabled];
  38. FImageFromAction := False;
  39. end;
  40. destructor TPngSpeedButton.Destroy;
  41. begin
  42. inherited Destroy;
  43. FPngImage.Free;
  44. end;
  45. procedure TPngSpeedButton.ActionChange(Sender: TObject; CheckDefaults: Boolean);
  46. begin
  47. inherited ActionChange(Sender, CheckDefaults);
  48. if Sender is TCustomAction then
  49. with TCustomAction(Sender) do begin
  50. //Copy image from action's imagelist
  51. if (PngImage.Empty or FImageFromAction) and (ActionList <> nil) and
  52. (ActionList.Images <> nil) and (ImageIndex >= 0) and (ImageIndex <
  53. ActionList.Images.Count) then begin
  54. CopyImageFromImageList(FPngImage, ActionList.Images, ImageIndex);
  55. CreatePngGlyph;
  56. FImageFromAction := True;
  57. end;
  58. end;
  59. end;
  60. procedure TPngSpeedButton.Paint;
  61. var
  62. PaintRect: TRect;
  63. GlyphPos, TextPos: TPoint;
  64. begin
  65. inherited Paint;
  66. if HasValidPng then begin
  67. Canvas.Handle := 0;
  68. Canvas.Font := Font;
  69. //Calculate the position of the PNG glyph
  70. CalcButtonLayout(Canvas, FPngImage, ClientRect, FState = bsDown, Down,
  71. Caption, Layout, Margin, Spacing, GlyphPos, TextPos, DrawTextBiDiModeFlags(0));
  72. PaintRect := Bounds(GlyphPos.X, GlyphPos.Y, FPngImage.Width, FPngImage.Height);
  73. if csLoading in ComponentState then Exit;
  74. if Enabled then
  75. DrawPNG(FPngImage, Canvas, PaintRect, [])
  76. else
  77. DrawPNG(FPngImage, Canvas, PaintRect, FPngOptions);
  78. end;
  79. end;
  80. procedure TPngSpeedButton.Loaded;
  81. begin
  82. inherited Loaded;
  83. CreatePngGlyph;
  84. end;
  85. function TPngSpeedButton.PngImageStored: Boolean;
  86. begin
  87. Result := not FImageFromAction;
  88. end;
  89. procedure TPngSpeedButton.SetPngImage(const Value: TPngImage);
  90. begin
  91. //This is all neccesary, because you can't assign a nil to a TPngImage
  92. if Value = nil then begin
  93. FPngImage.Free;
  94. FPngImage := TPngImage.Create;
  95. end
  96. else begin
  97. FPngImage.Assign(Value);
  98. end;
  99. if HasValidPng then begin
  100. //To work around the gamma-problem
  101. if FPngImage.Header.ColorType in [COLOR_RGB, COLOR_RGBALPHA, COLOR_PALETTE] then
  102. FPngImage.Chunks.RemoveChunk(FPngImage.Chunks.ItemFromClass(TChunkgAMA));
  103. end;
  104. FImageFromAction := False;
  105. CreatePngGlyph;
  106. Repaint;
  107. end;
  108. procedure TPngSpeedButton.SetPngOptions(const Value: TPngOptions);
  109. begin
  110. if FPngOptions <> Value then begin
  111. FPngOptions := Value;
  112. CreatePngGlyph;
  113. Repaint;
  114. end;
  115. end;
  116. procedure TPngSpeedButton.CreatePngGlyph;
  117. var
  118. Bmp: TBitmap;
  119. begin
  120. //Create an empty glyph, just to align the text correctly
  121. Bmp := TBitmap.Create;
  122. try
  123. Bmp.Width := FPngImage.Width;
  124. Bmp.Height := FPngImage.Height;
  125. Bmp.Canvas.Brush.Color := clBtnFace;
  126. Bmp.Canvas.FillRect(Rect(0, 0, Bmp.Width, Bmp.Height));
  127. Glyph.Assign(Bmp);
  128. NumGlyphs := 1;
  129. finally
  130. Bmp.Free;
  131. end;
  132. end;
  133. function TPngSpeedButton.HasValidPng: Boolean;
  134. begin
  135. Result := (FPngImage <> nil) and not FPngImage.Empty;
  136. end;
  137. end.