Implement creating a toolbar in CAD and adding menu commands, as shown below:

![Image Description](https://cdn.bimath.com/blog/pg/Snipaste_2026-01-04_16-09-20.png)
Reference article: > [cad --- menu, toolbar, screen menu, enhanced toolbar](https://blog.csdn.net/zeqi1991/article/details/102810373)

The main implementation path is to create a dockable window, creating toolbuttons within it, adding commands to the button click events, and displaying the submenu at the button position. For smoother interaction, you need to override the menu style.
As mentioned in the article, you can control controls via an XML file, which can omit the steps of modifying interaction.
I only implemented a simple horizontal layout and cancelled the button border background here. I also need to add adaptive modification content so that both top and side docking can be achieved.
There isn’t much to say about the code logic, so I’ll put the code directly below:
Dialog:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//-----------------------------------------------------------------------------
class CDockControlBarChildDlg : public CAcUiDialog {
DECLARE_DYNAMIC (CDockControlBarChildDlg)

public:
CDockControlBarChildDlg (CWnd *pParent =NULL, HINSTANCE hInstance =NULL) ;

enum { IDD = IDD_DOCKCONTROLBAR};

protected:
virtual void DoDataExchange (CDataExchange *pDX) ;
virtual BOOL OnCommand (WPARAM wParam, LPARAM lParam) ;
BOOL OnInitDialog() override;

protected:
afx_msg LRESULT OnAcadKeepFocus (WPARAM wParam, LPARAM lParam) ;
public:
afx_msg void OnSize (UINT nType, int cx, int cy) ;

protected:
DECLARE_MESSAGE_MAP()


public:
CDockMenuPickButton m_btn_1;

CDockMenuPickButton m_btn_3;
CDockMenuPickButton m_btn_4;
CDockMenuPickButton m_btn_5;
CDockMenuPickButton m_btn_6;
CDockMenuPickButton m_btn_7;
afx_msg void OnBnClickedButton7();
afx_msg void OnBnClickedButton6();
afx_msg void OnBnClickedButton3();
afx_msg void OnBnClickedButton4();
afx_msg void OnBnClickedButton5();
afx_msg void OnBnClickedButton1();

private:
CMenu m_menu_1;
CMenu m_menu_3;
CMenu m_menu_4;
CMenu m_menu_5;
CMenu m_menu_6;
CMenu m_menu_7;
} ;

IMPLEMENT_DYNAMIC (CDockControlBarChildDlg, CAcUiDialog)

BEGIN_MESSAGE_MAP(CDockControlBarChildDlg, CAcUiDialog)
//{{AFX_MSG_MAP(CDockControlBarChildDlg)
ON_MESSAGE(WM_ACAD_KEEPFOCUS, OnAcadKeepFocus) // Needed for modeless dialog.
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON7, &CDockControlBarChildDlg::OnBnClickedButton7)
ON_BN_CLICKED(IDC_BUTTON6, &CDockControlBarChildDlg::OnBnClickedButton6)
ON_BN_CLICKED(IDC_BUTTON3, &CDockControlBarChildDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON4, &CDockControlBarChildDlg::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CDockControlBarChildDlg::OnBnClickedButton5)
ON_BN_CLICKED(IDC_BUTTON1, &CDockControlBarChildDlg::OnBnClickedButton1)
END_MESSAGE_MAP()

//-----------------------------------------------------------------------------
CDockControlBarChildDlg::CDockControlBarChildDlg (CWnd *pParent /*=NULL*/, HINSTANCE hInstance /*=NULL*/) : CAcUiDialog (CDockControlBarChildDlg::IDD, pParent, hInstance) {
//{{AFX_DATA_INIT(CDockControlBarChildDlg)
//}}AFX_DATA_INIT
}

//-----------------------------------------------------------------------------
void CDockControlBarChildDlg::DoDataExchange (CDataExchange *pDX) {
CAcUiDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDockControlBarChildDlg)
//}}AFX_DATA_MAP

DDX_Control(pDX, IDC_BUTTON1, m_btn_1);//Feedback
DDX_Control(pDX, IDC_BUTTON6, m_btn_6);//Example Template
DDX_Control(pDX, IDC_BUTTON3, m_btn_3);//Text Template
DDX_Control(pDX, IDC_BUTTON4, m_btn_4);//Efficiency Tools
DDX_Control(pDX, IDC_BUTTON5, m_btn_5);//Drawing Guide
DDX_Control(pDX, IDC_BUTTON7, m_btn_7);//Drafting Standard
}

