请看一个例子:
1
#include <windows.h>
2
#include <tchar.h>
3
4
5
int APIENTRY _tWinMain(
6
HINSTANCE hInstance,
7
HINSTANCE hPrevInstance,
8
LPSTR lpCmdLine,
9
int nCmdShow
10
)
11

{
12
UNREFERENCED_PARAMETER( hInstance );
13
UNREFERENCED_PARAMETER( hPrevInstance );
14
UNREFERENCED_PARAMETER( lpCmdLine );
15
UNREFERENCED_PARAMETER( nCmdShow );
16
17
HWND hwnd = ::GetDesktopWindow();
18
19
::MessageBox( hwnd, _T( "First Windows" ), _T( "Example" ), MB_OK );
20
21
return 0;
22
}
这个例子是大山哥哥在他的BLOG中Windows API精讲一日一练的例子。
奇怪吧,这次的WinMain函数又不一样了。Windows编程难学,就是因为它那么多宏,它伟大之处也是因为它的宏,可以屏蔽硬件层、字符集对程序的影响。
一般的WinMain函数是这样写的: int WINAPI WinMain(...),那现在的这种又是怎样出来的呢?
APIENTRY在程序就是一个宏:#define APIENTRY WINAPI,那么我们就可以不管那个前缀了。
你肯定想不到的是,_tWinMain也是一个宏。它是定义在<tchar.h>中的。你可以试试将#include <tchar.h>去掉,你的程序肯定找不到入口点。
同样的,_T也是一个宏。
这两个宏其实是为了适应UNICODE和以前单字符的应用程序。
由于Windows这两个API的定义是不一样的,如下:
UNICODE的定义:
#define _tWinMain wWinMain
单字符的定义:
#define _tWinMain WinMain
只要经过这样的宏定义后,就可以适应不同字符宽度的函数接口了。
好,看函数里面。
函数里面第一句又是一个宏,晕...怎么老是它...不过要在Windows编程,必须爱上它。
这个宏与Windows API无关,UNREFERENCED_PARAMETER 展开传递的参数或表达式,其目的是避免编译器关于未引用参数的警告。当然你也可以在编译器属性那里
修改编译的警告级别。
例子中的4句宏,就是为了关掉编译器对WinMain函数4个参数未引用的报错。避免了几个警告的产生,呵呵。。。
GetDesktopWindow这个该不是宏了吧,哈哈。。。
MSDN上说:The GetDesktopWindow function returns a handle to the desktop window. The desktop window covers the entire screen.
The desktop window is the area on top of which other windows are painted.
这个函数返回了桌面的Handle,桌面大家都知道吧?
MessageBox想不到也是一个宏,它的定义是:
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
很明显是为了兼容字符集参数而定义的。难道Windows API函数的参数有字符串的,都是一个宏吗?
MessageBox可能见得很多,最怕的大概就是“警告:内存出错,程序退出”了。
这是MessageBox函数的声明
int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
参数一hWnd是一个HWND,它是这个MessageBox属于的窗口的HWND,如果它为NULL,则MessageBox不属于任何一个窗口。
参数二lpText是这个MessageBox显示的消息内容,为了迎合Microsoft的好意,我们都应该用宏来传入参数,来兼容字符串。
参数三lpCaption是这个MessageBox的标题内容。
参数四uType则是这个MessageBox的类型,它可以改变整个MessageBox的行为和样式哦。它是一组符号标识(flags),如:MB_OK。可以用"|"操作符来进行组合
返回值呢?当然是你在MessageBox上的操作啦。返回值一般用宏来表示,如:IDABORT,IDOK。