// ************************************************************************************************** // // 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-2021 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 /// The TButtonStyleHookFix 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 /// /// /// Use this hook in this way /// /// TStyleManager.Engine.RegisterStyleHook(TButton, TButtonStyleHookFix); /// /// TButtonStyleHookFix = class(TButtonStyleHook) protected procedure Paint(Canvas: TCanvas); override; end; {$IFEND} {$IF CompilerVersion <= 27.0} type /// The TListViewStyleHookFix vcl style hook fix these QC #108678, #108875 for Delphi XE2-XE6 /// /// /// Use this hook in this way /// /// TStyleManager.Engine.RegisterStyleHook(TListView, TListViewStyleHookFix); /// /// 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 /// This interposer class fix the QC #114032 for Delphi XE2 and Delphi XE3 /// /// /// To use this class add the Vcl.Styles.Fixes unit to your uses list after of the Vcl.ExtCtrls unit /// TColorBox = class(Vcl.ExtCtrls.TColorBox) private procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM; end; /// The TComboBoxExStyleHookFix vcl style hook fix the QC #108678 for Delphi XE2 and Delphi XE3 /// /// /// Use this hook in this way /// /// TStyleManager.Engine.RegisterStyleHook(TComboBoxEx, TComboBoxExStyleHookFix); /// /// 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} /// The TComboBoxStyleHookFix vcl style hook fix the QC #114632 for Delphi XE5 and earlier /// /// /// Use this hook in this way /// /// TStyleManager.Engine.RegisterStyleHook(TComboBox, TComboBoxStyleHookFix); /// /// 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.