//-----------------------------------------------------------------------------
//- Needed for modeless dialogs to keep focus.
//- Return FALSE to not keep the focus, return TRUE to keep the focus
LRESULT CDockControlBarChildDlg::OnAcadKeepFocus (WPARAM wParam, LPARAM lParam) {
return (TRUE) ;
}

//-----------------------------------------------------------------------------
//- As this dialog is a child dialog we need to disable ok and cancel
BOOL CDockControlBarChildDlg::OnCommand (WPARAM wParam, LPARAM lParam) {
switch ( wParam ) {
case IDOK:
case IDCANCEL:
return (FALSE) ;
}
return (CAcUiDialog::OnCommand (wParam, lParam)) ;
}

BOOL CDockControlBarChildDlg::OnInitDialog()
{
CAcUiDialog::OnInitDialog();

//Drafting Standard
m_menu_7.CreatePopupMenu();
m_menu_7.AppendMenu(MF_STRING, ID_32768, _T("Standard Border"));
m_menu_7.AppendMenu(MF_STRING, ID_32769, _T("Layer Standard"));
m_menu_7.AppendMenu(MF_STRING, ID_32770, _T("Drafting Standard"));
m_menu_7.AppendMenu(MF_STRING, ID_32771, _T("Common Blocks"));
//Efficiency Tools
m_menu_4.CreatePopupMenu();
m_menu_4.AppendMenu(MF_STRING, ID_32778, _T("Data Quick Check"));
m_menu_4.AppendMenu(MF_STRING, ID_32779, _T("Calculation Table"));
m_menu_4.AppendMenu(MF_STRING, ID_327710, _T("Drafting R&D Tools"));
////Text Template
m_menu_3.CreatePopupMenu();
m_menu_3.AppendMenu(MF_STRING, ID_32774, _T("Design Info Inquiry"));
m_menu_3.AppendMenu(MF_STRING, ID_32775, _T("Review Text"));
m_menu_3.AppendMenu(MF_STRING, ID_32776, _T("Report Text"));
m_menu_3.AppendMenu(MF_STRING, ID_32777, _T("Construction Drawing Files"));
////Example Template
m_menu_6.CreatePopupMenu();
m_menu_6.AppendMenu(MF_STRING, ID_32772, _T("Example Template"));
m_menu_6.AppendMenu(MF_STRING, ID_327723, _T("Depth Example"));
////Drawing Guide
m_menu_5.CreatePopupMenu();
m_menu_5.AppendMenu(MF_STRING, ID_327711, _T("Drafting Standard Guide"));
m_menu_5.AppendMenu(MF_STRING, ID_327712, _T("Plan Drawing Guide"));
m_menu_5.AppendMenu(MF_STRING, ID_327713, _T("Elevation/Section Guide"));
m_menu_5.AppendMenu(MF_STRING, ID_327714, _T("Detail Drawing Guide"));
m_menu_5.AppendMenu(MF_STRING, ID_327715, _T("Special Drawing Guide"));
////Feedback
m_menu_1.CreatePopupMenu();
m_menu_1.AppendMenu(MF_STRING, ID_327716, _T("Feedback"));

/*m_menu_1 = (CMenu*)GetDlgItem(IDR_MENU1);
m_btn_1.SetMenu(m_menu_1);*/


return TRUE;
}

//-----------------------------------------------------------------------------
void CDockControlBarChildDlg::OnSize (UINT nType, int cx, int cy) {
CAcUiDialog::OnSize (nType, cx, cy) ;
//- Now update the dialog
MoveWindow (0, 0, cx, cy) ;
}


void CDockControlBarChildDlg::OnBnClickedButton7()
{
CRect rect;
m_btn_7.GetWindowRect(&rect);

CString str;
str.Format(_T("rect width : %d , rect length : %d"), rect.Width(), rect.Height());

m_menu_7.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, this);

//m_menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, this);
}


void CDockControlBarChildDlg::OnBnClickedButton6()
{
// TODO: Add control notification handler code here
CRect rect;
m_btn_6.GetWindowRect(&rect);

CString str;
str.Format(_T("rect width : %d , rect length : %d"), rect.Width(), rect.Height());

m_menu_6.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, this);

}


