首先回顾下C语言在控制台下通过标准输入输出函数输出"Hello,world!"的程序, 代码如下
#include <stdio.h> int main() { printf( "Hello,world! " ) ; return 0 ; }
然后今天上了第一趟VC++课后,学会了Windows版Hello,world!,代码如下:
#include<windows.h> int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) { MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 ); return 0; }
在VC6.0环境下,新建WIN32 Application,选中C++Sources文件,添加cpp文件后,敲出如上代码,编译,运行,出现下面窗口:
这个对话框中, 有标题栏, 标题栏的内容是"HELLO", 对话框的内容为"Hello,world!", 还有一个"确定"按钮, 而且, 没有那个黑框框窗口, 一切看起来都是那么美好, 来一起看看这段Windows版的Hello,world!吧!
*关于windows.h头文件:
在windows.h这个头文件中, 实际上已经包含了若干的其他相关的头文件, 用书上的话说, windows.h是个非常重要的包含文件, 其中包含的其他比较重要的头文件有:
■ WINDEF.H 基本数据类型定义
■ WINNT.H 支持Unicode的类型定义
■ WINBASE.H 内核函数
■ WINUSER.H 用户界面函数
■ WINGDI.H 图像设备接口函数
不过我还是好奇windows.h到底包含了那些头文件, 找到VC6的安装目录, 打开Include文件夹, 找到WINDOWS.H并打开, 虽说看不太懂, 但找#include关键词还是无压力的.
除去上面的5个还有:
■ WINRESRC.H ■ EXCPT.H ■ STDARG.H ■ WINNLS.H ■ WINCON.H
■ WINVER.H ■ WINREG.H ■ WINNETWK.H ■ CDERR.H ■ DDE.H
■ DDEML.H ■ DLGS.H ■ LZEXPAND.H ■ MMSYSTEM.H ■ NB30.H
■ RPC.H ■ SHELLAPI.H ■ WINPERF.H ■ WINSOCK2.H ■ MSWSOCK.H
■ WINSOCK.H ■ WINCRYPT.H ■ COMMDLG.H ■ WINSPOOL.H ■ OLE.H
■ OLE2.H ■ WINWLM.H ■ WINSVC.H ■ MCX.H ■ IMM.H
*程序的入口
在Win32控制台程序(Win32 Console Application)中, 应用程序的入口为main()函数, windows程序的程序入口和win32控制台程序的入口类似, 为WinMain()函数.
程序的入口函数在WINBASE.H作出了声明, 声明如下:
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd );
其中由声明可以看出, WinMain函数的返回值被定义为int型;
WINAPI为WinMain函数的调用规则, 在WINDEF.H对"WINAPI"作出了如下宏定义:
#define WINAPI __stdcall
说明, WinMain函数的调用规则为"__stdcall"方式, 对于"__stdcall"调用规则, 现在暂时先不去深究, 知道有这么回事就行, 以后会详细了解到的, 现在如果深究"__stdcall"就偏离了这篇博文的主题。
*WinMain函数的参数:
1>. WinMain的第一个参数 HINSTANCE hInstance, 用书上的解释为"实例句柄", 由于第一次接触C语言Windows程序设计, 对这个句柄的概念也不是很了解, 去百科了下, 句柄的解释为"一个句柄是指使用的一个唯一的整数值,即一个四字节长的数值,来标志应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。"——引用自百度百科->句柄。
笔者是这样对句柄进行理解的, 在一个应用程序中, 通常创建了很多的窗口、按钮、标签, 或者使用了一个文件等, 在程序的任何地方, 只要能够获得这个被称为句柄的东西, 就能够找到该控件或者窗口在内存中的位置, 从而对其进行操作。感觉有点像带参数的main函数, 只是这里的主函数参数为一个句柄。
2>. WinMain函数的第二个参数, 同样是个实例句柄, 但书上又进一步解释说在32位的Windows程序设计中, WinMain函数的实例句柄概念已不再采用, 因此WinMain的第二个参数通常总是NULL。
笔者的见解: 感觉马上就要晕了, 疑问一: "因此WinMain的第二个参数通常总是NULL", 那么第一个呢?WinMain的第一个参数会不会也可以是NULL呢? 疑问二: WinMain函数的参数从何而来?是操作系统么?带着疑问继续向下看。
3>. WinMain的第三个参数是用来运行程序的命令行, PSTR: 用来指向一个字符串的指针类型, szCmdLine, sz:表示以0结尾的字符串; 目的是通过命令行方式运行程序并向主函数中传入参数, 应该就像给main函数传入参数一样;
4>. WinMain的第四个参数是一个int型参数, 用来指明程序(窗口)最初如何被显示, 例如最小化?最大化?全屏?
笔者的见解: 应该很有用, 经常见一些游戏一启动就是全屏的, 但是这个参数也是操心系统传给程序的么?因为从平时运行Windows程序时都是直接双击, 并没有通过命令行给它传入参数, 在编程时应该对程序启动时的显示方式有交代才对, 这样系统再运行时再把这个交代的参数传入给程序告诉程序启动时应该如何显示.
*WinMain函数函数体的MessageBox函数:
MessageBox(), 名如其"人", 不用猜也知道这个就是显示一个对话框的函数, 打开API文档,MSDN Library通过索引找到MessageBox函数, 发现其声明如下:
int MessageBox(
HWND hWnd, // handle of owner window, 窗口的一个句柄
LPCTSTR lpText, // address of text in message box, 一个文本(字符串)的指针
LPCTSTR lpCaption, // address of title of message box, 标题字符串的指针
UINT uType // style of message box, 对话框的风格
);
在上面示例中对MessageBox函数的调用如下:
MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 );
第一个参数窗口的句柄的实参为NULL, 意思为不属于任何窗口.
第二个参数为对话框的内容, 第三个参数为对话框的标题, 但是这两个参数都使用了一个TEXT()的函数, 书上讲使用TEXT()的目的是将这些字符串打包到TEXT宏代码里面, 笔者尝试了不用这个TEXT()函数而直接像这样:
MessageBox( NULL, "Hello,world!", "MessageBox", 0 );
在VC6.0不会报错,在VS2010下会报错,这个TEXT其实是为了支持不同字符编码的预编译设置,如果定义了UNICODE宏,则TEXT(“”str“”)展开为宽字符串L“str”,反之则展开为“str”。这个问题我查了很多资料,详细都记在笔记本中。
第四个参数为对话框的风格, 一些以MB_开头的一些常量的组合, 可以使用OR(|)运算进行组合, 这些常量定义在WINUSER.H中, 例如常用的有:
1>.对话框按钮类型:
#define MB_OK 0x00000000L //仅有一个"确定"按钮
#define MB_OKCANCEL 0x00000001L //"确定" + "取消"
#define MB_ABORTRETRYIGNORE 0x00000002L //"终止" + "重试" + "忽略"
#define MB_YESNOCANCEL 0x00000003L //"是" + "否" + "取消"
#define MB_YESNO 0x00000004L //"是" + "否"
#define MB_RETRYCANCEL 0x00000005L //"重试" + "取消"
2>.对话框中的图标类型:
#define MB_ICONHAND 0x00000010L //一个红X的错误/停止图标
#define MB_ICONQUESTION 0x00000020L //一个问号的询问图标
#define MB_ICONEXCLAMATION 0x00000030L //一个黄色感叹号的警告图标
#define MB_ICONASTERISK 0x00000040L //一个带有i的信息提示图标
同时, 在这些图标中有的还可以用其他名称代替, 这些别名在WINUSER.H的定义如下:
#define MB_ICONWARNING MB_ICONEXCLAMATION //警告
#define MB_ICONERROR MB_ICONHAND //错误
#define MB_ICONINFORMATION MB_ICONASTERISK //信息
#define MB_ICONSTOP MB_ICONHAND //停止
------------------------------------------------------------------