# 工具栏简述

Windows 下的工具栏通常是指放置工具的容器。
通常我们能在一些软件的菜单栏下见到,各类样式的图形按钮,被框在一栏中,这便是工具栏。

# 添加工具栏资源

  1. 右键 项目添加 -> 资源
  2. 选择 Toolbar ,点击 新建 ,进入资源编辑界面。
  3. 自行折腾编辑界面,随便画几个图案,这就是你工具栏里面的工具按钮
  4. 设置资源 ID,这里我将工具栏 ID 设置为 IDR_TOOLBAR_1 ,工具按钮的 ID 依次为 ID_TOOLBAR_BUTTOR_1ID_TOOLBAR_BUTTOR_2ID_TOOLBAR_BUTTOR_3

资源编辑界面示范:

# 使用工具栏

工具栏的使用与菜单类似,只需要映射 WM_COMMAND 消息即可。

代码示例
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
#include <afxwin.h>
#include <afxext.h>

#include "resource.h"

class CMyFrameWnd :public CFrameWnd {
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT pCs);
afx_msg void OnClose();

afx_msg void OnMenu_File_New();
afx_msg void OnContextMenu(CWnd* wnd, CPoint pos);

afx_msg void OnToolBar_1();
afx_msg void OnToolBar_2();
afx_msg void OnToolBar_3();

private:
CMenu* m_pMenu;
CToolBar* m_pToolBar;
};

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
ON_WM_CREATE()
ON_WM_CLOSE()

ON_COMMAND(ID_MENU_FILE_NEW, OnMenu_File_New)
ON_WM_CONTEXTMENU()

ON_COMMAND(ID_TOOLBAR_BUTTON_1, OnToolBar_1)
ON_COMMAND(ID_TOOLBAR_BUTTON_2, OnToolBar_2)
ON_COMMAND(ID_TOOLBAR_BUTTON_3, OnToolBar_3)
END_MESSAGE_MAP()

afx_msg int CMyFrameWnd::OnCreate(LPCREATESTRUCT pCs) {
// Menu
m_pMenu = new CMenu;
m_pMenu->LoadMenu(IDR_MENU_TOP);
SetMenu(m_pMenu);

// ToolBar
m_pToolBar = new CToolBar;
m_pToolBar->CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP);
m_pToolBar->LoadToolBar(IDR_TOOLBAR_1);
return CFrameWnd::OnCreate();
}

afx_msg void CMyFrameWnd::OnClose() {
if (m_pMenu) {
delete m_pMenu;
m_pMenu = nullptr;
}

if (m_pToolBar) {
delete m_pToolBar;
m_pToolBar = nullptr;
}
CFrameWnd::OnClose();
}


void CMyFrameWnd::OnContextMenu(CWnd* wnd, CPoint pos) {
CMenu* pNewMenu = m_pMenu->GetSubMenu(0);
pNewMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, pos.x, pos.y, wnd);
}


afx_msg void CMyFrameWnd::OnMenu_File_New() {
AfxMessageBox(L"new");
}


afx_msg void CMyFrameWnd::OnToolBar_1() {
AfxMessageBox(L"button 1");
}

afx_msg void CMyFrameWnd::OnToolBar_2() {
AfxMessageBox(L"button 2");
}

afx_msg void CMyFrameWnd::OnToolBar_3() {
AfxMessageBox(L"button 3");
}



class CMyWinApp :public CWinApp {
public:
CMyWinApp() {

}
virtual BOOL InitInstance() {
CMyFrameWnd* frame = new CMyFrameWnd;
frame->Create(nullptr, L"MFCBase");
m_pMainWnd = frame;
frame->ShowWindow(SW_SHOW);
frame->UpdateWindow();
return TRUE;
}
};

CMyWinApp g_theApp;

