一个月学会VC++2010 3.我们动手吧!
中国的文人,有个根深蒂固的传统:皓首穷经。
从三百千千,到四书五经,到诸子百家,诗词歌赋,琴棋书画,每个学子往往要经历漫长的十几年甚至三十年。所谓十年寒窗无人问,一朝成名天下知,是所有文人的潜藏情节。所以,有老实人说出了老实话:百无一用是书生。我一直觉得他们仿佛在学东方不败大侠,先对自己狠心点,然后闭门苦练,最后终于明白了万物滋生的大道,乃至所向无敌。
作为普通人,我们还是尽早动手为好。
第一项任务很简单,精确点描述是这样的:创建一个应用程序,使用两个Ribbon按钮,在两个窗体中切换。
是啊,用户做的第一件事情,就是找到功能,然后进入相应的界面,菜单、工具栏还有Vc++2010提供的Ribbon功能区方式,无论怎样,这都是首先要掌握的内容。
站在程序员的角度,你最经常遇见的可能是哪些场景呢?界面、读写文件、读写数据库、设计业务类,就这些,做得专业点,号称程序员就顺理成章了。我觉得各种知识的讲解很多,但如何在实际工作中,做到像模象样,好象没有多少这样的资料。因此,这个系列讲解的虽然只是一项不太复杂的功能,但会尽量的讲透,涉及到界面、性能、异常、用户体验诸方面。
因为是首次接触VC,那么我给自己定下的规矩很明确:学习阶段,绝不考虑重用性问题、绝不考虑扩展性问题、绝不考虑代码风格问题,尽量在第一时间将功能稳定的实现。在不熟悉语言的时候,你七七八八太多,那简直是在易做图自己的大脑。语言熟悉后这些东西你有精力再去玩,现在,还是老实点好。
那么,我们首先面临的问题是使用传统的菜单、工具栏形式,还是使用Ribbon界面。这种选择对于我来说,不是什么问题,喜新厌旧据说是男人的本能,嗯,照照镜子,我发现里面是一张男人胡子拉碴的脸。然后呢?我遇到的第一个问题,是文档视图结构。
这是一种延续了几十年的模式,换句话说,是一种古老的模式。大家看看记事本就知道了,处理一种后缀名为TXT的文件,打开、关闭、保存文件,将文件后缀在操作系统注册到记事本,简单的说,就是你创建的这种应用,将针对某种专用的格式,相关的一些处理工作,由文档视图结构预先的帮你做好,很贴心,是不是?
所谓文档视图结构,马上动手,用项目向导创建一个简单的单文档、单视图结构的应用,可以看到VS帮我们创建的一些代码,嗯,四个类:一个应用程序类,是整个系统的入口,然后创建MainFrame实例、后者将管理文档类和视图类。文档类负责处理对这种格式的文档的各类操作,视图类负责呈现、编辑这种格式的文档。
但是,两个问题:首先,我们现在已经很少敢于制定自己专有的文件格式,比如各类视频格式,都是几家恐怖的巨头在发布标准然后互相撕咬。一个可怜的程序员竟然做这种不合身份的事情,实在令人齿冷。其次,相对于专有格式而言,我们做桌面应用普遍还是以数据库应用居多。
所以我的想法很简单,文档类基本不用,放个空壳在哪里。视图类呢?首先我想找寻类似Wpf的窗体设计器,视图能不能直接的“画界面”?很沮丧,不能,我只找到了对话框设计器。接下来,我们知道,若视图继承于CFormView,则可以使用对话框设计器来设计界面。 但这样我们需要做多视图项目,
为了利用对话框的界面设计能力、同时保持整个程序的简单,浮现在我脑子里的,是一种古怪的想法:对话框有一种“子对话框”风格,我们在视图中直接打开这个对话框,则看起来是无缝集成的,我们就能自如的在两个对话框之间切换了。
嗯,有熟悉的程序员马上要问了:不是有基于对话框的应用程序向导吗?两个问题:首先我们希望的是处理多个窗体,但不要弹出,这个是木有办法的;其次,更重要的是,这时候你不能在应用程序向导中选择Ribbon方式,也许有“在对话框应用中使用Ribbon“之类的深入研究,但我确实很懒惰,不太愿意在这类事情上消耗时间。
接下来,我按照工作的步骤,简单的描述完成这项任务的过程。需要说明的是,这个系列的帖子是休闲贴,我不会一边做一边截图一边写,时间和精力不允许,所以很难做到step by step的方式,仅仅是列出步骤和基本的知识点,当然也包括初学者肯定会闹出的笑话。
1、创建项目:创建一个MFC应用,在配置向导中,注意勾上“功能区方式”,提供文档视图支持,单文档模式,其他无所谓。项目创建完毕后,运行一下。
2、简单的阅读一下生成的代码,次序是App类->MainFrame类->Document类->View类。不要深究,比如View中那堆很混乱的宏,只要从字面理解就行了:定义消息循环,不需要学究到一定要弄懂这堆宏究竟会转换成怎样的代码。读代码的方法,嘿嘿,这是秘籍:看看类结构,揣摩一下方法的名字,然后不要太关注每个函数内部的代码,会很快的。需要注意的问题,是我们经常见到的项目按文件夹组织的方式,这里没有,VC项目中叫做筛选器,仅仅将同一个目录下的文件分类,并不改变文件的物理位置。
3、我们将创建两个对话框,注意:style设为child,去掉确定和取消按钮,不要边框。仅仅放上一个静态文本字段,分别是“第一个”和“第二个”。
4、我们要为两个对话框创建类,这个不要傻乎乎的自己写代码:右键,为对话框生成类,就行了。为什么要有这个步骤?对话框以“资源”形式保存,仅仅保留了一个唯一的ID和控件类型、位置、大小等信息,我们毕竟要通过代码控制其工作,那么创建类绑定这个对话框就是必须要做的事情。
我不太喜欢用记事本写程序那一套,今后自然会理解:类向导自动的帮我们创建对应的对话框类,一般是继承自一个公用的基类,添加消息循环等代码片段,重写一些虚方法。
5、那么,我们在Ribbon设计器中,创建一个“面板”,然后放上两个按钮。
6、当然,需要为两个按钮创建“添加消息处理程序”,也是在Ribbon设计器中,右键,就能看到了。针对消息类型“Command"”和“Update_Command_UI”都要创建,前者是用户点击按钮后要做的事情,后者我们用来处理按钮是否可用的问题,当然,这两个方法添加到View类中。
7、我们现在有了四个消息处理函数,以Command为例,怎样在视图中显示一个对话框?
8、看看下面的代码:
void CSouGuView::OnButtonHome()
{
if (CurrentDialog) //如果已经有对话框打开了,干掉它。
{
CurrentDialog->DestroyWindow();
delete CurrentDialog;
}
CHomeDialog* dlg = new CHomeDialog(this); //创建对话框类的实例
CurrentDialog =dlg; //我们在View中定义的CDialogEx* CurrentDialog; 我们创建的对话框类都是从CDialogEx继承的,因此,这个指针用来表示当前显示的窗体。
CurrentDialog->Create(dlg->IDD,this); //这里创建窗体
CurrentDialog->ShowWindow(SW_SHOW); //显示窗体
CurrentDialog->CenterWindow(this);//将对话框在视图中居中,注意屏幕大小改变后,就不再居中,需要在OnSize事件中处理
CurrentDialog->SetBackgroundColor(RGB(255,255,255));//将背景色改为白色,马虎应付一下
}
9、然后看看消息循环中的代码:
BEGIN_MESSAGE_MAP(CSouGuView, CView)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP()
ON_COMMAND(ID_BUTTON_HOME, &CSouGuView::OnButtonHome)
ON_WM_SIZE()
ON_UPDATE_COMMAND_UI(ID_BUTTON_HOME, &CSouGuView::OnUpdateButtonHome) //注意这句,如果对应的对话框已经打开,则按钮不可用
ON_COMMAND(ID_BUTTON_QUOTE, &CSouGuView::OnButtonQuote) //注意这一句:如果用户点击这个按钮,执行OnButtonQuote方法。
ON_UPDATE_COMMAND_UI(ID_BUTTON_QUOTE, &CSouGuView::OnUpdateButtonQuote)
ON_COMMAND(ID_BUTTON_CHART, &CSouGuView::OnButtonChart)
ON_UPDATE_COMMAND_UI(ID_BUTTON_CHART, &CSouGuView::OnUpdateB
补充:软件开发 , Vc ,