要跟计算机进行交互,就需要计算机显示信息给人看到,或者发出声音给人听到,然后人看到或听到相应的信息后,再输入其它信息给计算机,这样就可以让计算机进行数据处理,把结果显示给我们。现在就来编写一个最简单的Windows应用程序,让它提示一行文字给我们看到,这就是简单的目标。
它实现的源程序和界面如下:
上面这个图,是从VC++ 2005里截出来的。这样可以看到源程序和显示的界面,很清楚地知道那些内容在那里显示,显示窗口里的标题是例子,就是MessageBox里的字符串“例子”的显示。“第一个应用程序”也是那样显示出来的。第一个应用程序是非常简单的,下面再来详细地解说每行程序的作用。
源程序如下:
#001 // First.cpp : 应用程序入口文件
#002 //
#003
#004 #include "stdafx.h"
#005 #include "First.h"
#006
#007 //
#008 //第一个例子。
#009 //蔡军生 2007/07/02
#010 //
#011 int APIENTRY _tWinMain(HINSTANCE hInstance,
#012 HINSTANCE hPrevInstance,
#013 LPTSTR lpCmdLine,
#014 int nCmdShow)
#015 {
#016 UNREFERENCED_PARAMETER(hPrevInstance);
#017 UNREFERENCED_PARAMETER(lpCmdLine);
#018 UNREFERENCED_PARAMETER(hInstance);
#019 UNREFERENCED_PARAMETER(nCmdShow);
#020
#021 //获取桌面的句柄。
#022 HWND hWnd = GetDesktopWindow();
#023
#024 //显示一行消息。
#025 ::MessageBox(hWnd, _T("第一个应用程序"), _T("例子"), MB_OK);
#026
#027 //
#028 return 0;
#029 }
第4行是包含Windows的API头文件。在这个文件里包含一些系统的定义等。
第5行是包行C++的头文件。
第11行是定义WinMain的入口。
第16行到第19行是指明不生产这些参数不使用的警告。
第22行是获取桌面的句柄。
第25行是显示一个窗口提示信息。
第28行是返回程序出错码。
从上面这段程序就可以看到,
_tWinMain
是应用程序的入口函数,这里是使用它的宏,定义在
tchar.h
头文件里,为什么要这样作宏定义的呢?由于
Windows
的应用程序要适应
UNICODE
和以前单字符的应用程序,由于
Windows
这两个
API
的定义是不一样的,如下:
UNICODE
的定义:
#define _tWinMain wWinMain
单字符的定义:
#define _tWinMain WinMain
只要经过这样的宏定义后,就可以适应不同字符宽度的函数接口了。由于我是采用
UNICODE
编译的,所以这里使用
wWinMain
函数定义,下面再把它的定义找出来,如下:
int
WINAPI
wWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nShowCmd
);
这里要详细地解释一下函数
wWinMain
的参数,它有四个参数。
hInstance
是当前应用程序的实例句柄,一般用来区分不同的资源使用。
hPrevInstance
是以前
Win98
使用的句柄,在
Win2000
以后的操作系统里都是空值
NULL
。
lpCmdLine
是命令行参数,比如你在
Windows
开始菜单里运行一个程序,并添加参数在后面,就会传递给应用程序,后面再详细讨论。
nShowCmd
是窗口的显示方式,比如最大化显示,最小化显示,还是正常显示。
Windows
运行程序时,是通过运行库里的启动代码来调用
wWinMain
函数,它是在启动文件里如下调用:
#ifdef WPRFLAG
mainret = wWinMain(
#else /* WPRFLAG */
mainret = WinMain(
#endif /* WPRFLAG */
(HINSTANCE)&__ImageBase,
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
这就是操作系统传递给应用程序的值,现在就来演示使用第一个参数
hInstance
。
请看下面的例子:
#001 #include "stdafx.h"
#002 #include "First.h"
#003
#004 //
#005 //
第一个例子。
#006 //
蔡军生
2007/07/03
#007 //
#008 int APIENTRY _tWinMain(HINSTANCE hInstance,
#009 HINSTANCE hPrevInstance,
#010 LPTSTR lpCmdLine,
#011 int nCmdShow)
#012 {
#013 UNREFERENCED_PARAMETER(hPrevInstance);
#014 UNREFERENCED_PARAMETER(lpCmdLine);
#015 UNREFERENCED_PARAMETER(nCmdShow);
#016
#017 //
使用应用程序句柄
#018 const int MAXSIZE_APPBUF = 256;
#019 TCHAR wAppTile[MAXSIZE_APPBUF];
#020 LoadString(hInstance,IDS_APP_TITLE,wAppTile,MAXSIZE_APPBUF);
#021
#022 //
获取桌面的句柄。
#023 HWND hWnd = GetDesktopWindow();
#024
#025 //
显示一行消息。
#026 MessageBox(hWnd, _T("
第一个应用程序
"), wAppTile, MB_OK);
#027
#028 //
#029 return 0;
#030 }
这个例子是在前面的基础上修改的,主要添加了使用应用程序实例句柄。在第
19
行里定义了一个保存应用程序标题的缓冲区,然后在第
20
行里调用函数
LoadString
从应用程序的资源里加载字符串,它的第一个参数就使用到
hInstance
句柄。因此应用程序句柄是表示程序在资源上唯一的标识符。
Windows API一日一练(3)使用命令行参数
下面再接着练习使用命令行参数,先在
VC2005
调试设置里设置输入参数,如下图:
可以看到在
Command Arguments
里输入给程序传送的命令行参数(
cmd1 cmd2
命令行参数)。
接着修改原来的程序如下:
#001 int APIENTRY _tWinMain(HINSTANCE hInstance,
#002 HINSTANCE hPrevInstance,
#003 LPTSTR lpCmdLine,
#004 int nCmdShow)
#005 {
#006 UNREFERENCED_PARAMETER(hPrevInstance);
#007 UNREFERENCED_PARAMETER(nCmdShow);
#008
#009 //
使用应用程序句柄
#010 const int MAXSIZE_APPBUF = 256;
#011 TCHAR wAppTile[MAXSIZE_APPBUF];
#012 ::LoadString(hInstance,IDS_APP_TITLE,wAppTile,MAXSIZE_APPBUF);
#013
#014 //
获取桌面的句柄。
#015 HWND hWnd = ::GetDesktopWindow();
#016
#017 //
显示命令行参数。
#018 ::MessageBox(hWnd, lpCmdLine, wAppTile, MB_OK);
#019
#020
#021 //
显示一行消息。
#022 ::MessageBox(hWnd, _T("
第一个应用程序
"), wAppTile, MB_OK);
#023
#024 //
#025 return 0;
#026 }
#027
在上面的程序里添加了第
18
行的代码,用来显示程序命令行的参数。它的显示结果如下:
这样就可以看到
WinMain
两个参数的使用了。现在就使用了第一个
API
函数
WinMain
了,就是这么简单地就学会了使用第一个
API
函数。
Windows API一日一练(4)MessageBox函数
为了显示提示信息给用户,
Windows
是提供了一个非常方便的
API
函数
MessageBox
给用户使用,使用这个
API
函数可以显示简单的文字信息出来,提醒或提示用户进行下一步操作。
函数声明如下:
WINUSERAPI
int
WINAPI
MessageBoxA(
__in_opt HWND hWnd,
__in_opt LPCSTR lpText,
__in_opt LPCSTR lpCaption,
__in UINT uType);
WINUSERAPI
int
WINAPI
MessageBoxW(
__in_opt HWND hWnd,
__in_opt LPCWSTR lpText,
__in_opt LPCWSTR lpCaption,
__in UINT uType);
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
从上面可以看出,
Windows
的
API
是两种声明,一种是使用到
ANSI
编码,一种是使用到
UNICODE
编码的
API
函数。通过宏定义把这两种
API
名称统一到
MessageBox
的声明。这是一种使用选择不同
API
的技术,在今后的编程里,大多数都需要使用
UNICODE
编码了,因为可以适应不同国家的语言显示,可以国际化编程,特别对于中文支持更加需要
UNICODE
编程。
下面来解释一下参数的定义:
hWnd
是指向父窗口的句柄,如果没有父窗口,可以把这个参数设置为
NULL
。
lpText
是需要显示的文字。显示字符串的起始地址。
lpCaption
是在窗口上标题显示。
uType
是窗口组合按钮和显示图标的类型。后面再详细说明。
返回值
是一个整数,如果有取消按钮,并且按下
ESC
键就返回
IDCANCEL
。如果有其它按钮,并且按下,就返回相应的值。主要的值如下:
IDABORT
放弃按钮
IDCANCEL
取消按钮
IDCONTINUE
继续按钮
IDIGNORE
忽略按钮
IDNO
否按钮
IDOK
确定按钮
IDRETRY
重试按钮
IDTRYAGAIN
重试按钮
IDYES
是按钮
演示例子如下:
上面显示的代码是:
#001 //MB_DEFBUTTON4
#002 int CMsgBox::Show_MB_DEFBUTTON4(void)
#003 {
#004 //
显示
MB_DEFBUTTON4
。
#005 return ::MessageBox(NULL, _T("MB_YESNOCANCEL|MB_DEFBUTTON4|MB_HELP"),
#006 _T("
第一个应用程序
"), MB_YESNOCANCEL|MB_DEFBUTTON4|MB_HELP|MB_ICONQUESTION);
#007 }
uType
常用的选择值如下:
按钮类型:
MB_ABORTRETRYIGNORE
MB_CANCELTRYCONTINUE
MB_HELP
MB_OK
MB_OKCANCEL
MB_RETRYCANCEL
MB_YESNO
MB_YESNOCANCEL
图标类型:
MB_ICONEXCLAMATION
MB_ICONWARNING
MB_ICONINFORMATION
MB_ICONASTERISK
MB_ICONQUESTION
MB_ICONSTOP
MB_ICONERROR
MB_ICONHAND
设置缺省按钮值:
MB_DEFBUTTON1
MB_DEFBUTTON2
MB_DEFBUTTON3
MB_DEFBUTTON4
修改显示信息窗口的属性:
MB_APPLMODAL
MB_SYSTEMMODAL
MB_TASKMODAL
MB_RIGHT
MB_RTLREADING
MB_SETFOREGROUND
MB_TOPMOST
MB_SERVICE_NOTIFICATION
Windows API一日一练(5)RegisterClass和RegisterClassEx函数
为了可以创建自己的窗口,就需要向
Windows
操作系统注册窗口类型,以便后面创建窗口时调用。当然,如果使用
Windows
预先注册的窗口是不需要注册的。
函数声明如下:
#if(WINVER >= 0x0400)
WINUSERAPI
ATOM
WINAPI
RegisterClassExA(
__in CONST WNDCLASSEXA *);
WINUSERAPI
ATOM
WINAPI
RegisterClassExW(
__in CONST WNDCLASSEXW *);
#ifdef UNICODE
#define RegisterClassEx RegisterClassExW
#else
#define RegisterClassEx RegisterClassExA
#endif // !UNICODE
函数的输入参数是一个
WNDCLASSEXA
或
WNDCLASSEXW
的指针。这里主要介绍
UNICODE
版本的函数定义,
WNDCLASSEXW
的结构定义如下:
typedef struct tagWNDCLASSEXW {
UINT cbSize;
/* Win 3.x */
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCWSTR lpszMenuName;
LPCWSTR lpszClassName;
/* Win 4.0 */
HICON hIconSm;
} WNDCLASSEXW, *PWNDCLASSEXW, NEAR *NPWNDCLASSEXW, FAR *LPWNDCLASSEXW;
cbSize
是本结构的字节大小,一般设置为
sizeof(WNDCLASSEXW);
style
是窗口类型。
lpfnWndProc
是窗口处理消息的回调函数。
cbClsExtra
是窗口类型的扩展。
cbWndExtra
是窗口实例的扩展。
hInstance
是窗口实例句柄。
hIcon
是窗口图标。
hCursor
是窗口的光标。
hbrBackground
是窗口背景颜色。
lpszMenuName
是窗口菜单名称。
lpszClassName
是窗口类型的名称。
hIconSm
是窗口小图标。
调用这个函数的实例如下:
#001 //
#002 //
函数
: MyRegisterClass()
#003 //
#004 //
目的
:
注册一个窗口类型
.
#005 //
#006 //
蔡军生
2007/07/12
#007 //
#008 ATOM MyRegisterClass(HINSTANCE hInstance)
#009 {
#010 WNDCLASSEX wcex;
#011
#012 wcex.cbSize = sizeof(WNDCLASSEX);
#013
#014 wcex.style = CS_HREDRAW | CS_VREDRAW;
#015 wcex.lpfnWndProc = WndProc;
#016 wcex.cbClsExtra = 0;
#017 wcex.cbWndExtra = 0;
#018 wcex.hInstance = hInstance;
#019 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTWIN));
#020 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
#021 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
#022 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TESTWIN);
#023 wcex.lpszClassName = szWindowClass;
#024 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
#025
#026 return RegisterClassEx(&wcex);
#027 }
第
10
行定义一个窗口结构的对象
wcex
。
第
12
行设置窗口结构的大小。
第
14
行设置窗口类型。
第
15
行设置窗口消息处理函数
WndProc
。
第
16
行设置窗口类型的扩展为空。
第
17
行设置窗口实例的扩展为空。
第
18
行设置窗口当前实例句柄
hInstance
。
第
19
行设置窗口图标。
第
20
行设置光标为箭头。
第
21
行设置窗口背景颜色为白色。
第
22
行设置窗口菜单。
第
23
行设置窗口类型名称。
第
24
行设置窗口小图标。
第
26
行是调用函数
RegisterClassEx
注册这个窗口类型。
如果注册成功,返回这个窗口类型的标识号,可以用标识号进行创建窗口,查找窗口和注销窗口类型等等。如果失败返回的值是空,因此可以通过检查返回值为判断是否调用成功。
from: http://blog.csdn.net/caimouse/article/category/49656/6