利用定时器和SetWindowLong函数就可以实现该功能。
9.3.1加载图标资源
首先将三个图标资源放到res目录下。接着Insert\Resource->Import->找到res目录,选中上述三个图标资源导入。
这样资源视图Icon中就有了三幅新图标:IDI_ICON1,IDI_ICON2,IDI_ICON3。如图。
然后,在框架类中,定义一个图标句柄数组的成员变量,框架类上鼠标右键进行添加。如图。
接下来就在框架类的OnCreate函数中利用LoadIcon函数来加载这三个图标,同时初始化图标句柄数组。
extern CStyleApp theApp;
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
……
// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_ERROR));
m_hIcons[0]=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));
m_hIcons[1]=LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));
m_hIcons[2]=LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3));
return 0;
}
LoadIcon函数如果使用系统图标,第一个参数就为NULL;否则设置为应用程序的当前实例句柄。获取应用程序的当前实例句柄有三种方式:
1、通过调用AfxGetInstanceHandle()函数获取当前实例句柄。
2、CStyleApp类有一个数据成员:m_hIstance,标识了当前应用程序的实例。
theApp是CStyleApp类型的全局对象。但是在一个源文件中调用另一个源文件的全局变量,先要在框架类OnCreate函数之前进行声名:
extern CStyleApp theApp;
3、MFC提供了一个全局函数:AfxGetApp(),可以获得当前应用程序对象的指针,利用AfxGetApp()函数的返回值来访问应用程序的m_hIstance数据成员。
第二个参数需要的是图标的名称或者图标资源标识字符串,而我们只有图标资源的ID,通过MAKEINTRESOURCE将资源ID转换成资源标识字符串。
9.3.2定时器的处理
本例设置时间间隔为1000ms触发一次定时器消息。
在OnCreate函数最后加上:SetTimer(1,1000,NULL);
然后为框架类添加WM_TIMER消息的响应函数,并在该响应函数中调用SetClassLong函数改变应用程序窗口的图标。
void CMainFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
static int index=0;
SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcons[index]);
index=++index%3;
CFrameWnd::OnTimer(nIDEvent);
}
作为静态的局部变量,它将存放在程序的数据区中,而不是在栈中分配。
因为第三个参数需要LONG类型,而m_hIcons类型是HICON。因此需要强制类型转换。
如果希望应用程序启动后不再显示原来的图标,而是直接显示自定义的图标。
需要在SetTimer(1,1000,NULL);之前添加:
SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcons[0]);
9.4工具栏编程
在ResourceView->Toolbar->IDR_MIANFRAME。
双击这个资源ID,就可以打开工具栏资源,这是一些带有位图图标的按钮,通过这些位图就大概知道每个按钮的功能。
双击这些位图,就可以查看工具栏上某个按钮的属性。如图。
可以发现子菜单文件下新建菜单项的ID与工具栏上面的按钮ID相同,通过使用工具栏上面的按钮将会更加便捷。
9.4.1在工具栏上面添加和删除按钮
添加的方法:
首先单击工具栏上面组后一个空白按钮,并设置外观,如图。将其ID设置为IDM_TEST。
然后再在帮助的子菜单下添加一个菜单项,ID设置为IDM_TEST,Caption设置为Test,添加命令消息响应函数OnTest。
void CMainFrame::OnTest()
{
// TODO: Add your command handler code here
MessageBox("Test");
}
可以单击菜单项,也可以单击工具栏按钮进行运行。如图。
工具栏有一条竖线,称为分隔符,在工具栏资源视图中,将T按钮向旁边移动一点,就会在中间出现分隔符,进行区分。
删除工具栏上面按钮:在资源编辑窗口,在此按钮中按下鼠标左键,将其拖出工具栏,松开鼠标左键就将该按钮从工具栏上面删除了。
9.4.2创建工具栏
框架类中定义了一个CToolBar类型的成员变量:m_wndToolBar,CToolBar就是一个工具栏类,派生于CControlBar类,后者派生于CWnd类,因此工具栏也是一个窗口。
创建工具栏的方法1:
创建工具栏资源;
构造CToolBar对象;
调用Create或CreateEx函数创建Windows工具栏,并把已创建的CToolBar对象关联起来。
调用LoadToolBar函数加载工具栏资源。
BOOL Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP, UINT nID = AFX_IDW_TOOLBAR );
第一个参数是父窗口指针;第二个参数指定工具栏样式:子窗口(WS_CHILD),可视(WS_VISIBLE),停靠在窗口顶部(CBRS_TOP)
第三个参数指定工具栏子窗口的ID。
BOOL CreateEx(CWnd* pParentWnd, DWORD dwCtrlStyle = TBSTYLE_FLAT, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect rcBorders = CRect(0, 0, 0, 0), UINT nID = AFX_IDW_TOOLBAR);
该函数第一个、第三个与第五个参数与上述函数参数相同。
第二个参数工具栏上控件创建时的扩展风格,默认为TBSTYLE_FLAT。
第四个参数指工具栏窗口边框的宽度。
创建工具栏的方法2:
构造CToolBar对象
调用Create或CreateEx函数创建Windows工具栏,并把已创建的CToolBar对象关联起来。
调用LoadBitmap函数加载包含工具栏按钮图像的位图。
调用SetButtons函数设置按钮的样式,并把工具栏上的一个按钮与位图中的一个图像相关联。
MFC创建工具栏的过程:
MFC自动创建的工具栏的代码存在于框架类的OnCreate函数中
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
……
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
……
// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
……
}
先是调用CreateEx函数创建程序的工具栏对象,然后调用LoadToolBar函数加载工具栏资源:IDR_MAINFRAME
然后调用工具栏对象的EnableDocking成员函数设置工具栏停靠的位置,这里设置为允许停靠在客户区的任意一边。
后者是框架类对象调用EnableDocking成员函数,目的是让主框架窗口可以停靠。
最后调用DockControlBar函数,让工具栏停靠在主框架窗口上。
创建自定义的工具栏:
首先得插入一个新的工具栏资源:第一种方法Insert\Resource->选中ToolBar->单击New;第二种方法资源视图下->鼠标右键单击ToolBar->Insert ToolBar。
然后该程序中就插入了一个名为IDR_TOOLBAR1的工具栏资源,添加三个按钮。如图。
接下来就是要构造一个CToolBar对象,右键单击框架类,添加一个CToolBar类型的成员变量。名称为m_newToolBar,如图。
然后利用Create或CreateEx函数创建工具栏,并于CToolBar对象相关联。这里可以复制框架类OnCreate函数中前面的代码。但是对象名改为m_newToolBar,资源ID为IDR_TOOLBAR1。然后停靠位置设为CBRS_RIGHT。
然后调用函数允许新工具栏任意停靠到客户区,由于主框架窗口在前面已经停靠,可以不写,最后调用DockControlBar将新工具栏停靠到主框架窗口上。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
……
SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcons[0]);
SetTimer(1,1000,NULL);
if (!m_newToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_RIGHT
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_newToolBar.LoadToolBar(IDR_TOOLBAR1))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
m_newToolBar.EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_newToolBar);
return 0;
}
现在在查看子菜单下添加一个菜单项,ID为IDM_VIEW_NEWTOOLBAR,Caption为新的工具栏。该菜单项主要用来显示和隐藏新建的工具栏。
接着为框架类添加该菜单项的命令消息响应函数,因为工具栏本身也是窗口,可以调用CWnd类ShowWindow函数让其显示和隐藏。
void CMainFrame::OnViewNewtoolbar()
{
// TODO: Add your command handler code here
if(m_newToolBar.IsWindowVisible())
{
m_newToolBar.ShowWindow(SW_HIDE);
}
else
{
m_newToolBar.ShowWindow(SW_SHOW);
}
RecalcLayout();
DockControlBar(&m_newToolBar);
}
单击菜单项,发现工具栏没有消息,只是上面的按钮消失了。如图。
这是因为窗口上的工具栏被隐藏后,停靠在窗口上的其他控制条对象位置有可能变动,这时需要在最后调用框架类的RecalcLayout成员函数来重新调整它们的位置:RecalcLayout();
将工具栏拖到窗口中间的某个位置,让它处于浮动状态,单击查看下的菜单项,会发现工具栏上面的按钮消失了,但是工具栏仍然存在。原因就是工具栏再次显示和隐藏后,需要再次调用框架类DockControlBar函数,让工具栏停靠在主框架窗口上。
单击菜单项,确实可以隐藏,但是再次单击发现工具栏停靠在客户区顶部了。如图。
那么如何将新建的工具栏从原处显示出来呢?这就需要用到CMainFrame类ShowControlBar函数。
void ShowControlBar( CControlBar* pBar, BOOL bShow, BOOL bDelay );
第一个参数指向将要显示或隐藏的控制条;第二个参数若为TRUE就显示指定的控制条,FALSE就指隐藏指定的控制条;第三个参数TRUE表示延迟显示控制条,FALSE表示立即显示控制条。
void CMainFrame::OnViewNewtoolbar()
{
// TODO: Add your command handler code here
ShowControlBar(&m_newToolBar,!m_newToolBar.IsWindowVisible(),FALSE);
}
利用该函数将比较简洁地实现相关功能。
下面为新的工具栏的菜单项设置复选标记,因此需要为这个菜单项添加UPDATE_COMMAND_UI消息响应函数。右键单击该菜单项,选择ClassWizard。
然后在该消息响应函数内部添加:
void CMainFrame::OnUpdateViewNewtoolbar(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetCheck(m_newToolBar.IsWindowVisible());
}
选中,就显示工具栏;未选中,就隐藏工具栏。如图。