天天看点

由MessageBox和AfxMessageBox的使用异同所感

我记得刚开始学图形界面编程的时候,接触的最早的一个函数应该就是MessageBox,之前都一直是控制台程序,突然能运行蹦出一个对话框感觉还是很新鲜的。当时还利用MessageBox写一些恶搞程序,利用上面的yes or no 按钮进行判断等等。但是说实话感觉用处不是特别大,调试的时候可能会用到,所以也就没有深入的研究和学习这个函数。后来转到MFC了,不知怎的吧,就用起了AfxMessageBox,也是没觉得什么,所以也就没多想什么,直到今天,项目中碰到了个问题,才导致我不得不研究一下MessageBox和AfxMessageBox两者的异同点。

那么我遇到的问题是什么呢?我在主对话框中有一个按钮,点击之后能弹出一个非模态的对话框,那么可能在子对话框中就有一些相应的操作要进行,刚开始并没有发觉哪里不妥。大家知道,弹出非模态的对话框,它并不阻塞父窗口,但是焦点却是在子对话框上,也就是当两者有层叠关系时,你点击父窗口的边框,父窗口并不会像我们预期的那样跳到最上面,却仍然是子对话框在最上面。这就比较不爽了,于是我参照了一个前辈的方法,具体见:

实现仿QQ主界面置顶(非模态对话框的显示问题)

如文中所示的方法后,我发现确实不同了,子对话框和父对话框重叠的时候,具有焦点的那个会被放到最上面。此时,我便遇到今天我要说的问题了。我项目中遇到提示信息需要用户注意的基本都是Afxmessagebox来实行。那么当我在子对话框中进行一些操作,弹出提示信息后,我们预期的是这个小的对话框应该出现在子对话框上面,但是让我意想不到的是,它出现在了父对话框的上面,也就是说,此时,父对话框跑到了子对话框之上,而这个弹出的对话框又在其之上。我马上就明白,这绝对是因为窗口句柄的关系,因为我项目中写的基本是AfxMessageBox(“xxxxxxx”,MB_OK)之类的,所以应该再加个句柄就行了,但是加进去不对了,提示调用参数太多了,这才又去查看了万能的百度,这才成为我想写这篇博客的动因。

那么Afx是什么呢?afx其实是微软的一个小组名称,Application Framework技术团队,名为AFX小组,用以开发C++对象导向工具给Windows应用程序开发人员使用,x并没有含义。Afx框架函数实现都是调用API函数的,你可以在VC中找到任意一个框架函数比如AfxMessageBox,单击右键选转到定义就可以看到它的源码了,它的函数体里面还是要调用MessageBox的。那么此处我就明白了,Afxmessagebox是微软对win32API函数messagebox的一个封装,专门用在MFC中.既然说到这了,虽然一直听说过win32 api 和mfc,但两者到底有什么关系呢?

Win32通常是指sdk编程方法,app没有被封装,开发人员需要自己搭程序框架;mfC则是以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。更多更细致的区别见博客:

mfc与win32区别

这里我就把它摘抄过来了:MFC就是 微软给你包装了的库,提供了很多扩展功能,以及高级功能,这样方便你使用,而不是自己从头调用API来实现,而API由于是MFC下一层,自然实现更灵活,可以根据你的需要来使用,不会被MFC类库所限制。‍win32和mfc编程的最大不同是win32是编程者自己把消息和响应函数联系在一起。mfc是编程者采用微软为我们做好了Messagemap机制,来处理消息。

mfc是便利的,为什么有人不用呢?不用mfc的人群往往是从DOS时代开始从事窗口编程的人,他们早在mfc出世之前就编得一手好程序。长期的编程过程中,每人,每个TEAM都拥有了自己的消息处理机制程序库或类库。当然有很多人认为他的类库比mfc使用方便。他开始为窗口编程的时候,mfc的TEAM的很多人还在学校里读书呢。如果不是从那个年代过来的人,还是用mfc吧!mfc是封装的类,最后还是会调用win32api win32api开发效率是底一些,但比较自由.

有时候mfc是封装的类不能满足我们的要求,这时就需要我们自己用api来开发啦 ‍MFC是专注于用户界面的,而Windows SDK专注于UI, console,Windows服务,嵌入式,驱动多种类型的程序, MFC是一套类库,适应范围窄,可以搞ERP软件,但效率不如其他语言高,而且类库并没有对DDK,openGL,D3D等专项领导的函数库进行封装。而Windows SDK提供了专题开发的平台。

