单击下拉按钮时,会向表单发送TBN_DROPDOWN
通知。这可用于跟踪启动菜单的按钮:
type
TForm1 = class(TForm)
[...]
private
FButtonArrowDown: TToolButton;
procedure WmNotify(var Msg: TWmNotify); message WM_NOTIFY;
[...]
uses
commctrl;
procedure TForm1.WmNotify(var Msg: TWmNotify);
function FindButton(Bar: TToolBar; Command: Integer): TToolButton;
var
i: Integer;
begin
Result := nil;
for i := 0 to Bar.ButtonCount - 1 do
if Bar.Buttons[i].Index = Command then begin
Result := Bar.Buttons[i];
Break;
end;
end;
begin
if (Msg.NMHdr.code = TBN_DROPDOWN) and
(LongWord(Msg.IDCtrl) = ToolBar1.Handle) then begin
FButtonArrowDown := FindButton(ToolBar1, PNMToolBar(Msg.NMHdr).iItem);
inherited;
FButtonArrowDown := nil;
end else
inherited;
end;
procedure TForm1.ToolBar1AdvancedCustomDrawButton(Sender: TToolBar;
Button: TToolButton; State: TCustomDrawState; Stage: TCustomDrawStage;
var Flags: TTBCustomDrawFlags; var DefaultDraw: Boolean);
var
DroppedDown: Boolean;
begin
DroppedDown := Button = FButtonArrowDown;
[...]
请注意,“OnAdvancedCustomDrawButton”中的“DroppedDown”变量与按钮的“向下”状态不同步,它仅反映下拉箭头的“向下”状态。
我相信,这就是这个问题中问题的原因:当工具栏具有TBSTYLE_EX_DRAWDDARROWS
扩展样式并且其按钮没有BTNS_WHOLEDROPDOWN
样式时,在其菜单启动时仅按下按钮的下拉箭头部分。实际上,该按钮不是“按下”。AFAIU,即使如此,您也想绘制按下的按钮。不幸的是,VCL 没有公开任何属性来拥有“wholedropdown”按钮。
可以在按钮上设置此样式:
var
ButtonInfo: TTBButtonInfo;
i: Integer;
Rect: TRect;
begin
ButtonInfo.cbSize := SizeOf(ButtonInfo);
ButtonInfo.dwMask := TBIF_STYLE;
for i := 0 to ToolBar1.ButtonCount - 1 do begin
SendMessage(ToolBar1.Handle, TB_GETBUTTONINFO, ToolBar1.Buttons[i].Index,
LPARAM(@ButtonInfo));
ButtonInfo.fsStyle := ButtonInfo.fsStyle or BTNS_WHOLEDROPDOWN;
SendMessage(Toolbar1.Handle, TB_SETBUTTONINFO, ToolBar1.Buttons[i].Index,
LPARAM(@ButtonInfo));
end;
// Tell the VCL the actual positions of the buttons, otherwise the menus
// will launch at wrong offsets due to the separator between button face
// and dropdown arrow being removed.
for i := 0 to ToolBar1.ButtonCount - 1 do begin
SendMessage(ToolBar1.Handle, TB_GETITEMRECT,
ToolBar1.Buttons[i].Index, Longint(@Rect));
ToolBar1.Buttons[i].Left := Rect.Left;
end;
end;
然后下拉部分不会与按钮分开,或者更准确地说,不会有单独的下拉部分,因此每当启动其菜单时都会设置按钮的按下/按下状态。
但是由于 VCL 不知道按钮的状态会带来一个问题;每当 VCL 更新按钮时,都需要重新设置样式。