当我尝试禁用一个风格的VCL上的按钮使用下面的代码行
- TButton(Sender).enabled:= False;
我得到这个结果(在运行时禁用了按钮)
而不是这个! (设计时按钮禁用)
让两个或更多个具有相同颜色的按钮彼此相互混淆确实令人困惑,一个被禁用,另一个被启用
解决方法
此问题的原因位于
TButtonStyleHook
(在Vcl.StdCtrls单元)样式hook类的Paint方法中.
- if FPressed then
- Details := StyleServices.GetElementDetails(tbPushButtonPressed)
- else if MouseInControl then //this condition is triggered even if the button is disabled
- Details := StyleServices.GetElementDetails(tbPushButtonHot)
- else if Focused then //this condition is triggered even if the button is disabled
- Details := StyleServices.GetElementDetails(tbPushButtonDefaulted)
- else if Control.Enabled then
- Details := StyleServices.GetElementDetails(tbPushButtonNormal)
- else
- Details := StyleServices.GetElementDetails(tbPushButtonDisabled);
并替换此代码
- if FPressed then
- Details := StyleServices.GetElementDetails(tbPushButtonPressed)
- else if MouseInControl and Control.Enabled then
- Details := StyleServices.GetElementDetails(tbPushButtonHot)
- else if Focused and Control.Enabled then
- Details := StyleServices.GetElementDetails(tbPushButtonDefaulted)
- else if Control.Enabled then
- Details := StyleServices.GetElementDetails(tbPushButtonNormal)
- else
- Details := StyleServices.GetElementDetails(tbPushButtonDisabled);
另一个选项是重写TButton的Style钩子:
检查这个代码在这篇文章Fixing a VCL Style bug in the TButton component.这个代码的优点是你正在修复两个问题103708和103962.
- Uses
- Winapi.CommCtrl,Vcl.Themes,Vcl.Styles;
- type
- TCustomButtonH=class(TCustomButton);
- //we need this helper to access some strict private fields
- TButtonStyleHookHelper = class Helper for TButtonStyleHook
- protected
- function Pressed : Boolean;
- function DropDown: Boolean;
- end;
- //to avoid writting a lot of extra code we are to use TButtonStyleHook class and override the paint method
- TButtonStyleHookFix = class(TButtonStyleHook)
- protected
- procedure Paint(Canvas: TCanvas); override;
- end;
- { TButtonStyleHookFix }
- procedure TButtonStyleHookFix.Paint(Canvas: TCanvas);
- 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;
- BCaption : String;
- begin
- if StyleServices.Available then
- begin
- BCaption := Text;
- if Pressed then
- LDetails := StyleServices.GetElementDetails(tbPushButtonPressed)
- else
- if MouseInControl and Control.Enabled then
- LDetails := StyleServices.GetElementDetails(tbPushButtonHot)
- else
- if Focused and Control.Enabled then
- LDetails := StyleServices.GetElementDetails(tbPushButtonDefaulted)
- else
- if Control.Enabled then
- LDetails := StyleServices.GetElementDetails(tbPushButtonNormal)
- else
- LDetails := StyleServices.GetElementDetails(tbPushButtonDisabled);
- 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
- iaLeft :
- begin
- ImageList_Draw(pbuttonImagelist.himl,Canvas.Handle,DrawRect.Left + 3,IY,ILD_NORMAL);
- Inc(DrawRect.Left,IW + 3);
- end;
- iaRight :
- begin
- ImageList_Draw(pbuttonImagelist.himl,DrawRect.Right - IW -3,ILD_NORMAL);
- Dec(DrawRect.Right,IW - 3);
- end;
- iaCenter:
- begin
- ImageList_Draw(pbuttonImagelist.himl,(DrawRect.Right - IW) div 2,ILD_NORMAL);
- end;
- iaTop :
- begin
- ImageList_Draw(pbuttonImagelist.himl,3,ILD_NORMAL);
- end;
- iaBottom:
- begin
- ImageList_Draw(pbuttonImagelist.himl,(DrawRect.Height - IH) - 3,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 := TCustomButtonH(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,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,Buffer,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,DrawRect);
- end;
- end
- else
- if (GetWindowLong(Handle,GWL_STYLE) and BS_SPLITBUTTON) = BS_SPLITBUTTON then
- begin
- Dec(DrawRect.Right,15);
- DrawControlText(Canvas,Text,DT_VCENTER or DT_CENTER);
- if DropDown then
- begin
- LDetails := StyleServices.GetElementDetails(tbPushButtonPressed);
- SaveIndex := SaveDC(Canvas.Handle);
- try
- IntersectClipRect(Canvas.Handle,Control.Width - 15,Control.Width,Control.Height);
- DrawRect := Rect(Control.Width - 30,Control.Height);
- StyleServices.DrawElement(Canvas.Handle,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
- iaLeft,iaRight,iaCenter : DrawControlText(Canvas,DT_VCENTER or DT_CENTER);
- iaBottom : DrawControlText(Canvas,DT_TOP or DT_CENTER);
- iaTop : DrawControlText(Canvas,DT_BOTTOM or DT_CENTER);
- end;
- end;
- end;
- end;
- { TButtonStyleHookHelper }
- function TButtonStyleHookHelper.DropDown: Boolean;
- begin
- Result:=Self.FDropDown;
- end;
- function TButtonStyleHookHelper.Pressed: Boolean;
- begin
- Result:=Self.FPressed;
- end;
- initialization
- TStyleManager.Engine.RegisterStyleHook(TButton,TButtonStyleHookFix);