ImageList:

- InsertBitmap improved to add multiple bitmaps from one big
- GetBitmap extended to get Bitmaps with different effects
- add DrawToDC to win32 imagelist to give ability to draw without TCanvas (having only HDC)

TButtonGlyph:
- use internal imagelist to perform different state drawing of glyph

TBitBtn:
- send ButtonGlyph to widgetset instead of TBitmap to perform different state drawing

git-svn-id: trunk@12779 -
This commit is contained in:
paul 2007-11-08 08:36:03 +00:00
parent 95f6b902b7
commit ee80b0fd46
12 changed files with 225 additions and 181 deletions

View File

@ -38,20 +38,27 @@ interface
{$endif} {$endif}
uses uses
Types, Classes, SysUtils, LCLType, LCLProc, LCLIntf, LCLStrConsts, Types, Classes, SysUtils, Math, LCLType, LCLProc, LCLIntf, LCLStrConsts,
GraphType, Graphics, ImgList, ActnList, Controls, StdCtrls, LMessages, Forms, GraphType, Graphics, ImgList, ActnList, Controls, StdCtrls, LMessages, Forms,
Themes, Menus{for ShortCut procedures}, LResources; Themes, Menus{for ShortCut procedures}, LResources;
type type
{ TButton } { TButton }
TButtonLayout = (blGlyphLeft, blGlyphRight, blGlyphTop, blGlyphBottom); TButtonLayout =
TButtonState = ( (
blGlyphLeft,
blGlyphRight,
blGlyphTop,
blGlyphBottom
);
TButtonState =
(
bsUp, // button is up bsUp, // button is up
bsDisabled, // button disabled (grayed) bsDisabled, // button disabled (grayed)
bsDown, // button is down bsDown, // button is down
bsExclusive // button is the only down in his group bsExclusive // button is the only down in his group
); );
{TNumGlyphs holds the number of glyphs in an image. {TNumGlyphs holds the number of glyphs in an image.
We restrict it to 4 to stay compatible but we don't NEED to. We restrict it to 4 to stay compatible but we don't NEED to.
@ -68,6 +75,7 @@ type
TButtonGlyph = class TButtonGlyph = class
private private
FImages: TCustomImageList;
FOriginal: TBitmap; FOriginal: TBitmap;
FNumGlyphs: TNumGlyphs; FNumGlyphs: TNumGlyphs;
FOnChange: TNotifyEvent; FOnChange: TNotifyEvent;
@ -78,11 +86,13 @@ type
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
procedure GetImageIndexAndEffect(State: TButtonState; var AIndex: Integer; var AEffect: TGraphicsDrawEffect);
function Draw(Canvas: TCanvas; const Client: TRect; const Offset: TPoint; function Draw(Canvas: TCanvas; const Client: TRect; const Offset: TPoint;
State: TButtonState; Transparent: Boolean; State: TButtonState; Transparent: Boolean;
BiDiFlags: Longint): TRect; BiDiFlags: Longint): TRect;
property Glyph: TBitmap read FOriginal write SetGlyph; property Glyph: TBitmap read FOriginal write SetGlyph;
property NumGlyphs: TNumGlyphs read FNumGlyphs write SetNumGlyphs; property NumGlyphs: TNumGlyphs read FNumGlyphs write SetNumGlyphs;
property Images: TCustomImageList read FImages;
public public
property OnChange: TNotifyEvent read FOnChange write FOnChange; property OnChange: TNotifyEvent read FOnChange write FOnChange;
end; end;
@ -98,7 +108,6 @@ type
TCustomBitBtn = class(TCustomButton) TCustomBitBtn = class(TCustomButton)
private private
FButtonGlyph: TButtonGlyph;
FKind: TBitBtnKind; FKind: TBitBtnKind;
FLayout: TButtonLayout; FLayout: TButtonLayout;
FMargin: integer; FMargin: integer;
@ -114,10 +123,10 @@ type
procedure SetNumGlyphs(AValue: Integer); procedure SetNumGlyphs(AValue: Integer);
Procedure SetSpacing(AValue: Integer); Procedure SetSpacing(AValue: Integer);
procedure RealizeKind; procedure RealizeKind;
procedure DrawGlyph;
//Return the caption associated with the aKind value. //Return the caption associated with the aKind value.
function GetCaptionOfKind(aKind: TBitBtnKind): String; function GetCaptionOfKind(aKind: TBitBtnKind): String;
protected protected
FButtonGlyph: TButtonGlyph;
procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
procedure GlyphChanged(Sender: TObject); procedure GlyphChanged(Sender: TObject);
procedure InitializeWnd; override; procedure InitializeWnd; override;

View File

@ -196,7 +196,8 @@ type
procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; AEnabled: Boolean = True); overload; procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; AEnabled: Boolean = True); overload;
procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; ADrawEffect: TGraphicsDrawEffect); overload; procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; ADrawEffect: TGraphicsDrawEffect); overload;
procedure FillDescription(out ADesc: TRawImageDescription); procedure FillDescription(out ADesc: TRawImageDescription);
procedure GetBitmap(Index: Integer; Image: TBitmap); procedure GetBitmap(Index: Integer; Image: TBitmap); overload;
procedure GetBitmap(Index: Integer; Image: TBitmap; AEffect: TGraphicsDrawEffect); overload;
procedure GetRawImage(Index: Integer; out Image: TRawImage); procedure GetRawImage(Index: Integer; out Image: TRawImage);
{$ifdef IMGLIST_KEEP_EXTRA} {$ifdef IMGLIST_KEEP_EXTRA}
procedure GetInternalImage(Index: integer; var Image, Mask: TBitmap; procedure GetInternalImage(Index: integer; var Image, Mask: TBitmap;

View File

@ -84,13 +84,8 @@ procedure TCustomBitBtn.GlyphChanged(Sender: TObject);
begin begin
if HandleAllocated if HandleAllocated
then begin then begin
if NumGlyphs > 1 then begin TWSBitBtnClass(WidgetSetClass).SetGlyph(Self, FButtonGlyph);
DrawGlyph; end;
TWSBitBtnClass(WidgetSetClass).SetGlyph(Self, FMultiGlyph);
end
else
TWSBitBtnClass(WidgetSetClass).SetGlyph(Self, Glyph);
end;
InvalidatePreferredSize; InvalidatePreferredSize;
AdjustSize; AdjustSize;
end; end;
@ -227,34 +222,6 @@ begin
end; end;
end; end;
procedure TCustomBitBtn.DrawGlyph;
var
AGlyphRect: TRect;
AOffset: TPoint;
AState :TButtonState;
begin
if FButtonGlyph.FOriginal = nil then exit;
AOffset.X:= 0;
AOffset.Y:= 0;
AGlyphRect.Left :=0;
AGlyphRect.Top := 0;
AGlyphRect.Bottom:= FButtonGlyph.Glyph.Height;
if NumGlyphs > 1 then
AGlyphRect.Right:= FButtonGlyph.Glyph.Width div NumGlyphs
else
AGlyphRect.Right:= FButtonGlyph.Glyph.Width;
if FMultiGlyph =nil then FMultiGlyph := TBitmap.Create;
FMultiGlyph.Height:=AGlyphRect.Bottom;
FMultiGlyph.Width:=AGlyphRect.Right;
FMultiGlyph.Canvas.Brush.Color:=Color;
FMultiGlyph.Canvas.FillRect(AGlyphRect);
if Enabled then AState := bsUp
else AState := bsDisabled;
FButtonGlyph.Draw(FMultiGlyph.Canvas,AGlyphRect,AOffset,AState,True,0);
end;
{ Return the caption associated with the akind value. { Return the caption associated with the akind value.
This function replaces BitBtnCaption const because the localizing This function replaces BitBtnCaption const because the localizing
dont work with an const array } dont work with an const array }
@ -280,12 +247,7 @@ end;
procedure TCustomBitBtn.InitializeWnd; procedure TCustomBitBtn.InitializeWnd;
begin begin
inherited InitializeWnd; inherited InitializeWnd;
if NumGlyphs > 1 then begin TWSBitBtnClass(WidgetSetClass).SetGlyph(Self, FButtonGlyph);
DrawGlyph;
TWSBitBtnClass(WidgetSetClass).SetGlyph(Self, FMultiGlyph);
end
else
TWSBitBtnClass(WidgetSetClass).SetGlyph(Self, Glyph);
TWSBitBtnClass(WidgetSetClass).SetLayout(Self, FLayout); TWSBitBtnClass(WidgetSetClass).SetLayout(Self, FLayout);
TWSBitBtnClass(WidgetSetClass).SetMargin(Self, FMargin); TWSBitBtnClass(WidgetSetClass).SetMargin(Self, FMargin);
TWSBitBtnClass(WidgetSetClass).SetSpacing(Self, FSpacing); TWSBitBtnClass(WidgetSetClass).SetSpacing(Self, FSpacing);

View File

@ -20,10 +20,10 @@
{------------------------------------------------------------------------------} {------------------------------------------------------------------------------}
constructor TButtonGlyph.Create; constructor TButtonGlyph.Create;
begin begin
// Inherited Create;
FOriginal := TBitmap.Create; FOriginal := TBitmap.Create;
FOriginal.Handle := 0; FOriginal.Handle := 0;
FOriginal.OnChange := @GlyphChanged; FOriginal.OnChange := @GlyphChanged;
FImages := TCustomImageList.Create(nil);
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
@ -32,10 +32,39 @@ end;
destructor TButtonGlyph.Destroy; destructor TButtonGlyph.Destroy;
begin begin
FOriginal.Free; FOriginal.Free;
FOriginal:=nil; FOriginal := nil;
FImages.Free;
inherited Destroy; inherited Destroy;
end; end;
procedure TButtonGlyph.GetImageIndexAndEffect(State: TButtonState;
var AIndex: Integer; var AEffect: TGraphicsDrawEffect);
begin
AIndex := 0;
AEffect := gdeNormal;
case State of
bsDisabled:
begin
if NumGlyphs > 1 then
AIndex := 1
else
AEffect := gdeDisabled;
end;
bsDown:
begin
if NumGlyphs > 2 then
AIndex := 2
else
AEffect := gdeShadowed;
end;
bsExclusive:
if NumGlyphs > 3 then
AIndex := 3
else
AEffect := gdeHighlighted;
end;
end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
TButtonGlyph SetGlyph TButtonGlyph SetGlyph
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
@ -43,18 +72,21 @@ procedure TButtonGlyph.SetGlyph(Value : TBitmap);
var var
GlyphCount : integer; GlyphCount : integer;
begin begin
if FOriginal = Value then exit; if FOriginal = Value then
if FOriginal=nil then begin exit;
FOriginal:=TBitmap.Create; if FOriginal = nil then
end; FOriginal := TBitmap.Create;
FOriginal.OnChange:=nil; FOriginal.OnChange := nil;
FOriginal.Assign(Value); FOriginal.Assign(Value);
FOriginal.OnChange := @GlyphChanged; FOriginal.OnChange := @GlyphChanged;
FNumGlyphs:=1; FNumGlyphs := 1;
if (FOriginal <> nil) and (FOriginal.Height > 0) then begin if (FOriginal <> nil) and (FOriginal.Height > 0) then
if FOriginal.Width mod FOriginal.Height = 0 then begin begin
if FOriginal.Width mod FOriginal.Height = 0 then
begin
GlyphCount:= FOriginal.Width div FOriginal.Height; GlyphCount:= FOriginal.Width div FOriginal.Height;
if GlyphCount > 4 then GlyphCount:= 1; if GlyphCount > 4 then
GlyphCount:= 1;
FNumGlyphs:= TNumGlyphs(GlyphCount); FNumGlyphs:= TNumGlyphs(GlyphCount);
end; end;
end; end;
@ -63,14 +95,20 @@ end;
procedure TButtonGlyph.GlyphChanged(Sender: TObject); procedure TButtonGlyph.GlyphChanged(Sender: TObject);
begin begin
FImages.Clear;
FImages.Width := FOriginal.Width div Max(1, FNumGlyphs);
FImages.Height := FOriginal.Height;
FImages.Add(FOriginal, nil);
if Sender = FOriginal then if Sender = FOriginal then
if Assigned(FOnChange) then FOnChange(Self); if Assigned(FOnChange) then
FOnChange(Self);
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
TButtonGlyph Draw TButtonGlyph Draw
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
Function TButtonGlyph.Draw(Canvas: TCanvas; const Client: TRect; function TButtonGlyph.Draw(Canvas: TCanvas; const Client: TRect;
const Offset: TPoint; State: TButtonState; Transparent: Boolean; const Offset: TPoint; State: TButtonState; Transparent: Boolean;
BiDiFlags: Longint): TRect; BiDiFlags: Longint): TRect;
var var
@ -78,53 +116,49 @@ var
gHeight: integer; gHeight: integer;
DestRect, SrcRect: TRect; DestRect, SrcRect: TRect;
ImgID: integer; ImgID: integer;
UseMaskHandle: HBitmap;
src_wh, dst_wh: Integer; src_wh, dst_wh: Integer;
AEffect: TGraphicsDrawEffect;
begin begin
Result:=Client; Result:=Client;
if (FOriginal = nil) then exit; if (FOriginal = nil) then
exit;
gWidth := FOriginal.Width; gWidth := FOriginal.Width;
gHeight := FOriginal.Height; gHeight := FOriginal.Height;
if (gWidth = 0) or (gHeight = 0)
or (Client.Left>=Client.Right) or (Client.Top>=Client.Bottom) then Exit; if (gWidth = 0) or (gHeight = 0) or
(Client.Left >= Client.Right) or (Client.Top >= Client.Bottom) then
Exit;
if NumGlyphs > 1 then if NumGlyphs > 1 then
gWidth := gWidth div NumGlyphs; gWidth := gWidth div NumGlyphs;
ImgID:=0; GetImageIndexAndEffect(State, ImgID, AEffect);
case State of
bsDisabled: if NumGlyphs>1 then ImgID:=1;
bsDown: if NumGlyphs>2 then ImgID:=2;
bsExclusive: if NumGlyphs>3 then ImgID:=3;
end;
SrcRect := Rect((ImgID*gWidth), 0, ((ImgID+1)*gWidth), gHeight); SrcRect := Rect((ImgID * gWidth), 0, ((ImgID+1) * gWidth), gHeight);
DestRect:=Client; DestRect := Client;
Inc(DestRect.Left, Offset.X); Inc(DestRect.Left, Offset.X);
src_wh:=SrcRect.Right-SrcRect.Left; dst_wh:=DestRect.Right-DestRect.Left; src_wh := SrcRect.Right - SrcRect.Left;
if (dst_wh>src_wh) then dst_wh := DestRect.Right - DestRect.Left;
DestRect.Right:=DestRect.Left+src_wh // if window for image is wider
else if (dst_wh<src_wh) then if (dst_wh > src_wh) then
SrcRect.Right:=SrcRect.Left+dst_wh; // if image not fits in their window width DestRect.Right := DestRect.Left+src_wh // if window for image is wider
else
if (dst_wh < src_wh) then
SrcRect.Right := SrcRect.Left + dst_wh; // if image not fits in their window width
Inc(DestRect.Top, Offset.Y); Inc(DestRect.Top, Offset.Y);
src_wh:=SrcRect.Bottom-SrcRect.Top; dst_wh:=DestRect.Bottom-DestRect.Top; src_wh := SrcRect.Bottom - SrcRect.Top;
if (dst_wh>src_wh) then dst_wh := DestRect.Bottom - DestRect.Top;
DestRect.Bottom:=DestRect.Top+src_wh // if window for image is higher
else if (dst_wh<src_wh) then if (dst_wh > src_wh) then
SrcRect.Bottom:=SrcRect.Top+dst_wh; // if image not fits in their window height DestRect.Bottom := DestRect.Top + src_wh // if window for image is higher
else
if (dst_wh < src_wh) then
SrcRect.Bottom := SrcRect.Top + dst_wh; // if image not fits in their window height
//Canvas.CopyRect(DestRect, FOriginal.Canvas, SrcRect) FImages.Draw(Canvas, DestRect.Left, DestRect.Top, ImgID, AEffect);
UseMaskHandle:=FOriginal.MaskHandle;
MaskBlt(Canvas.GetUpdatedHandle([csHandleValid]),
DestRect.Left,DestRect.Top,
DestRect.Right-DestRect.Left,DestRect.Bottom-DestRect.Top,
FOriginal.Canvas.GetUpdatedHandle([csHandleValid]),
SrcRect.Left,SrcRect.Top,
UseMaskHandle,SrcRect.Left,SrcRect.Top);
// ToDo: VCL returns the text rectangle // ToDo: VCL returns the text rectangle
Result:=SrcRect; Result:=SrcRect;
@ -136,7 +170,8 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TButtonGlyph.SetNumGlyphs(Value : TNumGlyphs); procedure TButtonGlyph.SetNumGlyphs(Value : TNumGlyphs);
begin begin
if Value <> FNumGlyphs then begin if Value <> FNumGlyphs then
begin
FNumGlyphs := Value; FNumGlyphs := Value;
GlyphChanged(FOriginal); GlyphChanged(FOriginal);
end; end;

View File

@ -59,6 +59,7 @@ end;
The image is copied. To add it directly use AddDirect. The image is copied. To add it directly use AddDirect.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function TCustomImageList.Add(Image, Mask: TBitmap): Integer; function TCustomImageList.Add(Image, Mask: TBitmap): Integer;
begin begin
{$ifdef IMGLIST_OLDSTYLE} {$ifdef IMGLIST_OLDSTYLE}
@ -629,6 +630,12 @@ end;
Creates a copy of the index'th image. Creates a copy of the index'th image.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TCustomImageList.GetBitmap(Index: Integer; Image: TBitmap); procedure TCustomImageList.GetBitmap(Index: Integer; Image: TBitmap);
begin
GetBitmap(Index, Image, gdeNormal);
end;
procedure TCustomImageList.GetBitmap(Index: Integer; Image: TBitmap;
AEffect: TGraphicsDrawEffect);
{$ifndef IMGLIST_OLDSTYLE} {$ifndef IMGLIST_OLDSTYLE}
var var
RawImg: TRawImage; RawImg: TRawImage;
@ -636,12 +643,14 @@ var
ImgHandle, MskHandle: HBitmap; ImgHandle, MskHandle: HBitmap;
{$endif} {$endif}
begin begin
if (FCount = 0) or (Image = nil) then Exit; if (FCount = 0) or (Image = nil) then Exit;
{$ifdef IMGLIST_OLDSTYLE} {$ifdef IMGLIST_OLDSTYLE}
Image.Assign(TBitMap(FImageList.Items[Index])); Image.Assign(TBitMap(FImageList.Items[Index]));
{$else} {$else}
GetRawImage(Index, RawImg); GetRawImage(Index, RawImg);
RawImg.PerformEffect(AEffect, True);
if not RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle, True) if not RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle, True)
then begin then begin
@ -657,6 +666,8 @@ begin
end; end;
Image.SetHandles(ImgHandle, MskHandle); Image.SetHandles(ImgHandle, MskHandle);
RawImg.FreeData;
{$endif} {$endif}
end; end;
@ -823,6 +834,7 @@ var
R: TRect; R: TRect;
ImgData: PRGBAQuad; ImgData: PRGBAQuad;
msk: THandle; msk: THandle;
i, ACount: Integer;
{$endif} {$endif}
begin begin
if AImage = nil then Exit; if AImage = nil then Exit;
@ -836,11 +848,16 @@ begin
FMaskList.Insert(AIndex,AMask); FMaskList.Insert(AIndex,AMask);
FCount := FImageList.Count; FCount := FImageList.Count;
{$else} {$else}
// todo: add support for multiple images ACount := AImage.Width div Width;
Inc(FCount); if ACount = 0 then
ACount := 1;
Inc(FCount, ACount);
AllocData(FCount); AllocData(FCount);
if AIndex < FCount - 1 if AIndex < FCount - ACount then
then InternalMove(FCount - 1, AIndex, True); begin
for i := 0 to ACount - 1 do
InternalMove(FCount - i - 1, AIndex + i, True);
end;
if AMask = nil if AMask = nil
then begin then begin
@ -849,12 +866,15 @@ begin
else msk := 0; else msk := 0;
end end
else msk := AMask.Handle; else msk := AMask.Handle;
R := Rect(0, 0, FWidth, FHeight);
RawImage_FromBitmap(RawImg, AImage.Handle, msk, R);
ImgData := InternalSetImage(AIndex, RawImg);
if HandleAllocated for i := 0 to ACount - 1 do
then TWSCustomImageListClass(WidgetSetClass).Insert(Self, AIndex, ImgData); begin
R := Rect(FWidth * i, 0, FWidth * (i + 1), FHeight);
RawImage_FromBitmap(RawImg, AImage.Handle, msk, R);
ImgData := InternalSetImage(AIndex + i, RawImg);
if HandleAllocated
then TWSCustomImageListClass(WidgetSetClass).Insert(Self, AIndex + i, ImgData);
end;
{$endif} {$endif}
FChanged := true; FChanged := true;

