学习MFC有一段时间了,很想通过一个小的项目类似的工程熟悉一下MFC的整个工作流程和熟悉一些基本用到的函数和需要注意的逻辑。所以心血来潮开始写一个小的考勤管理的软件,写的过程中也发现了很多需要解决的问题,为了记住这些东西,决定把整个过程给一步一步的记录下来,方便自己记忆的同时,也可以让有想自己学习做一个小的系统的同学学习一下,还可以让有不同见解的朋友做一个交流。
首先,做一个软件的话要有一些自己的想法,也就是我们所说的需求,要实现那些功能,每个地方需要用什么来实现,下面给出我这次想做出来的界面。
下面,我们就一步一步的来分解整个程序是怎么实现的。
- 新建一个项目->选择MFC应用程序,随便取一个名(这里我们去PersonManage)。
- 在MFC Application Wizard里面的Application Type里面选择Single Document,剩下的步骤中一路点击Next。
到这里为止,我们就建好了一个新的空白的单文档项目PersonManage。下面,我们首先来实现工具栏,这是第一个问题,如何实现工具栏加载icon图标,也就是自定义工具栏图标。
首先,我们选择好自己需要的图标,把它们都拷贝到一个文件夹里面去,然后放入项目工程里面(这里我们把它们都放置到项目里面的\res\Icon目录下面)。然后在我们的rc文件中在icon的位置添加下面的代码。
///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDR_MAINFRAME ICON "res\\PersonManage.ico" IDR_PersonManageTYPE ICON "res\\PersonManageDoc.ico" IDI_CLOSE ICON "res\\Icon\\Close.ico" IDI_FIRST ICON "res\\Icon\\First.ico" IDI_HELP ICON "res\\Icon\\Help.ico" IDI_LAST ICON "res\\Icon\\Last.ico" IDI_NEXT ICON "res\\Icon\\Next.ico" IDI_PRE ICON "res\\Icon\\Pre.ico" IDI_SAVE ICON "res\\Icon\\Save.ico" IDI_DELETE ICON "res\\Icon\\Deleteq.ico"
在resource.h中也要记得定义这些文件id
#define IDI_CLOSE 130 #define IDI_DELETE 131 #define IDI_FIRST 132 #define IDI_PRE 133 #define IDI_NEXT 134 #define IDI_LAST 135 #define IDI_SAVE 136 #define IDI_HELP 137
最后在CMainFrame的OnCreate(LPCREATESTRUCT lpCreateStruct)函数下面添加如下代码。
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; 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("未能创建工具栏\n"); return -1; // 未能创建 } ////////////////////////////////////////////////////////////////////////// // 自定义工具栏图标 static CImageList m_Imagelist; m_Imagelist.Create(48, 48, ILC_COLOR32 | ILC_MASK, 8, 1); //创建图像列表 m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_CLOSE)); m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_DELETE)); m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_FIRST)); m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_PRE)); m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_NEXT)); m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_LAST)); m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_SAVE)); m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_HELP)); m_wndToolBar.GetToolBarCtrl().SetImageList(&m_Imagelist); m_wndToolBar.SetSizes(CSize(60, 60),CSize(48, 48)); ////////////////////////////////////////////////////////////////////////// if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("未能创建状态栏\n"); return -1; // 未能创建 } // TODO: 如果不需要工具栏可停靠,则删除这三行 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar);
关于上面的这段代码,有几点需要特别的解释和说明,(1)这种方法只能在VS2010一下版本的开发工具下面运行(我用的是VS2005),因为在VS2010后,MFC中的工具栏调用的是CMFCToolBar类,而不是以前的CToolBar类,在CMFCToolBar类中,已经不存在GetToolBarCtrl()这个函数,所以这里会报错。(2)代码中的这一句(m_Imagelist.Create(48, 48, ILC_COLOR32 | ILC_MASK, 8, 1))中的参数的意思需要解释一下。
函数原型:BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow);
cx ,cy:
图片的实际像素宽与高,我们选择的图片是48*48的icon
nFlags:
创建图像列表的类型,包括4/8/16/24/32/位色,
nInitial :
创建ImageList初始包括的图像个数,这里我们初始的icon个数是8个,可参照上面的图片。
nGrow
当初始分配的图像个数不够的时候,新增一个图片时,指定图象列表能增加的新图象个数,图像列表空间不够而继续添加image时,将按照nGrow继续分配空间,设计时根据具体情况设置合适的值,避免内存频繁的改变图像列表而過度頻繁而使系統记忆体碎片化。
至此,Toolbar的实现我们就讲到这里,下一篇我们将继续了解下一个问题,怎么调用一个gridctrl控件和这个控件的一些用法。