第一章 不能免俗的“Hello, World!”
在这一章里,就像所有的入门级教程一样,我也将不能免俗地以一个“Hello, World!”程序开始我的教程。然后,我将逐步深入,向你介绍这个ATL版本程序中所有必要的信息。此外,我还将介绍一些Win32中你可能不知道的东西,包括WinMain的_t兼容以及如何在MessageBox中加入自己的图标等等。
接近,接近,再接近……
可以说,所有“Hello, World!”程序的内容不外乎都是以十分有限的几行代码向当前的目标屏幕环境上输出一个字符串“Hello, World!”。这个程序通常具有以下几个特点:
- 排除印刷错误的可能性,几乎所有的初学者都可以照葫芦画瓢地独立书写、编译并运行这个程序。
- 这个程序可以体现出当前语言环境的典型配置方式。
- 这个程序中具有当前语言特定的程序入口点。
- 这个程序中含有一条当前环境典型的输出语句(通常也是最简单、最常用的),由这条语句来输出“Hello, World!”字符串。
- 从这个程序可以很清楚的了解当前语言环境下程序运行的典型流程。
- 这个程序可能还会表现当前语言的一些其它特点。
那么,首先让我以最简单的C语言版“Hello, World!”开始吧:
#include <stdio.h>
int main() { printf( "Hello, World!\n" ); return 0; } |
虽然是不到10行的代码,但它仍然五脏俱全。现在,就由我将它和上述的特点对号入座吧。也就是说,这个程序能体现出C程序设计的以下特点:
- C语言的程序以main函数作为程序入口点。
- printf是C中用来输出字符串的代码。
- 函数是C语言程序的基本单位,它通常由返回值、函数名、参数列表、函数体、return组成。
- 调用函数的时候要include相应的头文件。
- \n是C语言中的转义字符,代表换行符。
接下来,我们来看一看Win32版的“Hello, World!”:
#include <windows.h>
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { MessageBox( NULL, TEXT("Hello, World!"), TEXT("Hello"), 0 ); return 0; } |
这个程序告诉你了以下几件事:
- 所有Win32下的C程序都需要包含windows.h头文件。
- Win32下的程序是以WinMain作为程序入口点的,而不是main。
- Win32下最常用输出信息的方法是MessageBox。
- WINAPI是Win32 API函数的调用约定,也就是__stdcall。
- HINSTANCE、LPSTR都是Win32自定义的数据类型,分别表示应用程序实例句柄和以空字符结尾的ANSI字符串指针。
- TEXT宏用于在源代码一级保证ANSI/Unicode字符串的兼容。
如果你对以上的几个知识点仍然有些许迷茫,请参考Charles Petzold的《Programming Windows》(中译《Windows程序设计》)的第一章。这段代码就是几乎原封不动地搬过来的。不过,我在编写这段代码的时候,通常会这么写:
#include <windows.h> #include <tchar.h>
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd ) { MessageBox( NULL, _T("Hello, World!"), _T("Hello"), 0 ); return 0; } |
是的,有几个地方有些不一样,我对它们的解释是:
- tchar.h中包含了对C runtime library中ANSI/Unicode字符串的源代码级兼容。
- _tWinMain提供了对命令行参数lpCmdLine的ANSI/Unicode源码级兼容。
- _T宏亦包含在tchar.h之中,它的作用和TEXT宏一样,但它比TEXT宏更加短小,因此可以节省编码的时间。
现在我可以告诉你,随着我们的步步接近,接下来ATL版的“Hello, World!”程序就要出现在我们的眼前了。那么,就让我们来看看这个犹抱琵琶半遮面的家伙吧。(请注意,虽然这是一个ATL版本的程序,但是你仍然需要建立一个Win32 Application的工程,而不是用ATL/COM Wizard。)
////////////////////////////////////////////////////////////////////////// // ATL的GUI程序设计配套源代码 // 第一章 不能免俗的“Hello, World!” // 工程名称:HelloWorld // 作者:李马 // http://www.titilima.cn //////////////////////////////////////////////////////////////////////////
#include <atlbase.h> CComModule _Module;
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd ) { _Module.Init( NULL, hInstance ); MessageBox( NULL, _T("Hello, World!"), _T("Hello"), 0 ); _Module.Term(); return 0; } |
也许有些陌生了,不过所幸它并无太多的变化——毕竟整个代码段就没有多长。好了,这一节的内容就到这里,希望李马的这种渐近的方法没让大家觉得一切来得太突然。大家可以喝口水先,然后做个深呼吸再,因为接下来我们就要开始接触真正的ATL程序了。