Delphi 我们是否负责在使用Windows API绘制按钮时绘制标题? 介绍
我一直对WindowsAPI有点兴趣,并看到了如何将控件绘制到画布上 经过反复试验,我终于想出了这个程序,可以在画布上画一个按钮:Delphi 我们是否负责在使用Windows API绘制按钮时绘制标题? 介绍,delphi,winapi,delphi-xe7,Delphi,Winapi,Delphi Xe7,我一直对WindowsAPI有点兴趣,并看到了如何将控件绘制到画布上 经过反复试验,我终于想出了这个程序,可以在画布上画一个按钮: type TButtonState = (bsDefault, bsDisabled, bsHot, bsNormal, bsPressed); procedure DrawButton(ACanvas: TCanvas; X, Y, AWidth, AHeight: Integer; AFont: TFont; Caption: string; Butt
type
TButtonState = (bsDefault, bsDisabled, bsHot, bsNormal, bsPressed);
procedure DrawButton(ACanvas: TCanvas; X, Y, AWidth, AHeight: Integer;
AFont: TFont; Caption: string; ButtonState: TButtonState);
var
Size: TSize;
R: TRect;
H: HTHEME;
begin
Size.cx := AWidth;
Size.cy := AHeight;
R := Rect(X, Y, X + AWidth, Y + AHeight);
if Winapi.uxTheme.UseThemes then
begin
H := OpenThemeData(0, 'BUTTON');
if H <> 0 then
try
ACanvas.Brush.Style := bsClear;
if AFont <> nil then
begin
ACanvas.Font.Assign(AFont);
end;
case ButtonState of
bsDefault:
begin
GetThemePartSize(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_DEFAULTED, nil, TS_DRAW, Size);
DrawThemeBackground(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_DEFAULTED, R, nil);
end;
bsDisabled:
begin
GetThemePartSize(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_DISABLED, nil, TS_DRAW, Size);
DrawThemeBackground(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_DISABLED, R, nil);
//ACanvas.Font.Color := $00838383; //todo get actual disabled font color
end;
bsHot:
begin
GetThemePartSize(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_HOT, nil, TS_DRAW, Size);
DrawThemeBackground(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_HOT, R, nil);
end;
bsNormal:
begin
GetThemePartSize(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_NORMAL, nil, TS_DRAW, Size);
DrawThemeBackground(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_NORMAL, R, nil);
end;
bsPressed:
begin
GetThemePartSize(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_PRESSED, nil, TS_DRAW, Size);
DrawThemeBackground(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_PRESSED, R, nil);
end;
end;
// draw the button caption
DrawText(ACanvas.Handle, PChar(Caption), Length(Caption), R, DT_CENTER or DT_VCENTER or DT_SINGLELINE);
finally
CloseThemeData(H);
end
end
else
begin
// draw button in classic theme?
end;
end;
结果就是我所期望的,就像任何Windows按钮控件一样:
问题:
当我在玩这个程序的时候,我很快意识到这个按钮没有标题,除了自己在按钮上画标题之外,我看不到添加标题的方法。如您所见,“Disabled”(已禁用)按钮仍显示默认字体颜色,禁用的控件通常具有不同的颜色以帮助显示控件已禁用。标准Windows主题下禁用的字体颜色是$00838383
(使用屏幕颜色选择器找到),但硬编码值从来不是一个好主意,因为这些值通常对每个主题都是唯一的
我的问题有几个部分,当使用WinOWSAPI绘制按钮时,我们需要自己手动绘制标题吗?如果是,我如何确保绘制的字体名称、样式和大小等正确,以确保按钮与系统范围内绘制的按钮相同
奖金
未启用主题时,如何以经典Windows样式绘制按钮?您应该自己绘制文本。您也可以使用主题api来绘制文本。例如:
...
bsDisabled:
begin
GetThemePartSize(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_DISABLED, nil, TS_DRAW, Size);
DrawThemeBackground(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_DISABLED, R, nil);
DrawThemeText(H, ACanvas.Handle, BP_PUSHBUTTON, PBS_DISABLED, PChar(Caption),
Length(Caption), DT_CENTER or DT_VCENTER or DT_SINGLELINE, 0, R);
//ACanvas.Font.Color := $00838383; //todo get actual disabled font color
end;
...
因为您将使用适当的状态调用api,所以将调用包括在case分支中,并删除对DrawText的调用
您可以将DrawFrameControl用于经典样式。例如:
DrawFrameControl(ACanvas.Handle, R, DFC_BUTTON, DFCS_BUTTONPUSH);
在您的用例中,您必须自己绘制按钮(非常罕见!)还是调用WinAPI来创建按钮(然后由Windows管理而无需担心字体样式)可以?后者是使用WinAPI的正常方式,如果您没有任何特殊要求,我建议使用后者。如果未启用主题,则必须使用
DrawText()
而不是DrawThemeText()
。还有一个用于绘制禁用文本的GrayString()
函数。还可以使用GetSysColor和COLOR\u GRAYTEXT来获取经典样式的禁用文本的颜色。这正是我所需要的,谢谢大家提供的有用信息。
DrawFrameControl(ACanvas.Handle, R, DFC_BUTTON, DFCS_BUTTONPUSH);