View File

@ -48,7 +48,7 @@ type
protected protected
public public
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); override; class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TButtonGlyph); override;
class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); override; class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); override;
end; end;
@ -91,11 +91,11 @@ end;
Sets the bitmap of bevel button in Carbon interface Sets the bitmap of bevel button in Carbon interface
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class procedure TCarbonWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; class procedure TCarbonWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn;
const AValue: TBitmap); const AValue: TButtonGlyph);
begin begin
if not CheckHandle(ABitBtn, Self, 'SetGlyph') then Exit; if not CheckHandle(ABitBtn, Self, 'SetGlyph') then Exit;
TCarbonBitBtn(ABitBtn.Handle).SetGlyph(AValue); TCarbonBitBtn(ABitBtn.Handle).SetGlyph(AValue.Glyph);
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------

View File

@ -34,7 +34,7 @@ uses
GLib, Gtk, gdk, Gtk1WSPrivate, GLib, Gtk, gdk, Gtk1WSPrivate,
{$ENDIF} {$ENDIF}
// LCL // LCL
Classes, LCLProc, LCLType, LMessages, Controls, Graphics, Buttons, Classes, LCLProc, LCLType, LMessages, Controls, Graphics, GraphType, Buttons,
// widgetset // widgetset
WSButtons, WSLCLClasses, WSProc, WSButtons, WSLCLClasses, WSProc,
// interface // interface
@ -59,7 +59,7 @@ type
class procedure UpdateMargin(const AInfo: PBitBtnWidgetInfo; const ALayout: TButtonLayout; const AMargin: Integer); class procedure UpdateMargin(const AInfo: PBitBtnWidgetInfo; const ALayout: TButtonLayout; const AMargin: Integer);
public public
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); override; class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TButtonGlyph); override;
class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); override; class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); override;
class procedure SetMargin(const ABitBtn: TCustomBitBtn; const AValue: Integer); override; class procedure SetMargin(const ABitBtn: TCustomBitBtn; const AValue: Integer); override;
class procedure SetSpacing(const ABitBtn: TCustomBitBtn; const AValue: Integer); override; class procedure SetSpacing(const ABitBtn: TCustomBitBtn; const AValue: Integer); override;
@ -152,12 +152,15 @@ begin
end; end;
class procedure TGtkWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; class procedure TGtkWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn;
const AValue: TBitmap); const AValue: TButtonGlyph);
var var
WidgetInfo: PWidgetInfo; WidgetInfo: PWidgetInfo;
BitBtnInfo: PBitBtnWidgetInfo; BitBtnInfo: PBitBtnWidgetInfo;
GDIObject: PGDIObject; GDIObject: PGDIObject;
Mask: PGdkBitmap; Mask: PGdkBitmap;
AGlyph: TBitmap;
AIndex: Integer;
AEffect: TGraphicsDrawEffect;
begin begin
if not WSCheckHandleAllocated(ABitBtn, 'SetGlyph') if not WSCheckHandleAllocated(ABitBtn, 'SetGlyph')
then Exit; then Exit;
@ -165,21 +168,25 @@ begin
WidgetInfo := GetWidgetInfo(Pointer(ABitBtn.Handle)); WidgetInfo := GetWidgetInfo(Pointer(ABitBtn.Handle));
BitBtnInfo := WidgetInfo^.UserData; BitBtnInfo := WidgetInfo^.UserData;
AGlyph := TBitmap.Create;
AValue.GetImageIndexAndEffect(bsUp, AIndex, AEffect);
AValue.Images.GetBitmap(AIndex, AGlyph, AEffect);
// check if an image is needed // check if an image is needed
if (AValue.Handle = 0) if (AGlyph.Handle = 0)
or (AValue.Width = 0) or (AGlyph.Width = 0)
or (AValue.Height = 0) or (AGlyph.Height = 0)
then begin then begin
if BitBtnInfo^.ImageWidget <> nil if BitBtnInfo^.ImageWidget <> nil
then begin then begin
gtk_container_remove(BitBtnInfo^.TableWidget, BitBtnInfo^.ImageWidget); gtk_container_remove(BitBtnInfo^.TableWidget, BitBtnInfo^.ImageWidget);
BitBtnInfo^.ImageWidget := nil; BitBtnInfo^.ImageWidget := nil;
end; end;
AGlyph.Free;
Exit; Exit;
end; end;
GDIObject := PgdiObject(AValue.Handle); GDIObject := PgdiObject(AGlyph.Handle);
Mask := CreateGdkMaskBitmap(AValue.Handle, AValue.MaskHandle); Mask := CreateGdkMaskBitmap(AValue.Glyph.Handle, AValue.Glyph.MaskHandle);
// check for image // check for image
if BitBtnInfo^.ImageWidget = nil if BitBtnInfo^.ImageWidget = nil
@ -194,6 +201,7 @@ begin
end; end;
gdk_pixmap_unref(Mask); gdk_pixmap_unref(Mask);
AGlyph.Free;
end; end;
class procedure TGtkWSBitBtn.SetLayout(const ABitBtn: TCustomBitBtn; class procedure TGtkWSBitBtn.SetLayout(const ABitBtn: TCustomBitBtn;

View File

@ -37,7 +37,7 @@ uses
{$endif} {$endif}
qtwidgets, qtobjects, qtwidgets, qtobjects,
// LCL // LCL
SysUtils, Controls, LCLType, Forms, InterfaceBase, Buttons, LMessages, Graphics, SysUtils, Controls, LCLType, Forms, InterfaceBase, Buttons, LMessages, Graphics, GraphType,
// Widgetset // Widgetset
WSProc, WSButtons, WSLCLClasses; WSProc, WSButtons, WSLCLClasses;
@ -49,7 +49,7 @@ type
private private
protected protected
public public
class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); override; class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TButtonGlyph); override;
end; end;
{ TQtWSSpeedButton } { TQtWSSpeedButton }
@ -72,21 +72,30 @@ uses QtWSControls;
Params: None Params: None
Returns: Nothing Returns: Nothing
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class procedure TQtWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); class procedure TQtWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TButtonGlyph);
var var
AIcon: QIconH; AIcon: QIconH;
APixmap: QPixmapH; APixmap: QPixmapH;
AGlyph: TBitmap;
AIndex: Integer;
AEffect: TGraphicsDrawEffect;
begin begin
APixmap := QPixmap_create(); APixmap := QPixmap_create();
QPixmap_fromImage(APixmap, TQtImage(AValue.Handle).Handle);
AGlyph := TBitmap.Create;
AValue.GetImageIndexAndEffect(bsUp, AIndex, AEffect);
AValue.Images.GetBitmap(AIndex, AGlyph, AEffect);
QPixmap_fromImage(APixmap, TQtImage(AGlyph.Handle).Handle);
try try
if APixmap <> nil then if APixmap <> nil then
begin begin
AIcon := QIcon_create(APixmap); AIcon := QIcon_create(APixmap);
TQtAbstractButton(ABitbtn.Handle).setIcon(AIcon); TQtAbstractButton(ABitBtn.Handle).setIcon(AIcon);
end; end;
finally finally
QPixmap_destroy(APixmap); QPixmap_destroy(APixmap);
AGlyph.Free;
end; end;
end; end;