代码并不复杂,在上一节代码的基础上进行了如下部分修改:

  1. 引入头文件 afxext.h
  2. CMyFrameWnd 类添加私有成员 m_pToolBar
  3. CMyFrameWnd::OnCreate 函数中使 m_pToolBar 指向新创建的对象,并进行工具栏的加载
  4. 处理 WM_COMMAND 消息的映射

# 工具栏把手

工具栏不仅仅只能固定在菜单栏下方,它是可以拖动,漂浮的。
而工具栏的把手,就是工具栏中,被允许被鼠标拖拽的控制区域。

# CBRS_GRIPPER

需要为工具栏添加把手时,需要在 CToolBar::CreateEx 函数中添加 CBRS_GRIPPER 样式。

# CToolBar::EnableDocking

用于指定工具栏可以停放到窗口中的何处

# CFrameWnd::EnableDocking

用于指定框架窗口允许被工具栏停放的位置

# CFrameWnd::DockControlBar

设置工具栏当前停放的位置

# 允许任意停放的工具栏

代码示例
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
#include <afxwin.h>
#include <afxext.h>

#include "resource.h"

class CMyFrameWnd :public CFrameWnd {
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT pCs);
afx_msg void OnClose();

afx_msg void OnMenu_File_New();
afx_msg void OnContextMenu(CWnd* wnd, CPoint pos);

afx_msg void OnToolBar_1();
afx_msg void OnToolBar_2();
afx_msg void OnToolBar_3();

private:
CMenu* m_pMenu;
CToolBar* m_pToolBar;
};

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
ON_WM_CREATE()
ON_WM_CLOSE()

ON_COMMAND(ID_MENU_FILE_NEW, OnMenu_File_New)
ON_WM_CONTEXTMENU()

ON_COMMAND(ID_TOOLBAR_BUTTON_1, OnToolBar_1)
ON_COMMAND(ID_TOOLBAR_BUTTON_2, OnToolBar_2)
ON_COMMAND(ID_TOOLBAR_BUTTON_3, OnToolBar_3)
END_MESSAGE_MAP()

afx_msg int CMyFrameWnd::OnCreate(LPCREATESTRUCT pCs) {
// Menu
m_pMenu = new CMenu;
m_pMenu->LoadMenu(IDR_MENU_TOP);
SetMenu(m_pMenu);

// ToolBar
m_pToolBar = new CToolBar;
m_pToolBar->CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER);
m_pToolBar->LoadToolBar(IDR_TOOLBAR_1);
m_pToolBar->EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(m_pToolBar);
return CFrameWnd::OnCreate(pCs);
}

afx_msg void CMyFrameWnd::OnClose() {
if (m_pMenu) {
delete m_pMenu;
m_pMenu = nullptr;
}

if (m_pToolBar) {
delete m_pToolBar;
m_pToolBar = nullptr;
}
CFrameWnd::OnClose();
}


void CMyFrameWnd::OnContextMenu(CWnd* wnd, CPoint pos) {
CMenu* pNewMenu = m_pMenu->GetSubMenu(0);
pNewMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, pos.x, pos.y, wnd);
}


afx_msg void CMyFrameWnd::OnMenu_File_New() {
AfxMessageBox(L"new");
}


afx_msg void CMyFrameWnd::OnToolBar_1() {
AfxMessageBox(L"button 1");
}

afx_msg void CMyFrameWnd::OnToolBar_2() {
AfxMessageBox(L"button 2");
}

afx_msg void CMyFrameWnd::OnToolBar_3() {
AfxMessageBox(L"button 3");
}



class CMyWinApp :public CWinApp {
public:
CMyWinApp() {

}
virtual BOOL InitInstance() {
CMyFrameWnd* frame = new CMyFrameWnd;
frame->Create(nullptr, L"MFCBase");
m_pMainWnd = frame;
frame->ShowWindow(SW_SHOW);
frame->UpdateWindow();
return TRUE;
}
};

CMyWinApp g_theApp;

代码并不复杂,就留给读者自行调试了。