// **************************************************************************************************
//
// Unit Vcl.Styles.Fixes
// unit for the VCL Styles Utils
// https://github.com/RRUZ/vcl-styles-utils/
//
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the
// License at http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
// ANY KIND, either express or implied. See the License for the specific language governing rights
// and limitations under the License.
//
// The Original Code is Vcl.Styles.Fixes
//
// The Initial Developer of the Original Code is Rodrigo Ruz V.
// Portions created by Rodrigo Ruz V. are Copyright (C) 2012-2020 Rodrigo Ruz V.
// All Rights Reserved.
//
// Contributors
//
// Leonardo Cechet
//
// **************************************************************************************************
unit Vcl.Styles.Fixes;
interface
uses
Winapi.Windows,
Winapi.Messages,
Vcl.Controls,
Vcl.ComCtrls,
Vcl.StdCtrls,
Vcl.ExtCtrls,
Vcl.Graphics;
{$IF CompilerVersion >= 23.0}
type
/// <summary> The <c>TButtonStyleHookFix</c> vcl style hook fix these QC #103708, #107764 for Delphi XE2
/// and the https://quality.embarcadero.com/browse/RSP-11619 issue present in X2-XE8
/// </summary>
/// <remarks>
/// Use this hook in this way
/// <code>
/// TStyleManager.Engine.RegisterStyleHook(TButton, TButtonStyleHookFix);
/// </code>
/// </remarks>
TButtonStyleHookFix = class(TButtonStyleHook)
protected
procedure Paint(Canvas: TCanvas); override;
end;
{$IFEND}
{$IF CompilerVersion <= 27.0}
type
/// <summary> The <c>TListViewStyleHookFix</c> vcl style hook fix these QC #108678, #108875 for Delphi XE2-XE6
/// </summary>
/// <remarks>
/// Use this hook in this way
/// <code>
/// TStyleManager.Engine.RegisterStyleHook(TListView, TListViewStyleHookFix);
/// </code>
/// </remarks>
TListViewStyleHookFix = class(TListViewStyleHook)
procedure DrawHeaderSection(Canvas: TCanvas; R: TRect; Index: Integer;
const Text: string; IsPressed, IsBackground: Boolean); override;
end;
{$IFEND}
{$IF CompilerVersion <= 24.0}
type
/// <summary> This interposer class fix the QC #114032 for Delphi XE2 and Delphi XE3
/// </summary>
/// <remarks>
/// To use this class add the Vcl.Styles.Fixes unit to your uses list after of the Vcl.ExtCtrls unit
/// </remarks>
TColorBox = class(Vcl.ExtCtrls.TColorBox)
private
procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
end;
/// <summary> The <c>TComboBoxExStyleHookFix</c> vcl style hook fix the QC #108678 for Delphi XE2 and Delphi XE3
/// </summary>
/// <remarks>
/// Use this hook in this way
/// <code>
/// TStyleManager.Engine.RegisterStyleHook(TComboBoxEx, TComboBoxExStyleHookFix);
/// </code>
/// </remarks>
TComboBoxExStyleHookFix = class(TComboBoxExStyleHook)
strict protected
procedure DrawListBoxItem(ADC: HDC; ARect: TRect; AIndex: Integer;
ASelected: Boolean);
procedure ComboBoxWndProc(var Msg: TMessage); override;
procedure DrawComboBox(DC: HDC); override;
end;
{$IFEND}
{$IF CompilerVersion <= 26.0}
/// <summary> The <c>TComboBoxStyleHookFix</c> vcl style hook fix the QC #114632 for Delphi XE5 and earlier
/// </summary>
/// <remarks>
/// Use this hook in this way
/// <code>
/// TStyleManager.Engine.RegisterStyleHook(TComboBox, TComboBoxStyleHookFix);
/// </code>
/// </remarks>
TComboBoxStyleHookFix = class(TComboBoxStyleHook)
strict private
FTempItemIndex: Integer;
procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
strict protected
procedure DrawItem(Canvas: TCanvas; Index: Integer;
const R: TRect; Selected: Boolean); override;
public
constructor Create(AControl: TWinControl); override;
end;
{$IFEND}
implementation
uses
Winapi.CommCtrl,
Vcl.Themes,
Vcl.Forms,
System.SysUtils,
System.Classes,
System.UITypes,
System.Types;
type
TCustomButtonClass = class(TCustomButton);
TWinControlClass = class(TWinControl);
{$IF CompilerVersion >= 23.0}
// we need this helper to access some strict private fields
TButtonStyleHookHelper = class Helper for TButtonStyleHook
protected
function Pressed: Boolean;
function DropDown: Boolean;
end;
{$IFEND}
{$IF CompilerVersion <= 27.0}
TListViewStyleHookHelper = class helper for TListViewStyleHook
function HeaderHandle: HWnd;
end;
{$IFEND}
{$IF CompilerVersion <= 24.0}
TComboBoxExStyleHookHelper = class helper for TComboBoxExStyleHook
function DroppedDown: Boolean;
end;
{$IFEND}
{$IF CompilerVersion <= 26.0}
TComboBoxStyleHookHelper = class helper for TComboBoxStyleHook
strict private
function _getDroppedDown: Boolean;
private
property _DroppedDown : Boolean read _getDroppedDown;
end;
{$IFEND}
{$IF CompilerVersion >= 23.0}
procedure TButtonStyleHookFix.Paint(Canvas: TCanvas);
const
PBS_NORMAL = 0;
PBS_HOT = 1;
PBS_PRESSED = 2;
PBS_DISABLED = 3;
PBS_DEFAULTED = 4;
PBS_STYLUSHOT = 5;
var
LDetails: TThemedElementDetails;
DrawRect: TRect;
pbuttonImagelist: BUTTON_IMAGELIST;
IW, IH, IY: Integer;
LTextFormatFlags: TTextFormatFlags;
ThemeTextColor: TColor;
Buffer: string;
BufferLength: Integer;
SaveIndex: Integer;
X, Y, I: Integer;
IsDefault: Boolean;
BCaption: String;
LImageIndex: Integer;
begin
LImageIndex:=PBS_NORMAL;
IsDefault := (Control is TCustomButton) and (TCustomButton(Control).Default);
if StyleServices.Available then
begin
BCaption := Text;
if not Control.Enabled then
begin
LDetails := StyleServices.GetElementDetails(tbPushButtonDisabled);
LImageIndex := PBS_DISABLED;
end
else
if Pressed then
begin
LDetails := StyleServices.GetElementDetails(tbPushButtonPressed);
LImageIndex := PBS_PRESSED;
end
else
if MouseInControl then
begin
LDetails := StyleServices.GetElementDetails(tbPushButtonHot);
LImageIndex := PBS_HOT;
end
else
if Control.Focused or (IsDefault and (Screen.ActiveControl<>nil) and not (Screen.ActiveControl is TCustomButton) ) then
begin
LDetails := StyleServices.GetElementDetails(tbPushButtonDefaulted);
LImageIndex := PBS_DEFAULTED;
end
else if Control.Enabled then
LDetails := StyleServices.GetElementDetails(tbPushButtonNormal);
DrawRect := Control.ClientRect;
StyleServices.DrawElement(Canvas.Handle, LDetails, DrawRect);
if Button_GetImageList(Handle, pbuttonImagelist) and
(pbuttonImagelist.himl <> 0) and
ImageList_GetIconSize(pbuttonImagelist.himl, IW, IH) then
begin
if (GetWindowLong(Handle, GWL_STYLE) and BS_COMMANDLINK) = BS_COMMANDLINK
then
IY := DrawRect.Top + 15
else
IY := DrawRect.Top + (DrawRect.Height - IH) div 2;
// here the image is drawn properly according to the ImageAlignment value
case TCustomButton(Control).ImageAlignment of
TImageAlignment.iaLeft:
begin
ImageList_Draw(pbuttonImagelist.himl, LImageIndex, Canvas.Handle,
DrawRect.Left + 3 + TCustomButton(Control).ImageMargins.Left, IY, ILD_NORMAL);
Inc(DrawRect.Left, IW + 3 + TCustomButton(Control).ImageMargins.Left);
end;
TImageAlignment.iaRight:
begin
ImageList_Draw(pbuttonImagelist.himl, LImageIndex, Canvas.Handle,
DrawRect.Right - IW - 3 - TCustomButton(Control).ImageMargins.Right, IY, ILD_NORMAL);
Dec(DrawRect.Right, IW - 3 + TCustomButton(Control).ImageMargins.Right);
end;
TImageAlignment.iaCenter:
begin
ImageList_Draw(pbuttonImagelist.himl, LImageIndex, Canvas.Handle,
(DrawRect.Right - IW) div 2, IY + TCustomButton(Control).ImageMargins.Top - TCustomButton(Control).ImageMargins.Bottom, ILD_NORMAL);
end;
TImageAlignment.iaTop:
begin
ImageList_Draw(pbuttonImagelist.himl, LImageIndex, Canvas.Handle,
(DrawRect.Right - IW) div 2, 3 + TCustomButton(Control).ImageMargins.Top - TCustomButton(Control).ImageMargins.Bottom, ILD_NORMAL);
end;
TImageAlignment.iaBottom:
begin
ImageList_Draw(pbuttonImagelist.himl, LImageIndex, Canvas.Handle,
(DrawRect.Right - IW) div 2, (DrawRect.Height - IH) - 3 + TCustomButton(Control).ImageMargins.Top - TCustomButton(Control).ImageMargins.Bottom,
ILD_NORMAL);
end;
end;
end;
if (GetWindowLong(Handle, GWL_STYLE) and BS_COMMANDLINK) = BS_COMMANDLINK then
begin
if pbuttonImagelist.himl = 0 then
Inc(DrawRect.Left, 35);
Inc(DrawRect.Top, 15);
Inc(DrawRect.Left, 5);
Canvas.Font := TCustomButtonClass(Control).Font;
Canvas.Font.Style := [];
Canvas.Font.Size := 12;
LTextFormatFlags := TTextFormatFlags(DT_LEFT);
if StyleServices.GetElementColor(LDetails, ecTextColor, ThemeTextColor)
then
Canvas.Font.Color := ThemeTextColor;
StyleServices.DrawText(Canvas.Handle, LDetails, BCaption, DrawRect,
LTextFormatFlags, Canvas.Font.Color);
SetLength(Buffer, Button_GetNoteLength(Handle) + 1);
if Length(Buffer) <> 0 then
begin
BufferLength := Length(Buffer);
if Button_GetNote(Handle, PChar(Buffer), BufferLength) then
begin
LTextFormatFlags := TTextFormatFlags(DT_LEFT or DT_WORDBREAK);
Inc(DrawRect.Top, Canvas.TextHeight('Wq') + 2);
Canvas.Font.Size := 8;
StyleServices.DrawText(Canvas.Handle, LDetails, Buffer, DrawRect,
LTextFormatFlags, Canvas.Font.Color);
end;
end;
if pbuttonImagelist.himl = 0 then
begin
if Pressed then
LDetails := StyleServices.GetElementDetails(tbCommandLinkGlyphPressed)
else if MouseInControl then
LDetails := StyleServices.GetElementDetails(tbCommandLinkGlyphHot)
else if Control.Enabled then
LDetails := StyleServices.GetElementDetails(tbCommandLinkGlyphNormal)
else
LDetails := StyleServices.GetElementDetails
(tbCommandLinkGlyphDisabled);
DrawRect.Right := 35;
DrawRect.Left := 3;
DrawRect.Top := 10;
DrawRect.Bottom := DrawRect.Top + 32;
StyleServices.DrawElement(Canvas.Handle, LDetails, DrawRect);
end;
end
else if (GetWindowLong(Handle, GWL_STYLE) and BS_SPLITBUTTON) = BS_SPLITBUTTON
then
begin
Dec(DrawRect.Right, 15);
DrawControlText(Canvas, LDetails, Text, DrawRect, DT_VCENTER or
DT_CENTER);
if DropDown then
begin
LDetails := StyleServices.GetElementDetails(tbPushButtonPressed);
SaveIndex := SaveDC(Canvas.Handle);
try
IntersectClipRect(Canvas.Handle, Control.Width - 15, 0, Control.Width,
Control.Height);
DrawRect := Rect(Control.Width - 30, 0, Control.Width,
Control.Height);
StyleServices.DrawElement(Canvas.Handle, LDetails, DrawRect);
finally
RestoreDC(Canvas.Handle, SaveIndex);
end;
end;
with Canvas do
begin
Pen.Color := StyleServices.GetSystemColor(clBtnShadow);
MoveTo(Control.Width - 15, 3);
LineTo(Control.Width - 15, Control.Height - 3);
if Control.Enabled then
Pen.Color := StyleServices.GetSystemColor(clBtnHighLight)
else
Pen.Color := Font.Color;
MoveTo(Control.Width - 14, 3);
LineTo(Control.Width - 14, Control.Height - 3);
Pen.Color := Font.Color;
X := Control.Width - 8;
Y := Control.Height div 2 + 1;
for I := 3 downto 0 do
begin
MoveTo(X - I, Y - I);
LineTo(X + I + 1, Y - I);
end;
end;
end
else
begin
// finally the text is aligned and drawn depending of the value of the ImageAlignment property
case TCustomButton(Control).ImageAlignment of
TImageAlignment.iaLeft,
TImageAlignment.iaRight,
TImageAlignment.iaCenter: if (Control is TCustomButton) and TCustomButtonClass(Control).WordWrap then
DrawControlText(Canvas, LDetails, BCaption, DrawRect, DT_VCENTER or DT_CENTER or DT_WORDBREAK or Control.DrawTextBiDiModeFlags(0))
else
DrawControlText(Canvas, LDetails, BCaption, DrawRect, DT_VCENTER or DT_CENTER or Control.DrawTextBiDiModeFlags(0));
TImageAlignment.iaBottom: if (Control is TCustomButton) and TCustomButtonClass(Control).WordWrap then
DrawControlText(Canvas, LDetails, BCaption, DrawRect, DT_TOP or DT_CENTER or DT_WORDBREAK or Control.DrawTextBiDiModeFlags(0))
else
DrawControlText(Canvas, LDetails, BCaption, DrawRect, DT_TOP or DT_CENTER or Control.DrawTextBiDiModeFlags(0));
TImageAlignment.iaTop: if (Control is TCustomButton) and TCustomButtonClass(Control).WordWrap then
DrawControlText(Canvas, LDetails, BCaption, DrawRect, DT_BOTTOM or DT_CENTER or DT_WORDBREAK or Control.DrawTextBiDiModeFlags(0))
else
DrawControlText(Canvas, LDetails, BCaption, DrawRect, DT_BOTTOM or DT_CENTER or Control.DrawTextBiDiModeFlags(0));
end;
end;
end;
end;
{ TButtonStyleHookHelper }
function TButtonStyleHookHelper.DropDown: Boolean;
begin
Result := Self.FDropDown;
end;
function TButtonStyleHookHelper.Pressed: Boolean;
begin
Result := Self.FPressed;
end;
{$IFEND}
{$IF CompilerVersion <= 27.0}
{ TListViewStyleHookHelper }
function TListViewStyleHookHelper.HeaderHandle: HWnd;
begin
Result := Self.FHeaderHandle;
end;
{$IFEND}
{$IF CompilerVersion <= 24.0}
{ TComboBoxExStyleHookHelper }
function TComboBoxExStyleHookHelper.DroppedDown: Boolean;
begin
Exit(Self.FDroppedDown);
end;
{$IFEND}
{$IF CompilerVersion <= 27.0}
{ TListViewStyleHookFix }
procedure TListViewStyleHookFix.DrawHeaderSection(Canvas: TCanvas; R: TRect;
Index: Integer; const Text: string; IsPressed, IsBackground: Boolean);
var
Item: THDItem;
ImageList: HIMAGELIST;
DrawState: TThemedHeader;
IconWidth, IconHeight: Integer;
Details: TThemedElementDetails;
begin
FillChar(Item, SizeOf(Item), 0);
Item.Mask := HDI_FORMAT;
Header_GetItem(HeaderHandle, Index, Item);
if IsBackground then
DrawState := thHeaderItemNormal
else if IsPressed then
DrawState := thHeaderItemPressed
else
DrawState := thHeaderItemNormal;
Details := StyleServices.GetElementDetails(DrawState);
StyleServices.DrawElement(Canvas.Handle, Details, R);
ImageList := SendMessage(HeaderHandle, HDM_GETIMAGELIST, 0, 0);
Item.Mask := HDI_FORMAT or HDI_IMAGE;
InflateRect(R, -2, -2);
IconWidth := 0;
if (ImageList <> 0) and Header_GetItem(HeaderHandle, Index, Item) then
begin
if Item.fmt and HDF_IMAGE = HDF_IMAGE then
ImageList_Draw(ImageList, Item.iImage, Canvas.Handle, R.Left, R.Top,
ILD_TRANSPARENT);
ImageList_GetIconSize(ImageList, IconWidth, IconHeight);
Inc(R.Left, IconWidth + 5);
end;
if IconWidth = 0 then Inc(R.Left, 2);
DrawControlText(Canvas, Details, Text, R, DT_VCENTER or DT_LEFT or
DT_SINGLELINE or DT_END_ELLIPSIS);
end;
{$IFEND}
{$IF CompilerVersion <= 24.0}
{ TColorBox }
procedure TColorBox.CNDrawItem(var Message: TWMDrawItem);
const
ColorStates: array [Boolean] of TStyleColor = (scComboBoxDisabled,
scComboBox);
FontStates: array [Boolean] of TStyleFont = (sfComboBoxItemDisabled,
sfComboBoxItemNormal);
var
LState: TOwnerDrawState;
begin
LState := TOwnerDrawState(LoWord(Message.DrawItemStruct^.itemState));
if Message.DrawItemStruct^.itemState and ODS_COMBOBOXEDIT <> 0 then
Include(LState, odComboBoxEdit);
if Message.DrawItemStruct^.itemState and ODS_DEFAULT <> 0 then
Include(LState, odDefault);
Canvas.Handle := Message.DrawItemStruct^.HDC;
Canvas.Font := Font;
if TStyleManager.IsCustomStyleActive then
begin
{$IF CompilerVersion<=23} //XE2
Canvas.Brush.Color := StyleServices.GetStyleColor(ColorStates[Enabled]);
Canvas.Font.Color := StyleServices.GetStyleFontColor(FontStates[Enabled]);
{$ELSE}
if seClient in StyleElements then
Canvas.Brush.Color := StyleServices.GetStyleColor(ColorStates[Enabled])
else
Canvas.Brush := Brush;
if seFont in StyleElements then
Canvas.Font.Color := StyleServices.GetStyleFontColor(FontStates[Enabled]);
{$IFEND}
end
else
Canvas.Brush := Brush;
if (Integer(Message.DrawItemStruct^.itemID) >= 0) and
(odSelected in LState){$IF CompilerVersion>23} and (seClient in StyleElements) {$IFEND} then
begin
if TStyleManager.IsCustomStyleActive then
begin
Canvas.Brush.Color := StyleServices.GetSystemColor(clHighlight);
Canvas.Font.Color := StyleServices.GetSystemColor(clHighlightText);
end
else
begin
Canvas.Brush.Color := clHighlight;
Canvas.Font.Color := clHighlightText
end;
end;
if Integer(Message.DrawItemStruct^.itemID) >= 0 then
DrawItem(Message.DrawItemStruct^.itemID,
Message.DrawItemStruct^.rcItem, LState)
else
Canvas.FillRect(Message.DrawItemStruct^.rcItem);
if (odFocused in LState) and (TStyleManager.ActiveStyle.IsSystemStyle) then
DrawFocusRect(Message.DrawItemStruct^.HDC, Message.DrawItemStruct^.rcItem);
Canvas.Handle := 0;
end;
{ TComboBoxExStyleHookFix }
procedure TComboBoxExStyleHookFix.ComboBoxWndProc(var Msg: TMessage);
begin
case Msg.Msg of
WM_DRAWITEM:
begin
DrawListBoxItem(TWMDrawItem(Msg).DrawItemStruct.HDC,
TWMDrawItem(Msg).DrawItemStruct.rcItem,
TWMDrawItem(Msg).DrawItemStruct.itemID,
TWMDrawItem(Msg).DrawItemStruct.itemState and ODS_SELECTED <> 0);
end
else
inherited;
end;
end;
procedure TComboBoxExStyleHookFix.DrawComboBox(DC: HDC);
var
DX, DY: Integer;
LCanvas: TCanvas;
LDetails: TThemedElementDetails;
LRect: TRect;
LThemedComboBox: TThemedComboBox;
LCaption: string;
LBitmap: TBitmap;
LDrawState: TThemedComboBox;
begin
if not StyleServices.Available or (Control.Width = 0) or (Control.Height = 0)
then
Exit;
LCanvas := TCanvas.Create;
try
LCanvas.Handle := DC;
LBitmap := TBitmap.Create;
try
LBitmap.Width := Control.Width;
LBitmap.Height := Control.Height;
if not Control.Enabled then
LDrawState := tcBorderDisabled
else if Control.Focused then
LDrawState := tcBorderFocused
else if MouseInControl then
LDrawState := tcBorderHot
else
LDrawState := tcBorderNormal;
LRect := Rect(0, 0, Control.Width, Control.Height);
LDetails := StyleServices.GetElementDetails(LDrawState);
StyleServices.DrawElement(LBitmap.Canvas.Handle, LDetails, LRect);
{$IF CompilerVersion > 23.0}
if not(seClient in Control.StyleElements) then
begin
LRect := Control.ClientRect;
InflateRect(LRect, -3, -3);
LRect.Right := ButtonRect.Left - 2;
LBitmap.Canvas.Brush.Color := TWinControlClass(Control).Color;
LBitmap.Canvas.FillRect(LRect);
end;
{$IFEND}
if not Control.Enabled then
LThemedComboBox := tcDropDownButtonDisabled
else if DroppedDown then
LThemedComboBox := tcDropDownButtonPressed
else if MouseOnButton then
LThemedComboBox := tcDropDownButtonHot
else
LThemedComboBox := tcDropDownButtonNormal;
if TCustomComboBoxEx(Control).Style <> csExSimple then
begin
LDetails := StyleServices.GetElementDetails(LThemedComboBox);
StyleServices.DrawElement(LBitmap.Canvas.Handle, LDetails, ButtonRect);
end;
LRect := Control.ClientRect;
InflateRect(LRect, -3, -3);
LRect.Right := ButtonRect.Left - 2;
LBitmap.Canvas.Font.Assign(TComboBoxEx(Control).Font);
{$IF CompilerVersion > 23.0}
if seFont in Control.StyleElements then
{$IFEND}
if Control.Enabled then
LBitmap.Canvas.Font.Color := StyleServices.GetStyleFontColor
(sfComboBoxItemNormal)
else
LBitmap.Canvas.Font.Color := StyleServices.GetStyleFontColor
(sfComboBoxItemDisabled);
if TComboBoxEx(Control).Style = csExDropDownList then
begin
if TComboBoxEx(Control).Focused then
begin
if TComboBoxEx(Control).ItemIndex <> -1 then
begin
LBitmap.Canvas.Brush.Color := StyleServices.GetSystemColor
(clHighlight);
LBitmap.Canvas.Brush.Style := bsSolid;
LBitmap.Canvas.FillRect(LRect);
LBitmap.Canvas.Font.Color := StyleServices.GetSystemColor
(clHighlightText);
end;
LBitmap.Canvas.DrawFocusRect(LRect);
end
else
begin
LBitmap.Canvas.Brush.Color := Self.Brush.Color;
LBitmap.Canvas.Brush.Style := bsSolid;
LBitmap.Canvas.FillRect(LRect);
end;
end;
if TComboBoxEx(Control).Style <> csExSimple then
begin
{ image }
if (TComboBoxEx(Control).Images <> nil) and
(TComboBoxEx(Control).ItemIndex <> -1) then
begin
DX := 5;
DY := LRect.Top + LRect.Height div 2 - TComboBoxEx(Control)
.Images.Height div 2;
if DY < LRect.Top then
DY := LRect.Top;
if (TComboBoxEx(Control).ItemsEx[TComboBoxEx(Control).ItemIndex]
.ImageIndex >= 0) and
(TComboBoxEx(Control).ItemsEx[TComboBoxEx(Control).ItemIndex]
.ImageIndex < TComboBoxEx(Control).Images.Count) then
TComboBoxEx(Control).Images.Draw(LBitmap.Canvas, DX, DY,
TComboBoxEx(Control).ItemsEx[TComboBoxEx(Control).ItemIndex]
.ImageIndex, Control.Enabled);
LRect.Left := DX + TComboBoxEx(Control).Images.Width + 5;
end
else
Inc(LRect.Left, 5);
{ text }
if (TComboBoxEx(Control).ItemIndex <> -1) then
begin
LBitmap.Canvas.Brush.Style := bsClear;
LCaption := TComboBoxEx(Control).ItemsEx
[TComboBoxEx(Control).ItemIndex].Caption;
if LCaption <> '' then
DrawText(LBitmap.Canvas.Handle, PWideChar(LCaption),
Length(LCaption), LRect, DT_LEFT OR DT_VCENTER or DT_SINGLELINE);
end;
end;
LCanvas.Draw(0, 0, LBitmap);
finally
LBitmap.Free;
end;
finally
LCanvas.Handle := 0;
LCanvas.Free;
end;
Handled := True;
end;
procedure TComboBoxExStyleHookFix.DrawListBoxItem(ADC: HDC; ARect: TRect;
AIndex: Integer; ASelected: Boolean);
var
LCanvas: TCanvas;
Offset: Integer;
DX, DY: Integer;
Buffer: TBitmap;
LCaption: String;
LRect: TRect;
begin
if (AIndex < 0) or (AIndex >= TComboBoxEx(Control).ItemsEx.Count) then
Exit;
LCanvas := TCanvas.Create;
LCanvas.Handle := ADC;
Buffer := TBitmap.Create;
Buffer.Width := ARect.Width;
Buffer.Height := ARect.Height;
try
Buffer.Canvas.Font.Assign(TComboBoxEx(Control).Font);
begin
{ background }
Buffer.Canvas.Brush.Style := bsSolid;
if ASelected then
begin
Buffer.Canvas.Brush.Color := StyleServices.GetSystemColor(clHighlight);
Buffer.Canvas.Font.Color := StyleServices.GetSystemColor
(clHighlightText);
end
else
begin
{$IF CompilerVersion > 23.0}
if seClient in Control.StyleElements then
Buffer.Canvas.Brush.Color := StyleServices.GetStyleColor(scComboBox)
else
Buffer.Canvas.Brush.Color := TWinControlClass(Control).Color;
{$ELSE}
Buffer.Canvas.Brush.Color := StyleServices.GetStyleColor(scComboBox);
{$IFEND}
{$IF CompilerVersion > 23.0}
if seFont in Control.StyleElements then
Buffer.Canvas.Font.Color := StyleServices.GetStyleFontColor
(sfComboBoxItemNormal)
else
Buffer.Canvas.Font.Color := TWinControlClass(Control).Font.Color;
{$ELSE}
Buffer.Canvas.Font.Color := StyleServices.GetStyleFontColor
(sfComboBoxItemNormal);
{$IFEND}
end;
Buffer.Canvas.FillRect(Rect(0, 0, Buffer.Width, Buffer.Height));
Offset := TComboExItem(TComboBoxEx(Control).ItemsEx[AIndex]).Indent;
if Offset > 0 then
Offset := (Offset * 10) + 5
else
Offset := 5;
{ image }
if (TComboBoxEx(Control).Images <> nil) then
begin
DX := Offset;
DY := Buffer.Height div 2 - TComboBoxEx(Control).Images.Height div 2;
if DY < 0 then
DY := 0;
if (TComboBoxEx(Control).ItemsEx[AIndex].ImageIndex >= 0) and
(TComboBoxEx(Control).ItemsEx[AIndex].ImageIndex <
TComboBoxEx(Control).Images.Count) then
TComboBoxEx(Control).Images.Draw(Buffer.Canvas, DX, DY,
TComboBoxEx(Control).ItemsEx[AIndex].ImageIndex, True);
Offset := Offset + TComboBoxEx(Control).Images.Width + 5;
end;
{ text }
LRect := Rect(Offset, 0, Buffer.Width, Buffer.Height);
Buffer.Canvas.Brush.Style := bsClear;
LCaption := TComboBoxEx(Control).ItemsEx[AIndex].Caption;
if LCaption <> '' then
DrawText(Buffer.Canvas.Handle, PWideChar(LCaption), Length(LCaption),
LRect, DT_LEFT OR DT_VCENTER or DT_SINGLELINE);
end;
LCanvas.Draw(ARect.Left, ARect.Top, Buffer);
finally
Buffer.Free;
LCanvas.Handle := 0;
LCanvas.Free;
end;
end;
{$IFEND}
{$IF CompilerVersion <= 26.0}
constructor TComboBoxStyleHookFix.Create(AControl: TWinControl);
begin
inherited;
FTempItemIndex := -1;
end;
procedure TComboBoxStyleHookFix.WMCommand(var Message: TWMCommand);
begin
if (Message.NotifyCode = CBN_SELENDCANCEL) or (Message.NotifyCode = CBN_SELENDOK) or
(Message.NotifyCode = CBN_CLOSEUP) or (Message.NotifyCode = CBN_DROPDOWN) or
(Message.NotifyCode = CBN_SELCHANGE) then
begin
if (Message.NotifyCode = CBN_DROPDOWN) or (Message.NotifyCode = CBN_SELCHANGE) then
FTempItemIndex := TComboBox(Control).ItemIndex;
end;
inherited;
end;
procedure TComboBoxStyleHookFix.CNCommand(var Message: TWMCommand);
begin
if (Message.NotifyCode = CBN_SELENDCANCEL) or (Message.NotifyCode = CBN_SELENDOK) or
(Message.NotifyCode = CBN_CLOSEUP) or (Message.NotifyCode = CBN_DROPDOWN) or
(Message.NotifyCode = CBN_SELCHANGE) then
begin
if (Message.NotifyCode = CBN_DROPDOWN) or (Message.NotifyCode = CBN_SELCHANGE) then
FTempItemIndex := TComboBox(Control).ItemIndex;
end;
inherited;
end;
procedure TComboBoxStyleHookFix.DrawItem(Canvas: TCanvas; Index: Integer;
const R: TRect; Selected: Boolean);
begin
if _DroppedDown then
inherited DrawItem(Canvas, FTempItemIndex, R, Selected)
else
inherited;
end;
function TComboBoxStyleHookHelper._getDroppedDown: Boolean;
begin
Result := Self.DroppedDown;
end;
{$IFEND}
end.