我正在尝试从使用Toolbar2000切换到常规工具栏,因为似乎没有Delphi XE2版本,看起来它使用了一些程序集,我真的不想处理它,如果我不必。 (我真的很喜欢使用Delphi工具栏的淡入效果)
但是,我不喜欢的是按钮的背景会得到常规的蓝色按钮处理。我知道如何改变颜色,但是我可以不改变颜色并且按钮周围没有边框吗?
我已经实现了'OnAdvancedCustomDrawButton',但是可用的标志看起来似乎不正常,我不确定它们如何与渐变颜色和热门轨道颜色相互作用,我最终会有一些奇怪的闪烁或怪异黑色背景。
以下是我创建工具栏的方法
ToolBar1 := TToolBar.Create(Self);
ToolBar1.DoubleBuffered := true;
ToolBar1.OnAdvancedCustomDrawButton := Toolbar1CustomDrawButton;
ToolBar1.Transparent := false;
ToolBar1.Parent := Self;
ToolBar1.GradientEndColor := $7ca0c2; //RGB(194, 160, 124);
ToolBar1.GradientStartColor := $edeeed; //RGB(237, 238, 124);
ToolBar1.Indent := 5;
ToolBar1.Images := Normal;
ToolBar1.DrawingStyle := dsGradient;
ToolBar1.HotImages := Over;
ToolBar1.AutoSize := True;
ToolBar1.Visible := False;
以下是我如何创建按钮(循环中):
ToolButton := TToolButton.Create(ToolBar1);
ToolButton.Parent := ToolBar1;
ToolButton.ImageIndex := ToolButtonImages[Index].ImageIndex;
ToolButton.OnClick := ToolButtonClick;
这是我的AdvancedCustomDrawButton函数
procedure TMyForm.Toolbar1CustomDrawButton(Sender: TToolBar; Button: TToolButton;
State: TCustomDrawState; Stage: TCustomDrawStage;
var Flags: TTBCustomDrawFlags; var DefaultDraw: Boolean);
begin
Flags := [tbNoEdges, tbNoOffset];
DefaultDraw := True;
end;
答案 0 :(得分:2)
将工具栏的绘图样式设置为dsNormal
,并在自定义绘制处理程序中将Flags
设置为[tbNoEdges]。
<强>更新强>
虽然以上适用于2K和XP,但Vista和7似乎在没有绘制按钮背景时不绘制边框。不幸的是,用VCL提供TTBCustomDrawFlags
来实现这一点是不可能的,所以我们无法摆脱自定义绘图处理程序中的边框。
如果工具栏位于表单本身,我们可以为WM_NOTIFY
设置处理程序,因为通知消息将发送到父窗口:
type
TForm1 = class(TForm)
..
private
procedure WMNotify(var Msg: TWMNotify); message WM_NOTIFY;
..
..
procedure TForm1.WMNotify(var Msg: TWMNotify);
begin
inherited;
if (Msg.NMHdr.code = NM_CUSTOMDRAW) and
Assigned(Toolbar1) and (Toolbar1.HandleAllocated) and
(Msg.NMHdr.hwndFrom = ToolBar1.Handle) then
case PNMTBCustomDraw(Msg.NMHdr).nmcd.dwDrawStage of
CDDS_PREPAINT: Msg.Result := Msg.Result or CDRF_NOTIFYITEMDRAW;
CDDS_ITEMPREPAINT: Msg.Result := TBCDRF_NOEDGES or TBCDRF_NOBACKGROUND;
// NOEDGES for 2K, XP, // NOBACKGROUND for Vista 7
end;
end;
如果工具栏是另一个窗口(如面板)的父级,那么我们需要子类化工具栏:
type
TForm1 = class(TForm)
..
private
FSaveToolbarWndProc: TWndMethod;
procedure ToolbarWndProc(var Msg: TMessage);
..
..
uses
commctrl;
procedure TForm1.FormCreate(Sender: TObject);
begin
..
FSaveToolbarWndProc := ToolBar1.WindowProc;
ToolBar1.WindowProc := ToolbarWndProc;
end;
procedure TForm1.ToolbarWndProc(var Msg: TMessage);
begin
FSaveToolbarWndProc(Msg);
if (Msg.Msg = CN_NOTIFY) and
(TWMNotify(Msg).NMHdr.hwndFrom = ToolBar1.Handle) and
(TWMNotify(Msg).NMHdr.code = NM_CUSTOMDRAW) then begin
case PNMTBCustomDraw(TWmNotify(Msg).NMHdr)^.nmcd.dwDrawStage of
CDDS_PREPAINT: Msg.Result := CDRF_NOTIFYITEMDRAW;
CDDS_ITEMPREPAINT: Msg.Result := TBCDRF_NOEDGES or TBCDRF_NOBACKGROUND;
end;
end;
end;
(请注意,绘图风格仍需dsNormal
。)
使用此解决方案,您无需为自定义绘图添加处理程序。但是如果你还是需要/想要的话,你可能需要'或'Msg.Result
和一个VCL的窗口程序返回,即'case'看起来像:
CDDS_PREPAINT: Msg.Result := Msg.Result or CDRF_NOTIFYITEMDRAW;
CDDS_ITEMPREPAINT: Msg.Result :=
Msg.Result or TBCDRF_NOEDGES or TBCDRF_NOBACKGROUND;
当我们在表单上处理WM_NOTIFY时也一样。
可能还有其他方法可以实现相同,自定义绘图是一个广泛的主题。如果你想深入研究它,我建议你从下面的链接开始解决手头的问题:
About Custom Draw
NM_CUSTOMDRAW (toolbar) notification code
NMCUSTOMDRAW structure
NMTBCUSTOMDRAW structure