From 9e7bfb96b9a1e0407581a67e2cea8ab79704462a Mon Sep 17 00:00:00 2001 From: micha Date: Thu, 21 Jul 2005 09:43:14 +0000 Subject: [PATCH] implement tbitbtn.spacing for win32 allow -1 for tbitbtn.spacing; means center text fix transparent (xpm typically) images drawing on bitbtns git-svn-id: trunk@7388 - --- lcl/include/bitbtn.inc | 2 +- lcl/interfaces/win32/win32wsbuttons.pp | 196 ++++++++++++++++--------- 2 files changed, 127 insertions(+), 71 deletions(-) diff --git a/lcl/include/bitbtn.inc b/lcl/include/bitbtn.inc index ae5d3d1a28..85a62e3f30 100644 --- a/lcl/include/bitbtn.inc +++ b/lcl/include/bitbtn.inc @@ -152,7 +152,7 @@ end; Procedure TCustomBitBtn.SetSpacing(AValue: Integer); Begin - if (FSpacing = AValue) or (AValue < 0) then Exit; + if (FSpacing = AValue) or (AValue < -1) then Exit; FSpacing := AValue; if HandleAllocated then TWSBitBtnClass(WidgetSetClass).SetSpacing(Self, FSpacing); diff --git a/lcl/interfaces/win32/win32wsbuttons.pp b/lcl/interfaces/win32/win32wsbuttons.pp index 58ef4cc608..d2bf4f760a 100644 --- a/lcl/interfaces/win32/win32wsbuttons.pp +++ b/lcl/interfaces/win32/win32wsbuttons.pp @@ -35,7 +35,7 @@ uses //////////////////////////////////////////////////// Windows, Buttons, Graphics, Controls, //////////////////////////////////////////////////// - WSButtons, WSLCLClasses, Win32WSControls, LCLType; + WSControls, WSButtons, WSLCLClasses, Win32WSControls, LCLType; type @@ -56,6 +56,8 @@ type TWin32WSBitBtn = class(TWSBitBtn) class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): HWND; override; + class procedure SetBounds(const AWinControl: TWinControl; + const ALeft, ATop, AWidth, AHeight: integer); override; class procedure SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); override; class procedure SetLayout(const ABitBtn: TCustomBitBtn; const AValue: TButtonLayout); override; class procedure SetMargin(const ABitBtn: TCustomBitBtn; const AValue: Integer); override; @@ -185,62 +187,82 @@ var procedure DrawBitmap(Enabled: boolean); var - SrcDC, MaskDC: HBITMAP; - MaskBmp, OldSrcBmp, OldMaskBmp: HBITMAP; + SrcDC, MaskDC, MonoDC: HDC; + MaskBmp, MonoBmp, OldSrcBmp, OldMaskBmp, OldMonoBmp: HBITMAP; BkColor: TColorRef; OldBitmapHandle: HBITMAP; // Handle of the provious bitmap in hdcNewBitmap - BitmapFlags: integer; // flags for glyph (enabled or disabled) TextFlags: integer; // flags for caption (enabled or disabled) + themesActive: boolean; begin - BitmapFlags := DST_BITMAP; TextFlags := DST_PREFIXTEXT; OldBitmapHandle := SelectObject(hdcNewBitmap, NewBitmap); - if Enabled or TWin32WidgetSet(InterfaceObject).ThemesActive - then begin - // themed - if not Enabled - then begin - BitmapFlags := BitmapFlags or DSS_DISABLED; - TextFlags := TextFlags or DSS_DISABLED; - end; - - Windows.FillRect(hdcNewBitmap, BitmapRect, BitBtn.Brush.Handle); - if BitmapHandle <> 0 - then DrawState(hdcNewBitmap, 0, nil, BitmapHandle, 0, XDestBitmap, YDestBitmap, 0, 0, BitmapFlags); - end - else begin - // non themed - // When disabled only create a black and white image - // Let windows itself draw the disabled state - Windows.FillRect(hdcNewBitmap, BitmapRect, Windows.GetStockObject(WHITE_BRUSH)); - if BitmapHandle <> 0 - then begin - // Create a source DC - SrcDC := CreateCompatibleDC(hdcNewBitmap); - OldSrcBmp := SelectObject(SrcDC, BitmapHandle); - // Create a mask DC - MaskBmp := CreateBitmap(BitmapInfo.bmWidth, BitmapInfo.bmHeight, 1, 1, nil); - MaskDC := CreateCompatibleDC(hdcNewBitmap); - OldMaskBmp := SelectObject(MaskDC, MaskBmp); + MaskDC := CreateCompatibleDC(hdcNewBitmap); + if BitBtn.Glyph.MaskHandleAllocated then + begin + // Create a mask DC + MaskBmp := CreateCompatibleBitmap(hdcNewBitmap, BitmapInfo.bmWidth, BitmapInfo.bmHeight); + OldMaskBmp := SelectObject(MaskDC, MaskBmp); + SrcDC := CreateCompatibleDC(hdcNewBitmap); + OldSrcBmp := SelectObject(SrcDC, BitmapHandle); + FillRect(MaskDC, BitmapRect, BitBtn.Brush.Handle); + TWin32WidgetSet(InterfaceObject).MaskBlt(MaskDC, 0, 0, BitmapInfo.bmWidth, BitmapInfo.bmHeight, SrcDC, + 0, 0, BitBtn.Glyph.MaskHandle, 0, 0); + end else begin + MaskBmp := BitmapHandle; + OldMaskBmp := SelectObject(MaskDC, MaskBmp); + end; + + // fill with background color + Windows.FillRect(hdcNewBitmap, BitmapRect, BitBtn.Brush.Handle); + if Enabled then + begin + if MaskBmp <> 0 then + BitBlt(hdcNewBitmap, XDestBitmap, YDestBitmap, BitmapInfo.bmWidth, + BitmapInfo.bmHeight, MaskDC, 0, 0, SRCCOPY); + end else begin + TextFlags := TextFlags or DSS_DISABLED; + // when not themed, windows wants a white background picture for disabled button image + themesActive := TWin32WidgetSet(InterfaceObject).ThemesActive; + if not themesActive then + FillRect(hdcNewBitmap, BitmapRect, GetStockObject(WHITE_BRUSH)); + if BitmapHandle <> 0 then + begin + // Create a Mono DC + MonoBmp := CreateBitmap(BitmapInfo.bmWidth, BitmapInfo.bmHeight, 1, 1, nil); + MonoDC := CreateCompatibleDC(hdcNewBitmap); + OldMonoBmp := SelectObject(MonoDC, MonoBmp); // Create the black and white image - BkColor := SetBkColor(SrcDC, BitBtn.Brush.Color); - BitBlt(MaskDC, 0, 0, BitmapInfo.bmWidth, BitmapInfo.bmHeight, SrcDC, 0, 0, SrcCopy); - SetBkColor(SrcDC, BkColor); + BkColor := SetBkColor(MaskDC, ColorToRGB(BitBtn.Brush.Color)); + BitBlt(MonoDC, 0, 0, BitmapInfo.bmWidth, BitmapInfo.bmHeight, MaskDC, 0, 0, SRCCOPY); + SetBkColor(MaskDC, BkColor); + if themesActive then + begin + // non-themed winapi wants white/other as background/picture-disabled colors + // themed winapi draws bitmap-as, with transparency defined by bitbtn.brush color + BkColor := SetBkColor(hdcNewBitmap, ColorToRGB(BitBtn.Brush.Color)); + SetTextColor(hdcNewBitmap, GetSysColor(COLOR_BTNSHADOW)); + end; // Draw the black and white image BitBlt(hdcNewBitmap, XDestBitmap, YDestBitmap, BitmapInfo.bmWidth, BitmapInfo.bmHeight, - MaskDC, 0, 0, SRCCOPY); + MonoDC, 0, 0, SRCCOPY); - SelectObject(SrcDC, OldSrcBmp); - DeleteDC(SrcDC); - - SelectObject(MaskDC, OldMaskBmp); - DeleteDC(MaskDC); - DeleteObject(MaskBmp); + SelectObject(MonoDC, OldMonoBmp); + DeleteDC(MonoDC); + DeleteObject(MonoBmp); end; end; + if BitBtn.Glyph.MaskHandleAllocated then + begin + SelectObject(SrcDC, OldSrcBmp); + DeleteDC(SrcDC); + DeleteObject(MaskBmp); + end; + SelectObject(MaskDC, OldMaskBmp); + DeleteDC(MaskDC); + SetBkMode(hdcNewBitmap, TRANSPARENT); DrawState(hdcNewBitmap, 0, nil, LPARAM(ButtonCaption), 0, XDestText, YDestText, 0, 0, TextFlags); SelectObject(hdcNewBitmap, OldBitmapHandle); @@ -267,47 +289,72 @@ begin case BitBtnLayout of blGlyphLeft, blGlyphRight: begin - newWidth := TextSize.cx + BitmapInfo.bmWidth; + if BitBtn.Spacing = -1 then + newWidth := BitBtn.Width - 10 + else + newWidth := TextSize.cx + BitmapInfo.bmWidth + BitBtn.Spacing; if BitmapHandle <> 0 then inc(newWidth, 2); newHeight := TextSize.cy; if newHeight < BitmapInfo.bmHeight then newHeight := BitmapInfo.bmHeight; - YDestBitmap := (newHeight - BitmapInfo.bmHeight) shr 1; - YDestText := (newHeight - TextSize.cy) shr 1; + YDestBitmap := (newHeight - BitmapInfo.bmHeight) div 2; + YDestText := (newHeight - TextSize.cy) div 2; + case BitBtnLayout of + blGlyphLeft: + begin + XDestBitmap := 0; + XDestText := BitmapInfo.bmWidth; + if BitBtn.Spacing = -1 then + inc(XDestText, (newWidth - BitmapInfo.bmWidth - TextSize.cx) div 2) + else + inc(XDestText, BitBtn.Spacing); + end; + blGlyphRight: + begin + XDestBitmap := newWidth - BitmapInfo.bmWidth; + XDestText := XDestBitmap - TextSize.cx; + if BitBtn.Spacing = -1 then + dec(XDestText, (newWidth - BitmapInfo.bmWidth - TextSize.cx) div 2) + else + dec(XDestText, BitBtn.Spacing); + end; + end; end; blGlyphTop, blGlyphBottom: begin newWidth := TextSize.cx; if newWidth < BitmapInfo.bmWidth then newWidth := BitmapInfo.bmWidth; - newHeight := TextSize.cy + BitmapInfo.bmHeight; + if BitBtn.Spacing = -1 then + newHeight := BitBtn.Height - 10 + else + newHeight := TextSize.cy + BitmapInfo.bmHeight + BitBtn.Spacing; if BitmapHandle <> 0 then inc(newHeight, 2); XDestBitmap := (newWidth - BitmapInfo.bmWidth) shr 1; XDestText := (newWidth - TextSize.cx) shr 1; + case BitBtnLayout of + blGlyphTop: + begin + YDestBitmap := 0; + YDestText := BitmapInfo.bmHeight; + if BitBtn.Spacing = -1 then + inc(YDestText, (newHeight - BitmapInfo.bmHeight - TextSize.cy) div 2) + else + inc(YDestText, BitBtn.Spacing); + end; + blGlyphBottom: + begin + YDestBitmap := newHeight - BitmapInfo.bmHeight; + YDestText := YDestBitmap - TextSize.cy; + if BitBtn.Spacing = -1 then + dec(YDestText, (newHeight - BitmapInfo.bmHeight - TextSize.cy) div 2) + else + dec(YDestText, BitBtn.Spacing); + end; end; end; - case BitBtnLayout of - blGlyphLeft: - begin - XDestBitmap := 0; - XDestText := newWidth - TextSize.cx; - end; - blGlyphRight: - begin - XDestBitmap := newWidth - BitmapInfo.bmWidth; - XDestText := 0; - end; - blGlyphTop: - begin - YDestBitmap := 0; - YDestText := newHeight - TextSize.cy; - end; - blGlyphBottom: begin - YDestBitmap := newHeight - BitmapInfo.bmHeight; - YDestText := 0; - end; end; // create new if (newWidth = 0) and (newHeight = 0) then @@ -329,10 +376,10 @@ begin if NewBitmap <> 0 then begin ButtonImageList.himl := ImageList_Create(newWidth, newHeight, ILC_COLORDDB or ILC_MASK, 5, 0); - ButtonImageList.margin.left := 2; - ButtonImageList.margin.right := 2; - ButtonImageList.margin.top := 2; - ButtonImageList.margin.bottom := 2; + ButtonImageList.margin.left := 5; + ButtonImageList.margin.right := 5; + ButtonImageList.margin.top := 5; + ButtonImageList.margin.bottom := 5; ButtonImageList.uAlign := BUTTON_IMAGELIST_ALIGN_CENTER; // for some reason, if bitmap added to imagelist, need to redrawn, otherwise it's black!? for I := 0 to 4 do @@ -359,6 +406,7 @@ begin SelectObject(hdcNewBitmap, OldFontHandle); DeleteDC(hdcNewBitmap); ReleaseDC(BitBtnHandle, BitBtnDC); + BitBtn.Invalidate; end; function TWin32WSBitBtn.CreateHandle(const AWinControl: TWinControl; @@ -384,6 +432,14 @@ begin Result := Params.Window; end; +procedure TWin32WSBitBtn.SetBounds(const AWinControl: TWinControl; + const ALeft, ATop, AWidth, AHeight: integer); +begin + TWin32WSWinControl.SetBounds(AWinControl, ALeft, ATop, AWidth, AHeight); + if TCustomBitBtn(AWinControl).Spacing = -1 then + DrawBitBtnImage(TCustomBitBtn(AWinControl), PChar(AWinControl.Caption)); +end; + procedure TWin32WSBitBtn.SetGlyph(const ABitBtn: TCustomBitBtn; const AValue: TBitmap); begin