ドロップダウン ボタンをクリックすると、フォームに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 がボタンの状態を認識していないため、1 つの問題が発生します。VCL がボタンを更新するたびに、スタイルの再設定が必要になります。