View File

@ -33,10 +33,10 @@ uses
// To get as little as posible circles, // To get as little as posible circles,
// uncomment only when needed for registration // uncomment only when needed for registration
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
Windows, Classes, Buttons, Graphics, Controls, Windows, Classes, Buttons, Graphics, GraphType, Controls,
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
WSProc, WSControls, WSButtons, WSLCLClasses, WSProc, WSControls, WSButtons, WSLCLClasses,
Win32WSControls, LCLType, Themes; Win32WSControls, Win32WSImgList, LCLType, Themes;
type type
@ -52,7 +52,7 @@ type
const ALeft, ATop, AWidth, AHeight: integer); override; const ALeft, ATop, AWidth, AHeight: integer); override;
class procedure SetColor(const AWinControl: TWinControl); override; class procedure SetColor(const AWinControl: TWinControl); override;
class procedure SetFont(const AWinControl: TWinControl; const AFont: TFont); override; class procedure SetFont(const AWinControl: TWinControl; const AFont: TFont); override;
class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); override; class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TButtonGlyph); override;
class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); override; class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); override;
class procedure SetMargin(const ABitBtn: TCustomBitBtn; const AValue: Integer); override; class procedure SetMargin(const ABitBtn: TCustomBitBtn; const AValue: Integer); override;
class procedure SetSpacing(const ABitBtn: TCustomBitBtn; const AValue: Integer); override; class procedure SetSpacing(const ABitBtn: TCustomBitBtn; const AValue: Integer); override;
@ -74,6 +74,10 @@ implementation
uses uses
Win32Int, InterfaceBase, Win32Proc; Win32Int, InterfaceBase, Win32Proc;
type
TBitBtnAceess = class(TCustomBitBtn)
end;
{ TWin32WSBitBtn } { TWin32WSBitBtn }
const const
@ -145,42 +149,34 @@ var
procedure DrawBitmap(AState: TButtonState); procedure DrawBitmap(AState: TButtonState);
var var
MonoDC: HDC;
MonoBmp, OldMonoBmp: HBITMAP;
TextFlags: integer; // flags for caption (enabled or disabled) TextFlags: integer; // flags for caption (enabled or disabled)
numGlyphs, glyphLeft, glyphWidth, glyphHeight: integer; glyphWidth, glyphHeight: integer;
themesActive, emulateDisabled: boolean; themesActive: boolean;
OldBitmapHandle: HBITMAP; // Handle of the provious bitmap in hdcNewBitmap OldBitmapHandle: HBITMAP; // Handle of the provious bitmap in hdcNewBitmap
AIndex: Integer;
AEffect: TGraphicsDrawEffect;
begin begin
emulateDisabled := false;
glyphLeft := 0;
glyphWidth := srcWidth; glyphWidth := srcWidth;
glyphHeight := srcHeight; glyphHeight := srcHeight;
TextFlags := DST_PREFIXTEXT; TextFlags := DST_PREFIXTEXT;
numGlyphs := BitBtn.NumGlyphs;
case AState of if AState = bsDisabled then
bsDisabled: TextFlags := TextFlags or DSS_DISABLED;
begin
if numGlyphs > 1 then
glyphLeft := glyphWidth
else
emulateDisabled := true;
TextFlags := TextFlags or DSS_DISABLED;
end;
bsDown: if numGlyphs > 2 then glyphLeft := 2*glyphWidth;
bsExclusive: if numGlyphs > 3 then glyphLeft := 3*glyphWidth;
end;
// fill with background color // fill with background color
OldBitmapHandle := SelectObject(hdcNewBitmap, NewBitmap); OldBitmapHandle := SelectObject(hdcNewBitmap, NewBitmap);
Windows.FillRect(hdcNewBitmap, BitmapRect, BitBtn.Brush.Handle); Windows.FillRect(hdcNewBitmap, BitmapRect, BitBtn.Brush.Handle);
if not emulateDisabled then if AState <> bsDisabled then
begin begin
if (srcWidth <> 0) and (srcHeight <> 0) then if (srcWidth <> 0) and (srcHeight <> 0) then
begin begin
WidgetSet.MaskBlt(hdcNewBitmap, XDestBitmap, YDestBitmap, glyphWidth, TBitBtnAceess(BitBtn).FButtonGlyph.GetImageIndexAndEffect(AState, AIndex, AEffect);
glyphHeight, BitBtn.Glyph.Canvas.Handle, glyphLeft, 0, BitBtn.Glyph.MaskHandle, glyphLeft, 0); TWin32WSCustomImageList.DrawToDC(TBitBtnAceess(BitBtn).FButtonGlyph.Images, AIndex,
hdcNewBitmap, Rect(XDestBitmap, YDestBitmap, glyphWidth, glyphHeight),
TBitBtnAceess(BitBtn).FButtonGlyph.Images.BkColor,
TBitBtnAceess(BitBtn).FButtonGlyph.Images.BlendColor, AEffect,
TBitBtnAceess(BitBtn).FButtonGlyph.Images.DrawingStyle,
TBitBtnAceess(BitBtn).FButtonGlyph.Images.ImageType);
end; end;
end else end else
begin begin
@ -191,18 +187,6 @@ var
if (srcWidth <> 0) and (srcHeight <> 0) then if (srcWidth <> 0) and (srcHeight <> 0) then
begin begin
// Create a Mono DC
MonoBmp := CreateBitmap(glyphWidth, glyphHeight, 1, 1, nil);
MonoDC := CreateCompatibleDC(hdcNewBitmap);
OldMonoBmp := SelectObject(MonoDC, MonoBmp);
// Create the black and white image
with BitBtn.Glyph do
begin
FillRect(MonoDC, Rect(0, 0, glyphWidth, glyphHeight), BitBtn.Brush.Handle);
WidgetSet.MaskBlt(MonoDC, 0, 0, glyphWidth, glyphHeight,
Canvas.Handle, glyphLeft, 0, MaskHandle, glyphLeft, 0);
end;
if themesActive then if themesActive then
begin begin
// non-themed winapi wants white/other as background/picture-disabled colors // non-themed winapi wants white/other as background/picture-disabled colors
@ -210,13 +194,14 @@ var
SetBkColor(hdcNewBitmap, ColorToRGB(BitBtn.Brush.Color)); SetBkColor(hdcNewBitmap, ColorToRGB(BitBtn.Brush.Color));
SetTextColor(hdcNewBitmap, GetSysColor(COLOR_BTNSHADOW)); SetTextColor(hdcNewBitmap, GetSysColor(COLOR_BTNSHADOW));
end; end;
// Draw the black and white image TBitBtnAceess(BitBtn).FButtonGlyph.GetImageIndexAndEffect(AState, AIndex, AEffect);
BitBlt(hdcNewBitmap, XDestBitmap, YDestBitmap, glyphWidth, glyphHeight,
MonoDC, 0, 0, SRCCOPY);
SelectObject(MonoDC, OldMonoBmp); TWin32WSCustomImageList.DrawToDC(TBitBtnAceess(BitBtn).FButtonGlyph.Images, AIndex,
DeleteDC(MonoDC); hdcNewBitmap, Rect(XDestBitmap, YDestBitmap, glyphWidth, glyphHeight),
DeleteObject(MonoBmp); TBitBtnAceess(BitBtn).FButtonGlyph.Images.BkColor,
TBitBtnAceess(BitBtn).FButtonGlyph.Images.BlendColor, AEffect,
TBitBtnAceess(BitBtn).FButtonGlyph.Images.DrawingStyle,
TBitBtnAceess(BitBtn).FButtonGlyph.Images.ImageType);
end; end;
end; end;
SetBkMode(hdcNewBitmap, TRANSPARENT); SetBkMode(hdcNewBitmap, TRANSPARENT);
@ -367,7 +352,9 @@ begin
DrawBitmap(XPBitBtn_ImageIndexToState[I]); DrawBitmap(XPBitBtn_ImageIndexToState[I]);
ImageList_AddMasked(ButtonImageList.himl, NewBitmap, ColorToRGB(BitBtn.Brush.Color)); ImageList_AddMasked(ButtonImageList.himl, NewBitmap, ColorToRGB(BitBtn.Brush.Color));
end; end;
end else begin end
else
begin
ButtonImageList.himl := 0; ButtonImageList.himl := 0;
end; end;
Windows.SendMessage(BitBtnHandle, BCM_SETIMAGELIST, 0, LPARAM(@ButtonImageList)); Windows.SendMessage(BitBtnHandle, BCM_SETIMAGELIST, 0, LPARAM(@ButtonImageList));
@ -476,7 +463,7 @@ begin
end; end;
class procedure TWin32WSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; class procedure TWin32WSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn;
const AValue: TBitmap); const AValue: TButtonGlyph);
begin begin
if not WSCheckHandleAllocated(ABitBtn, 'SetGlyph') then Exit; if not WSCheckHandleAllocated(ABitBtn, 'SetGlyph') then Exit;
DrawBitBtnImage(ABitBtn, ABitBtn.Caption); DrawBitBtnImage(ABitBtn, ABitBtn.Caption);

