Windows下的C和C编程.docx
《Windows下的C和C编程.docx》由会员分享,可在线阅读,更多相关《Windows下的C和C编程.docx(55页珍藏版)》请在冰豆网上搜索。
Windows下的C和C编程
Windows下的C/C++编程
对于任何一种编程语言,都会以一个最基本的程序入门,就是大家都很熟悉的HelloWorld。
那么,我们也从这里开始吧。
最简单的Windows程序
1)TC中的HelloWorld
相信对于下面的TurboC程序大家都不会陌生,这就是最简单的TC经典入门程序:
#include
main()
{
prinft(“HelloWorld!
”);
}
这个程序将在DOS模式中输出“HelloWorld”。
2)最简单的Windows下的HelloWorld
其实,下面的程序并不是标准的Windows应用程序,它不产生传统意义上的窗口,而只是跳出一个对话框。
让我们详细的操作一下:
首先从开始菜单中选择MicrosoftVisualC++6.0(其他版本也行);(见图1-1)
图1-1MicrosoftVisualC++6.0
然后通过File菜单中的new选项新建一个工程。
在Projects选项中选择Win32Application;然后指定工程名,这里是:
HelloWorld;再指定存储路径,这里是D:
\DirectX8.0游戏编程\;最后点击OK。
(见图1-2)
图1-2Projects选项Win32Application
下面出现以下窗口,选择Anemptyproject;点击OK。
(见图1-3)
图1-3Anemptyproject
这样,就创建了一个空的工程,工程名为HelloWorld,存储路径为D:
\DirectX8.0游戏编程\下的HelloWorld文件夹。
下一步,在空的工程中加入C语言的源程序文件。
在VisualC++6.0的File菜单中选择new选项;在弹出的File菜单中选择C++SourceFile;选中Addtoproject选框;选中加入到那个工程中,这里是HelloWorld,就是刚才创建的工程;填写文件,这里是HelloWorld,下面是工程的存放路径;最后,选择OK。
(见图1-4)
图1-4工程的存放路径
这样,就在刚才的空工程中加入了一个文件,可以在Vc的FileView框中看到它,右边是它的编辑框,在那里编写源程序。
(见图1-5)
图1-5Vc的编辑框
那么,加入如下代码:
#include
intWINAPIWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPSTRlpcmdLine,
intnCmdShow)
{
MessageBox(NULL,TEXT("HelloWorld!
")
TEXT("My1stProgram"),MB_OK);
return0;
}
然后,选择执行,或者直接按F5键。
就会得到如下的执行结果:
一个弹出的对话框(见图1-6)。
图1-6HelloWorld弹出框
3)程序分析
和TC程序比较,这个Windows程序基本相同。
包含了头文件,有一个主函数,在主函数中调用了一个系统函数,主函数返回一个整数值。
每个语句以分号结束,复合语句用大括号包含。
下面对它进行详细的分析。
4)程序的参数
下面,对上面的程序的参数从上至下进行分析。
◆#include
程序包含了一个头文件windows.h,基本上所有的Windows程序都会包含这个文件。
它定义了Windows的基本数据类型、数据结构、系统函数等。
◆intWINAPIWinMain
Tc中的程序是以main函数为程序入口的,而Windows程序是以WinMain函数为入口的,这个函数的定义如下:
第一个参数hInstance是当前实例句柄,为一个整数,用于标识窗口、程序等。
第二个参数hPrevInstance被置为NULL。
第三个参数lpcmdLine是运行程序的命令行。
第四个参数nCmdShow用于指定程序窗口最初的显示模式,可以在初始是指定是正常还是最大化等。
WinMain函数返回一个整数。
WINAPI用于指定调用约定,具体在WINDEH.H中定义。
◆MessageBox
MessageBox是一个WindowsAPI函数,用于弹出一个对话框,显示一些简短的信息。
定义如下:
第一个参数hWnd是一个窗口句柄,表明对话框所属的窗口。
第二个参数lpText是一个字符串,表明需要显示的信息。
TEXT是一个宏。
第三个参数lpCaption是一个字符串,表明对话框的标题。
第四个参数uType用于指定对话框中的按钮和图标。
(见表1-1)各种按钮和图标类型可以同时使用,用“|”连接,如“MB_OK|MB_ERROR”。
类型
按钮
图标
MB_OK
确定
-----
MB_OKCANCEL
确定和取消
-----
MB_YESNO
是和否
-----
MB_INFORMATION
-----
提示
MB_WARNING
-----
警告
MB_ERROR
-----
出错
表1-1按钮和图标
Windows应用程序
1)真正的HelloWorld
上一节中,实现了Windows弹出一个对话框,显示了一个简短的信息“HelloWorld”。
但是,这和平时看到的大多数Windows应用程序不太一样,没有窗口,没有最大化、最小化按钮等。
虽然如此,它还是相当重要的,特别在显示出错或提示信息时尤为简便。
下面,来看一看一个真正的Windows窗口程序。
同样,创建一个新的工程,这里是HelloWorldWindows(见图1-7):
图1-7HelloWorldWindows工程
然后加入一个新的C++源文件(其实可以看成是C源文件,只是换了后缀名),文件名为WinHelloWorld。
下面是程序的代码。
#include
LRESULTCALLBACKWndProc(HWND,UINT,
WPARAM,LPARAM);
intWINAPIWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,LPSTRlpcmdLine,intnCmdShow)
{
staticTCHARszAppName[]=TEXT("HelloWorld");
staticTCHARszClassName[]=TEXT("HelloWorldClass");
HWNDhwnd;
MSGmsg;
WNDCLASSwndclass;
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=
(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.LpszMenuName=NULL;
wndclass.lpszClassName=szClassName;
if(!
RegisterClass(&wndclass))
{
MessageBox(NULL,TEXT("Thisprogram
requiresWindowsNT!
"),
szAppName,MB_ICONERROR);
return0;
}
hwnd=CreateWindow(szClassName,
TEXT("MyHelloWorldtoWindowsProgram"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,
hInstance,
NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
returnmsg.wParam;
}
LRESULTCALLBACKWndProc(HWNDhwnd,
UINTmessage,
WPARAMwParam,
LPARAMlParam)
{
HDChdc;
PAINTSTRUCTps;
RECTrect;
switch(message)
{
caseWM_CREATE:
MessageBox(NULL,"Hello
World!
","HelloWorld",MB_OK);
MessageBeep(MB_OK);
return0;
caseWM_PAINT:
hdc=BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&rect);
DrawText(hdc,TEXT("Hello,Windows!
"),
-1,&rect,
DT_SINGLELINE|DT_CENTER
|DT_VCENTER);
EndPaint(hwnd,&ps);
return0;
caseWM_DESTROY:
PostQuitMessage(0);
return0;
}
returnDefWindowProc(hwnd,message,wParam,lParam);
}
运行这个程序,将得到如下结果:
首先弹出一个对话框,并且伴随一个很熟悉的“当”的一声(见图1-8):
图1-8HelloWorld弹出框2
点击确定以后,关闭这个对话框,打开了一个Windows窗口(见图1-9):
图1-9Windows窗口
这个窗口大家因该很熟悉了吧。
一个标准的Windows窗口,可以最大化、最小化、拖动等。
好,接下来仔细分析一下整个程序的代码。
当然,没有必要去记住这些所有的代码,基本上也没有人记得住,以后在使用的时候,可以直接复制过去,然后作相应的修改就行了。
2)Windows类
在程序分析之前,先说明一些基本的新的东西。
◆数据类型
在这里,出现了一些在TC中没有见过的数据类型。
这些是Windows程序的一些常见数据类型。
基本上,它们的命名与相应的英文含义相同,或是在前面加上表示类型的字母,如32位的类型加上L,不过部分因为Windows版本的变迁而失去了原来的意义,只是沿用以前的名字。
详细的说明以后会慢慢熟悉,下面列举了一些常用的前缀和表达的意义(见表1-2):
前缀
表示的数据类型
c
char
by
BYTE(无符号字符)
n
short
x、y
int(表示x坐标和y坐标)
cx、cy
int(表示x方向长度,y方向长度)
w
WORD
l
LONG
p
pointer(指针)
sz
stringendedwithzero(以0结尾的字符串)
s
string
dw
DWORD
fn
Function(函数)
b
BOOL(int)
表1-2常用的前缀
◆函数
这里,除了MessageBox之外,还有一些WindowsAPI函数,下面列表说明(见表1-3):
API函数
作用
LoadIcon
加载程序图标
LoadCursor
加载鼠标
GetStockObject
获取图形设备对象
RegisterClass
注册窗口类
CreateWindow
创建窗口
ShowWindows
显示窗口
UpdateWindow
刷新窗口
GetMessage
从消息队列中获取消息
TranslateMessage
转换消息
DispatchMessage
发送消息
MessageBeep
发出系统声音
BeginPaint
开始在用户区绘制
GetClientRect
取得用户区
DrawText
显示文本
EndPaint
结束绘制
PostQuitMessage
插入推出消息
DefWindowProc
执行缺省的消息处理
表1-3WindowsAPI函数
好,现在来看看Windows类。
Windows窗口类规定了窗口的一些基本特征,如显示方式、名称、风格等等。
创建的窗口是属于窗口类的一个具体的实例,由窗口类可以创建多个窗口。
就像房子的窗户一样,窗户类定义了窗户是用来采光、通风的、有一个外框、可以用一些材料封闭等;而窗户就是一个个窗户类的实例,当然,窗户有很多种,但是它们的基本特征就是上面所说得。
就像在房子上开一个窗户要准备一些材料、工具一样,在创建一个Windows窗口之前有一系列准备工作,要为窗口注册一个窗口类,告诉Windows希望创建一个什么样的窗口。
RegisterClass函数用于注册窗口类,它的定义如下:
如果调用成功,返回一个非零值,ATOM数据类型保证其返回的值在系统中是唯一的;调用失败,返回零。
RegisterClass函数的参数只有一个,是一个指向WNDCLASS数据类型的指针,WNDCLASS数据类型是一个结构,Windows有一个通用的定义:
typedefstruct_WNDCLASS
{
UNITstyle;
WNDPROClpfnWndProc;
IntcbClsExtra;
IntcbWndExtra;
HINSTANCEhInstance;
HICONhIcon;
HCURSORhCursor;
HBRUSHhbrBackground;
LPCTSTRlpszMenuName;
LPCTSTRlpszClassName;
}WNDCLASS;
看到这里大家因该想到些什么了吧。
对了!
在创建窗口之前要注册窗口,在注册窗口之前,就是要填充上面这个结构。
下面,一项项看:
◆首先,定义了一个WNDCLASS结构:
WNDCLASSwndclass;
下面就填充这个结构
◆wndclass.style=CS_HREDRAW|CS_VREDRAW;
表示当窗口的水平方向或垂直方向的大小发生变化时,完全刷新窗口,这使得Hello,Windows!
一直位于窗口的正中心。
◆wndclass.lpfnWndProc=WndProc;
设置窗口函数为WndProc。
这个函数处理窗口里的所有消息。
◆wndclass.cbClsExtra=0;
目前不使用,设为0。
◆wndclass.cbWndExtra=0;
目前不使用,设为0。
◆wndclass.hInstance=hInstance;
程序的句柄,也就是标识。
◆wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
设置图标,就是程序的图标,比如Windows记事本的图标就是一个小的翻开的记事本。
◆wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
设置鼠标,比如说游戏中的鼠标往往是不同形状的。
◆wndclass.hbrBackground=
(HBRUSH)GetStockObject(WHITE_BRUSH);
指定窗口背景色。
◆wndclass.LpszMenuName=NULL;
指定窗口菜单,置为NULL表示不需要菜单。
◆wndclass.lpszClassName=szClassName;
指定一个类名。
填充完这个结构后,就要注册窗口,而且要对返回值进行检验:
if(!
RegisterClass(&wndclass))
{
MessageBox(NULL,TEXT("Thisprogram
requiresWindowsNT!
"),
szAppName,MB_ICONERROR);
return0;
}
注册成功,就可以创建窗口了。
3)创建窗口
好了,既然决定了窗户的样子,就可以照着作了。
当然,还要决定窗户的位置等信息,这只要调用CreateWindows函数就可以了:
hwnd=CreateWindow(szClassName,
TEXT("MyHelloWorldtoWindowsProgram"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
这里,CreateWindow函数又出现了11个参数,来看看这些参数有些什么作用(见表1-4),表中的参数从上至下的对应上面CreateWindow函数的参数顺序:
参数
作用
szClassName
字符串,表示窗口类名称
TEXT("MyHelloWorldtoWindowsProgram")
字符串,用于显示窗口标题栏中的字
WS_OVERLAPPEDWINDOW
显示风格
CW_USEDEFAULT
窗口左上x坐标,这里用默认值
CW_USEDEFAULT
窗口左上y坐标,这里用默认值
CW_USEDEFAULT
窗口右下x坐标,这里用默认值
CW_USEDEFAULT
窗口右下y坐标,这里用默认值
NULL
父窗口句柄,NULL表示最高级
NULL
菜单句柄,NULL表示没有
hInstance
应用程序实例句柄
NULL
创建参数,这里置为NULL
表1-4CreateWindow函数参数
这里说明一下,WS_OVERLAPPEDWINDOW是标准窗口风格,包括一个标题栏、窗口图标、窗口标题、最小化按钮、最大化按钮、关闭按钮、可调边框。
下面是WS_OVERLAPPEDWINDOW的定义。
#defineWS_OVERLAPPEDWINDOW(WS_OPVERLAPPED|
WS_CAPTION|
WS_SYSMENU|
WS_THICKFRAME|
WS_MINIMIZEBOX|
WS_MAXIMIZEBOX)
CreateWindows函数创建个窗口,系统为这个窗口分配一定的资源,下一步就是在屏幕下显示了,也就是调用ShowWindow函数:
ShowWindow(hwnd,nCmdShow);
函数的第一个参数hwnd表示窗口的句柄,也就是这个窗口在系统中的唯一标识。
第二个参数nCmdShow是显示参数,用以指定窗口初始化时的状态,决定是最小化、最大化还是常规显示。
如果要自己设置初始状态,可以参照下面的表来进行(见表1-5):
参数
作用
SW_SHOWNORMAL
按常规显示窗口并激活
SW_SHOWMAXIMIZED
最大化显示窗口并激活
SW_SHOWMINIMIZED
最小化显示窗口并激活
SW_SHOWMININOACTIVE
最小化显示窗口,不激活
表1-5nCmdShow显示参数
接下来,调用UpdateWindow函数,通过窗口函数WndProc进行窗口的绘制:
UpdateWindow(hwnd);
4)主循环
在UpdateWindow(hwnd)语句之后,有一段循环语句,这就是Windows程序的消息循环。
在这里,指定了Windows程序从消息队列中取数据的方式和事件与消息的转换方式。
所谓的消息循环可以这样理解:
比如说,有时当连续按键盘时,屏幕上并不是同步显示,而是有一段时间延迟。
消息循环就是当触发一定的事件时(比如按键盘),主循环将它转换成消息,也就是Windows可以识别的信息,放入消息队列,等待系统以一定的方式进行读取。
下面的代码就是负责接受消息,并进行转换和发送,真正处理消息的函数稍后说明。
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage有4个参数,用一个表格来说明它们的作用(见表1-6):
参数
说明
msg
MSG类型,就是Windows消息结构
NULL
窗口句柄,NULL表示接受自己创建窗口的所用消息
0
提取消息的最小索引值,常与下一个参数同时置0
0
提取消息的最大索引值,置0表示提取所用消息
表1-6GetMessage参数
GetMessage(&msg,NULL,0,0)语句有一个返回值,当不为WM_QUIT(退出)时返回一个非零值,这时while循环为1,执行内部的语句;为WM_QUIT时返回一个零值,于是跳出while循环,执行推出程序。
当GetMessage返回一个非零值时,执行while循环内的语句,将消息传给Windows,进行转换:
TranslateMessage(&msg);
并由Windows发送到窗口函数,在这个程序中是WndProc函数:
DispatchMessage(&msg);
所有的流程可以通过下面的图来表示(见图1-10):
图1-10Windows程序流程
5)事件处理
好,现在清楚了WinMain函数的工作流程,那就进入到窗口函数中,看看WndProc函数。
从上面的流程图可以看出,这里,窗口函数处理所用的Windows消息,也就是说,这将是程序的核心,而WinMain函数仅仅是搭建了一个基本的框架。
看看窗