PngSpeedButton.pas 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. //Calculate the position of the PNG glyph
  68. CalcButtonLayout(Canvas, FPngImage, ClientRect, FState = bsDown, Down,
  69. Caption, Layout, Margin, Spacing, GlyphPos, TextPos, DrawTextBiDiModeFlags(0));
  70. PaintRect := Bounds(GlyphPos.X, GlyphPos.Y, FPngImage.Width, FPngImage.Height);
  71. if csLoading in ComponentState then Exit;
  72. if Enabled then
  73. DrawPNG(FPngImage, Canvas, PaintRect, [])
  74. else
  75. DrawPNG(FPngImage, Canvas, PaintRect, FPngOptions);
  76. end;
  77. end;
  78. procedure TPngSpeedButton.Loaded;
  79. begin
  80. inherited Loaded;
  81. CreatePngGlyph;
  82. end;
  83. function TPngSpeedButton.PngImageStored: Boolean;
  84. begin
  85. Result := not FImageFromAction;
  86. end;
  87. procedure TPngSpeedButton.SetPngImage(const Value: TPngImage);
  88. begin
  89. //This is all neccesary, because you can't assign a nil to a TPngImage
  90. if Value = nil then begin
  91. FPngImage.Free;
  92. FPngImage := TPngImage.Create;
  93. end
  94. else begin
  95. FPngImage.Assign(Value);
  96. end;
  97. if HasValidPng then begin
  98. //To work around the gamma-problem
  99. if FPngImage.Header.ColorType in [COLOR_RGB, COLOR_RGBALPHA, COLOR_PALETTE] then
  100. FPngImage.Chunks.RemoveChunk(FPngImage.Chunks.ItemFromClass(TChunkgAMA));
  101. end;
  102. FImageFromAction := False;
  103. CreatePngGlyph;
  104. Repaint;
  105. end;
  106. procedure TPngSpeedButton.SetPngOptions(const Value: TPngOptions);
  107. begin
  108. if FPngOptions <> Value then begin
  109. FPngOptions := Value;
  110. CreatePngGlyph;
  111. Repaint;
  112. end;
  113. end;
  114. procedure TPngSpeedButton.CreatePngGlyph;
  115. var
  116. Bmp: TBitmap;
  117. begin
  118. //Create an empty glyph, just to align the text correctly
  119. Bmp := TBitmap.Create;
  120. try
  121. Bmp.Width := FPngImage.Width;
  122. Bmp.Height := FPngImage.Height;
  123. Bmp.Canvas.Brush.Color := clBtnFace;
  124. Bmp.Canvas.FillRect(Rect(0, 0, Bmp.Width, Bmp.Height));
  125. Glyph.Assign(Bmp);
  126. NumGlyphs := 1;
  127. finally
  128. Bmp.Free;
  129. end;
  130. end;
  131. function TPngSpeedButton.HasValidPng: Boolean;
  132. begin
  133. Result := (FPngImage <> nil) and not FPngImage.Empty;
  134. end;
  135. end.