View File

@ -54,6 +54,8 @@ type
class procedure DestroyHandle(AComponent: TComponent); override; class procedure DestroyHandle(AComponent: TComponent); override;
class procedure Draw(AList: TCustomImageList; AIndex: Integer; ACanvas: TCanvas; class procedure Draw(AList: TCustomImageList; AIndex: Integer; ACanvas: TCanvas;
ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); override; ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); override;
class procedure DrawToDC(AList: TCustomImageList; AIndex: Integer; ADC: HDC;
ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType);
class procedure Insert(AList: TCustomImageList; AIndex: Integer; AData: PRGBAQuad); override; class procedure Insert(AList: TCustomImageList; AIndex: Integer; AData: PRGBAQuad); override;
class procedure Move(AList: TCustomImageList; ACurIndex, ANewIndex: Integer); override; class procedure Move(AList: TCustomImageList; ACurIndex, ANewIndex: Integer); override;
class procedure Replace(AList: TCustomImageList; AIndex: Integer; AData: PRGBAQuad); override; class procedure Replace(AList: TCustomImageList; AIndex: Integer; AData: PRGBAQuad); override;
@ -265,19 +267,26 @@ end;
class procedure TWin32WSCustomImageList.Draw(AList: TCustomImageList; AIndex: Integer; class procedure TWin32WSCustomImageList.Draw(AList: TCustomImageList; AIndex: Integer;
ACanvas: TCanvas; ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); ACanvas: TCanvas; ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType);
begin
if not WSCheckHandleAllocated(AList, 'Draw')
then Exit;
DrawToDC(AList, AIndex, ACanvas.Handle, ABounds, ABkColor, ABlendColor, ADrawEffect, AStyle, AImageType);
end;
class procedure TWin32WSCustomImageList.DrawToDC(AList: TCustomImageList;
AIndex: Integer; ADC: HDC; ABounds: TRect; ABkColor, ABlendColor: TColor;
ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle;
AImageType: TImageType);
var var
DrawParams: TImageListDrawParams; DrawParams: TImageListDrawParams;
RawImg: TRawImage; RawImg: TRawImage;
ListImg, DeviceImg: TLazIntfImage; ListImg, DeviceImg: TLazIntfImage;
ImgHandle, MskHandle: HBitmap; OldBmp, ImgHandle, MskHandle: HBitmap;
ABitmap: TBitmap; ImgDC: HDC;
begin begin
if not WSCheckHandleAllocated(AList, 'Draw')
then Exit;
if ADrawEffect = gdeNormal then if ADrawEffect = gdeNormal then
begin begin
ImageList_DrawEx(HImageList(AList.Handle), AIndex, ACanvas.Handle, ABounds.Left, ImageList_DrawEx(HImageList(AList.Handle), AIndex, ADC, ABounds.Left,
ABounds.Top, ABounds.Right, ABounds.Bottom, ColorToImagelistColor(ABkColor), ABounds.Top, ABounds.Right, ABounds.Bottom, ColorToImagelistColor(ABkColor),
ColorToImagelistColor(ABlendColor), DRAWINGSTYLEMAP[AStyle] or IMAGETPYEMAP[AImageType]); ColorToImagelistColor(ABlendColor), DRAWINGSTYLEMAP[AStyle] or IMAGETPYEMAP[AImageType]);
end end
@ -289,7 +298,7 @@ begin
DrawParams.cbSize := SizeOf(DrawParams); DrawParams.cbSize := SizeOf(DrawParams);
DrawParams.himlL := HImageList(AList.Handle); DrawParams.himlL := HImageList(AList.Handle);
DrawParams.i := AIndex; DrawParams.i := AIndex;
DrawParams.hdcDst := ACanvas.Handle; DrawParams.hdcDst := ADC;
DrawParams.x := ABounds.Left; DrawParams.x := ABounds.Left;
DrawParams.y := ABounds.Top; DrawParams.y := ABounds.Top;
DrawParams.cx := ABounds.Right; DrawParams.cx := ABounds.Right;
@ -305,8 +314,7 @@ begin
// use RawImage_PerformEffect to perform drawing effect // use RawImage_PerformEffect to perform drawing effect
AList.GetRawImage(AIndex, RawImg); AList.GetRawImage(AIndex, RawImg);
RawImg.PerformEffect(ADrawEffect, True); RawImg.PerformEffect(ADrawEffect, True);
ABitmap := TBitmap.Create;
if not Widgetset.RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle, True) if not Widgetset.RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle, True)
then begin then begin
// bummer, the widgetset doesn't support our 32bit format, try device // bummer, the widgetset doesn't support our 32bit format, try device
@ -319,10 +327,15 @@ begin
DeviceImg.Free; DeviceImg.Free;
ListImg.Free; ListImg.Free;
end; end;
ABitmap.SetHandles(ImgHandle, MskHandle); ImgDC := CreateCompatibleDC(0);
ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap); OldBmp := SelectObject(ImgDC, ImgHandle);
ABitmap.Free; WidgetSet.StretchMaskBlt(ADC, ABounds.Left, ABounds.Top, ABounds.Right, ABounds.Bottom,
FreeMem(RawImg.Data); ImgDC, 0, 0, ABounds.Right, ABounds.Bottom, MskHandle, 0, 0, SRCCOPY);
RawImg.FreeData;
SelectObject(ImgDC, OldBmp);
if ImgHandle<>0 then DeleteObject(ImgHandle);
if MskHandle<>0 then DeleteObject(MskHandle);
DeleteDC(ImgDC);
end; end;
end; end;