MFC中对所有的句柄,对象,消息都进行了严格的检测,如果你不知道它的内部机制,随便调用函数很容易出错,而SDK提供的是一种宽松的开发环境,你可以用面向对象的思想定义自己的类,对界面控件进行封装。

在一些专题开发项目,你可以不懂MFC,但是在一些常规的软件开发,你必须熟悉MFC,同时还要懂SDK.‍ win32是windows下的最基本的编程方式,使用它得到的代码最干净最有效率,也是最底层,它是其它所有方式实现的基础。一般指只使用API和SDK。

MFC是对win32的封装,使用win32编程方法,写了一个又一个类,让我们不用再重复大量劳动。但毕竟是封装,所以不可能完全实现win32所有功能。用着虽然方便,但距离细节毕竟远了,在个性个、特殊化方面还有差距。 两者相比,win32更本质,MFC更抽像。

可能说的有点远,但其实没有,MessageBox是win32API函数,而AfxMessageBox是mfc里封装之后的函数。那么究竟两者有什么异同呢?

对于AfxMessageBox,定义如下:(来自百度百科)

int AfxMessageBox( LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0 );

int AFXAPI AfxMessageBox( UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp = (UINT) –1 );

在第一种形式中,lpszText表示在消息框内部显示的文本,消息框的标题为应用程序的可执行文件名(如Hello)。在第二种形式中,nIDPrompt为要显示的文本字符串在字符串表中的ID。函数调用时会自动从字符串表中载入字符串并显示在消息框中。nType为消息框中显示的按钮风格和图标风格的组合,可以采用|(或)操作符组合各种风格。

按钮风格

MB_ABORTRETRYIGNORE 消息框中显示Abort、Retry、Ignore按钮

MB_OK 显示OK按钮

MB_OKCANCEL 显示OK、Cancel按钮

MB_RETRYCANCEL 显示Retry、Cancel按钮

MB_YESNO 显示Yes、No按钮

MB_YESNOCANCEL 显示Yes、No、Cancel按钮

图标风格

MB_ICONINFORMATION 显示一个i图标,表示提示

MB_ICONEXCLAMATION 显示一个惊叹号,表示警告

MB_ICONSTOP 显示手形图标,表示警告或严重错误

MB_ICONQUESTION 显示问号图标,表示疑问

使用时,可以只调用AfxMessageBox(LPCTSTR lpszText);这样默认风格为AfxMessageBox(LPCTSTR lpszText,MB_OK|MB_ICONEXCLAMATION );

2返回值

编辑

返回值有8种,如果内存不够,则返回0,否则返回以下值中的一种,分别对应相应的按钮被点击:

IDABORT、IDCANCEL、IDIGNORE、IDNO、IDOK 、IDRETRY、IDYES。

MessageBox的定义如下:

MessageBox显示一个模态对话框,其中包含一个系统图标、 一组按钮和一个简短的特定于应用程序消息,如状态或错误的信息。消息框中返回一个整数值,该值指示用户单击了哪个按钮。

int WINAPI MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);

hWnd:

消息框的拥有窗此参数口。如果为NULL,则消息框没有拥有窗口。

lpText:

消息框的内容。如果使用了Unicode库,则把文本变成:

1TEXT(/sometext/)

lpCaption:

消息框的标题。如果使用了Unicode库,则把文本变成:

TEXT(/sometext/)

uType:

指定一个决定对话框的内容和行为的位标志集。此参数可以为下列标志组中标志的组合。指定下列标志中的一个来显示消息框中的按钮以及图标。

当然此处就可以明显的看到两者最大的不同在于messagebox第一个参数hWnd,AfxMessageBox是全局函数,在任何地方都能用,但MessageBox就不能如此用了,因为第一个参数的限制,它只能用在CWnd类和其派生类当中。那么至此,我觉得我的问题应该找到了,并能够解决了。想要在mfc里调用具有窗口句柄的messagebox,则应该这样

::MessageBox((GetSafeHwnd(),”text”,”title”,MB_OK)

其中GetSafeHwnd()函数获取当前对话框的窗口句柄。

那么在运行之后,点击弹出子对话框,再弹出提示消息,此时便和我们预想的效果是一样的了,提示的消息出现在子对话框之上,焦点任然是子对话框。

OK,至此,完成,我今晚的博客!加油!
          拙见,小记!