void CDockControlBarChildDlg::OnBnClickedButton3()
{
// TODO: Add control notification handler code here
CRect rect;
m_btn_3.GetWindowRect(&rect);

CString str;
str.Format(_T("rect width : %d , rect length : %d"), rect.Width(), rect.Height());

m_menu_3.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, this);
}


void CDockControlBarChildDlg::OnBnClickedButton4()
{
// TODO: Add control notification handler code here
CRect rect;
m_btn_4.GetWindowRect(&rect);

CString str;
str.Format(_T("rect width : %d , rect length : %d"), rect.Width(), rect.Height());

m_menu_4.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, this);
}


void CDockControlBarChildDlg::OnBnClickedButton5()
{
// TODO: Add control notification handler code here
CRect rect;
m_btn_5.GetWindowRect(&rect);

CString str;
str.Format(_T("rect width : %d , rect length : %d"), rect.Width(), rect.Height());

m_menu_5.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, this);
}


void CDockControlBarChildDlg::OnBnClickedButton1()
{
//MessageBox(_T("Test Menu"));
// TODO: Add control notification handler code here
CRect rect;
m_btn_1.GetWindowRect(&rect);

/*CString str;
str.Format(_T("rect width : %d , rect length : %d"), rect.left, rect.bottom);
MessageBox(str);*/

BOOL addMenu = m_menu_1.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, this);
if(!addMenu)
{
MessageBox(_T("Test Menu Failed"));
}
}

Button:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//-----------------------------------------------------------------------------
class CDockMenuPickButton : public CAcUiToolButton {
DECLARE_DYNAMIC (CDockMenuPickButton)

public:
CDockMenuPickButton () ;
virtual ~CDockMenuPickButton () ;
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) override;

afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnMouseHover(UINT nFlags, CPoint point);
afx_msg void OnMouseLeave();

protected:
DECLARE_MESSAGE_MAP()

private:
BOOL m_bTrackLeave;
} ;


#include "StdAfx.h"
#include "resource.h"
#include "DockMenuPickButton.h"

//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC (CDockMenuPickButton, CAcUiToolButton)

BEGIN_MESSAGE_MAP(CDockMenuPickButton, CAcUiToolButton)


END_MESSAGE_MAP()


CDC* hdc;
CRect hRect;

//-----------------------------------------------------------------------------
CDockMenuPickButton::CDockMenuPickButton () {
}

//-----------------------------------------------------------------------------
CDockMenuPickButton::~CDockMenuPickButton () {
}

void CDockMenuPickButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC dc;
dc.Attach(lpDrawItemStruct->hDC);
dc.SelectStockObject(NULL_BRUSH);
dc.Rectangle(&lpDrawItemStruct->rcItem);

hdc = &dc;

COLORREF local_bk = dc.GetBkColor();

CString str;
GetWindowText(str);

CRect rect = lpDrawItemStruct->rcItem;
hRect = rect;
GetClientRect(&rect);
//Set background transparent color
dc.SetBkMode(TRANSPARENT);
dc.SetPolyFillMode(TRANSPARENT);
::GetStockObject(NULL_BRUSH);

//Set pen to null, no border
if(lpDrawItemStruct->itemState & ODS_SELECTED )
{
//Set color to background color, achieving border invisible effect
//dc.FillSolidRect(&rect,::GetBkColor(dc));
dc.FillSolidRect(&rect, RGB(190, 200, 255));
//If hovering or selected, display only border
dc.Draw3dRect(&rect, GetSysColor(COLOR_3DDKSHADOW), GetSysColor(COLOR_3DDKSHADOW));


//Set text
dc.DrawText(str, rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

dc.SetTextColor(RGB(255, 0, 0));
}
else if(lpDrawItemStruct->itemData & ODS_HOTLIGHT)
{
//Set color to background color, achieving border invisible effect
dc.FillSolidRect(&rect, RGB(170,180,255));
//Set text
dc.DrawText(str, rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

dc.SetTextColor(RGB(255, 0, 0));
}
else
{
//Set color to background color, achieving border invisible effect
dc.FillSolidRect(&rect, ::GetBkColor(dc));


//Set text
dc.DrawText(str, rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

dc.SetTextColor(RGB(255, 0, 0));
}

//CBrush* pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
//CBrush* pOldBrush = dc.SelectObject(pBrush);
//dc.SelectObject(pBrush);

//dc.SelectObject(pOldBrush);

}