View File

@ -54,7 +54,7 @@ type
TWSBitBtnClass = class of TWSBitBtn; TWSBitBtnClass = class of TWSBitBtn;
TWSBitBtn = class(TWSButton) TWSBitBtn = class(TWSButton)
class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); virtual; class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TButtonGlyph); virtual;
class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); virtual; class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); virtual;
class procedure SetMargin(const ABitBtn: TCustomBitBtn; const AValue: Integer); virtual; class procedure SetMargin(const ABitBtn: TCustomBitBtn; const AValue: Integer); virtual;
class procedure SetSpacing(const ABitBtn: TCustomBitBtn; const AValue: Integer); virtual; class procedure SetSpacing(const ABitBtn: TCustomBitBtn; const AValue: Integer); virtual;
@ -74,7 +74,7 @@ implementation
{ TWSCustomBitBtn } { TWSCustomBitBtn }
class procedure TWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; class procedure TWSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn;
const AValue: TBitmap); const AValue: TButtonGlyph);
begin begin
end; end;

View File

@ -120,7 +120,7 @@ begin
ABitmap.SetHandles(ImgHandle, MskHandle); ABitmap.SetHandles(ImgHandle, MskHandle);
ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap); ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap);
ABitmap.Free; ABitmap.Free;
FreeMem(RawImg.Data); RawImg.FreeData;
end; end;
end; end;