第1章 WINDOWS编程.docx
- 文档编号:3733770
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:22
- 大小:163.84KB
第1章 WINDOWS编程.docx
《第1章 WINDOWS编程.docx》由会员分享,可在线阅读,更多相关《第1章 WINDOWS编程.docx(22页珍藏版)》请在冰豆网上搜索。
第1章WINDOWS编程
第1章Windows编程
Windows是应用于微机上的图形化用户界面的操作系统。
它为应用程序提供了一个由一致窗口和菜单结构构成的多任务环境。
熟悉DOS环境下的软件开发的程序员很快就会发现,Windows编程与DOS环境下的编程相比有很大的不同。
在用VisualC++开发Windows应用程序时,主要使用两种方法,一种是使用Windows提供的WindowsAPI函数;另一种是直接使用Microsoft提供的MFC类库。
API是应用程序编程接口(applicationprogramminginterface)的缩写,WindowsAPI是Windows系统和Windows应用程序间的标准程序接口。
API为应用程序提供系统的各种特殊函数及数据结构定义,Windows应用程序可以利用上千个标准API函数调用系统功能。
API程序设计较繁琐,需要注册窗口类、编写消息循环,用繁琐的Switch/Case处理消息。
另外,API程序设计较少体现面向对象的程序设计方法,程序的可重用性较差。
MFC类库,封装了Windows的API、USER、KERNEL、GDI函数,定义了大量的类,完成了Windows程序所需的大部分功能。
程序员可以从这些类中派生自己的类,继承这些类的功能,并加上所需的特殊功能。
隐去了创建、维护窗口的许多复杂的例行工作。
使用MFC编程,可以利用MFC提供的大量类,花费较少的程序设计工作量,是使用最广泛的程序设计方法之一。
1.1用API编写Windows应用程序
为理解如何用WindowsAPI进行Windows编程,下面首先建立一个最简单的Windows应用程序。
【例1.1】建立一个名为Demo11的应用程序,显示欢迎信息。
在VisualC++中,打开File\NewsProjects,然后在列表中选择Win32Application,在ProjectName编辑框中输入工程文件名Demo11,在Location中指定应用程序创建的位置,单击OK按纽。
弹出Win32ApplicationStep1-1对话框,选择Anemptyproject,最后单击Finish按纽完成程序项目的建立。
再次打开File|New|File,然后在列表中选择C++SourceFile,选中AddtoProject复选框,在Filename编辑中输入文件名Demo11,系统创建并打开Demo11.cpp。
输入如下代码:
#include"windows.h"
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,
PSTRszCmdLine,intiCmdShow)
{
MessageBox(NULL,TEXT("你好,欢迎来到VisualC++"),TEXT("Welcome"),0);
return0;
}
编译并运行程序,结果如下图所示。
可以看到,如同在DOS中用语言编程一样,程序包含一个头文件windows.h,只是Windwos下的主函数变成了WinMain()函数。
MessageBox()是Windows一个很常用的API,用于显示指定信息。
为进一步理解Windows程序的编写,再举一例。
【例1.2】创建名为Demo12的应用程序,在屏幕上进行作图。
创建应用程序Demo12的过程同上例,在Demo12.cpp中添加以下代码。
//Windows.h文件中包含应用程序中所需的数据类型和数据结构的定义
#include
//窗口函数说明
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
//-----------------以下初始化窗口-----------------------------
intWINAPIWinMain(HINSTANCEhInstance,//WinMain函数说明
HINSTANCEhPrevInst,
LPSTRlpszCmdLine,
intnCmdShow)
{
HWNDhwnd;
MSGMsg;
WNDCLASSwndclass;
charlpszClassName[]="窗口";//窗口类名
charlpszTitle[]="My_Windows";//窗口标题名
//窗口类的定义
wndclass.style=0;//窗口类型为默认类型
wndclass.lpfnWndProc=WndProc;//窗口处理函数为WinProc
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=lpszClassName;//窗口类名为"窗口示例"
//--------------------以下进行窗口类注册--------------------------
if(!
RegisterClass(&wndclass))//如果注册失败则发出警告
{
MessageBeep(0);
returnFALSE;
}
//创建窗口
hwnd=CreateWindow(lpszClassName,//窗口类名
lpszTitle,//窗口实例的标题名
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)
{
switch(message)
{
HDChDC;//定义指向设备上下文的句柄
HBRUSHhBrush;//定义指向画刷的句柄
HPENhPen;//定义指向画笔的句柄
PAINTSTRUCTPtStr;//定义指向包含绘图信息的结构变量
caseWM_PAINT:
//处理绘图信息
hDC=BeginPaint(hwnd,&PtStr);
SetMapMode(hDC,MM_ANISOTROPIC);//设置映像模式
hPen=(HPEN)GetStockObject(BLACK_PEN);
//设置画笔为系统预定定义的黑色画笔
hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH);
//采用系统预定义的深灰色画刷
SelectObject(hDC,hBrush);//选择画刷
SelectObject(hDC,hPen);//选择画笔
RoundRect(hDC,50,120,100,200,15,15);//画圆角矩形
hBrush=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
//采用系统预定义的亮灰色画刷
SelectObject(hDC,hBrush);//选择画刷
Ellipse(hDC,150,50,200,150);//画椭圆
hBrush=(HBRUSH)GetStockObject(HOLLOW_BRUSH);
//采用系统预定义的虚画刷
SelectObject(hDC,hBrush);//选择画刷
Pie(hDC,250,50,300,100,250,50,300,50);//画饼形
EndPaint(hwnd,&PtStr);//结束绘图
return0;
caseWM_DESTROY:
PostQuitMessage(0);//调用PostQuitMessage发出WM_QUIT消息
default:
//默认时采用系统消息默认处理函数
returnDefWindowProc(hwnd,message,wParam,lParam);
}
return0;
}
运行程序,其结果如下图所示。
上述程序可能让初次接触Windows程序的用户理解起来很困难。
下面对程序作一个简单介绍。
在DOS下,C程序至少有一个main()函数。
Windows程序则至少有两个函数,一个是WinMain(),另一个是窗口过程函数WndProc(),其中WinMain()函数为应用程序的入口。
在Windows中,应用程序通过Windows完成指定操作,承担这项通信任务的API函数就是Windows的相应窗口函数WndProc。
在DOS程序中,程序能直接控制事件的发生顺序、结果等。
而在Windows系统中,应用程序不直接调用任何窗口函数,而是等待Windows调用窗口函数,请求完成任务或返回信息。
为保证Windows调用窗口函数,必须先向Windows登记,然后在Windows实施相应操作时回调,所以窗口函数又称为回调函数。
WndPro是一个主回调函数,Windows至少有一个回调函数。
回调函数WndProc在WinMain函数中通过语句wndclass.lpfnWndProc=WndProc指定。
一个Windows程序可分为以下几个过程:
●
(1)建立、注册窗口类:
用来完成窗口类型、窗口标题、风格等的指定。
●
(2)创建窗口:
按注册窗口完成窗口的建立。
●(3)显示和更新窗口。
●(4)创建消息循环;
●(5)处理消息:
根据消息,完成程序的相应功能。
Windows程序的驱动方式是事件驱动。
Windows系统是一个典型的“基于界面”(Message_Based)的操作系统,或称为“事件驱动”(Event_Driven)的操作系统。
因此,称Windows是一个事件驱动的操作系统。
1.2事件驱动
Windows程序设计围绕事件或消息的产生驱动运行处理函数(过程)。
所谓消息是描述事件发生的信息。
例如按下鼠标键时,系统就会产生一条特定的消息,标识鼠标按键事件的发生。
Windows程序的执行顺序取决于事件发生的顺序,程序的执行顺序是由顺序产生的消息驱动的,但是消息的产生往往并不要求有次序之分。
程序员可以针对消息类型编写程序以处理接收的消息,或者发出其他消息以驱动其他程序,但是不必预先确定消息产生的次序。
事件驱动程序模型如下图所示,输入界面1~3并没有固定的顺序,用户可以随机选取,以任何合理的顺序来输入数据。
1.3消息循环与输入
Windows操作系统用“消息(message)”这样一种数据结构来描述一个事件。
事件驱动围绕着消息的产生与处理展开,一条消息是关于发生的事件的消息。
事件驱动是靠消息循环机制来实现的。
消息是一种报告有关事件发生的通知。
消息类似于DOS下用户的输入,Windows应用程序的消息来源有以下4种:
(1)输入消息:
包括键盘和鼠标的输入。
这一类消息首先放在系统消息队列中,然后由Windows将它们送入应用程序消息队列中,由应用程序来处理消息。
(2)控制消息:
用来与Windows的控制对象,如列表框、按纽、检查框等进行双向通信。
当用户在列表框中改动当前选择或改变了检查框的状态时发出此类消息。
这类消息一般不经过应用程序消息队列,而是直接发送到控制对象上去。
(3)系统消息:
对程序化的事件或系统时钟中断作出反应。
一些系统消息,像DDE消息(动态数据交换消息)要通过Windows的系统消息队列,而有的则不通过系统消息队列而直接送入应用程序的消息队列,如创建窗口消息。
(4)用户消息:
这是程序员自己定义并在应用程序中主动发出的,一般由应用程序的某一部分内部处理。
Windows操作系统包括三个内核基本元件:
GDI、KERNEL、USER。
其中GDI(图形设备接口)负责在屏幕上绘制像素,打印硬拷贝输出,绘制用户界面等。
系统内核KERNEL支持与操作系统密切相关的功能。
USER为所有的用户界面对象提供支持,用于接收和管理所有输入消息、系统消息,并把它们发给相应的窗口的消息队列。
消息队列是一个系统定义的内存块,用于临时存储消息;或是把消息直接发给窗口过程。
每个窗口维护自己的消息队列,并从中取出消息,利用窗口函数进行处理。
消息驱动模型如图2.4所示。
图2.4消息驱动模型
1.4Windows程序运行机制
从2.3节的应用程序中可以看到,在Windows程序中,程序的基本单位已不是过程和函数,而是窗口。
窗口是Windows应用程序的基本操作单元,是应用程序与用户之间交互的接口环境,也是系统管理应用程序的基本单位。
编写一个Windows应用程序首先应创建一个或多个窗口,随后应用程序的运行过程即是窗口内部、窗口与窗口之间、窗口与系统之间进行数据处理与数据交换的过程。
1.4.1Windows程序界面
●1.程序界面
从程序设计的角度看,窗口是一个“对象(object)”,其“类(class)”特性由一个数据结构WNDCLASS描述:
typedefstruct_WNDCLASS
{
UINTstyle;
WNDPROClpfnWndProc;
intcbClaExtra;
intcbWndExtra;
HANDLEhInstance;
HICONhIcon;
HCURSORhCursor;
HBRUSHhbrBackground;
LPCTSTRlpszMenuName;
LPCTSTRlpszClassName;
}WNDCLASS;
其中:
style:
指定窗口类的风格(是否支持鼠标双击,滚动时是否重绘等)。
lpfnWndProc:
窗口消息处理函数(又称“窗口函数”)。
cbClsExtra:
指定内存中,在窗口类结构形成后,附加分配的字节数。
cbWndExtra:
指定内存中,在窗口实例形成后,附加分配的字节数。
hInstance:
程序“实例(instance)”。
Windows程序可以运行多个副本(同一个程序启动多次),每一个副本称为一个实例。
当程序启动时,操作系统把实例编号传送给程序。
hIcon:
程序图标(icon)的名柄(handle)。
句柄是一个整数值,可以被看成是一个对象的编号或指针,即句柄指向一个对象。
hCursor:
光标(cursor)句柄。
代表鼠标在客户区的形状。
hbrBackground:
背景画刷(brush)句柄。
表示客户区的背景颜色。
lpszMenuName:
指向菜单资源名的指针。
lpszClassName:
指向类名的指针
Windows程序界面如下图所示。
●2.Windows程序设计中的数据类型
在VisualC++中,编译程序定义了很多新的数据类型是。
例如:
数据类型
描述
BYTE
8位无符号整数
WORD
16位无符号整数
DWORD
32位无符号整数或地址
LONG
32位无符号整数
UINT
32位无符号数(unsignedint)
COLORREF
32位颜色值
LPARAM
32位无符号整数,表示函数参数
WPARAM
32位无符号整数,表示函数参数
LPCSTR
指向字符串常量的指针
LPSTR
指向字符的
LRESULT
窗口过程(函数)返回的32位
WNDPROC
指向窗口过程的指针
typedefstructtagPOINT
{
LONGx;
LONGy;
}POINT;//点的x,y坐标
同时Windows还指定了一些关键字,这些关键字定义了Win32中的函数中的有关参数和返加值的大小和意义。
Win32常用的关键字有:
数据类型
描述
HANDLE
定义一个32位无符号整数,用做句柄
HINSTANCE
定义一个32位的无符号整数,用做实例句柄
HWND
定义一个32位的无符号整数,用做窗口句柄
HDC
一个设备描述背景的句柄
WCHAR
说明一个16位的UNICODE字符,用来表示世界上所有已知的书的符号
句柄是Windows编程的一个关键性的概念,编写Windows应用程序总是要和各种句柄打交道。
所谓句柄,就是一个唯一的数,用以标识许多不同的对象类型,如窗口、菜单、内存、画笔、画刷等。
在Win32里,句柄是指向一个“无类型对象”(void*)的指针,也就是一个4字节长的数据。
无论它的本质是什么,句柄并不是一个真正意义上的指针。
从构造来看,句柄是一个指针,尽管它没有指向用于存储某个对象的内存位置。
事实上,句柄指向一个包含了对该对象引用的位置。
句柄的声明是这样的:
typedefvoid*HANDLE
由于Windows是一个多任务操作系统,它可以同时运行多个程序或一个程序的多个副本。
这些运行的程序称为一个实例。
为了对同一程序的多个副本进行管理,Windows引入了实例句柄。
Windows为每个应用程序建立一张表,实例句柄就好象是这张表的一个索引。
Windows不仅使用句柄来管理实例,也用它来管理窗口、位图、字体、元文件、图标等系统资源。
●3.标识符命名
在编程中,变量、函数的命名是一个极其重要的问题。
好的命名方法使变量易于记忆且程序的可读性大大提高。
Microsoft采用匈牙利命名法来命名WindowsAPI函数和变量。
匈牙利命名法是由Microsoft的著名开发人员、EXCEL的主要设计者查尔斯.西蒙尼在他的博士论文中提出来的,由于西蒙尼的国籍是匈牙利,所以这种命名法叫匈牙利命名法。
匈牙利命名法为C标识符的命名定义了一种非常标准化的方式,这种命名方式是以两条规则为基础的。
(1)标识符的名字以一个或者多个小写字母开头,用这些字母来指定数据类型。
下面列出了常用的数据类型的标准前缀。
在Windows中被定义的数据类型的一些标准前缀有:
前缀
数据类型
c
字符(char)
s
短整数(short)
cb
用于定义对象(一般为一个结构)尺寸的整数
n
整数(integer)
sz
以”\0”结尾的字符串
b
字节
i
整数(int)
x
短整数(坐标x)
y
短整数(坐标y)
f
布尔(BOOL)
w
字(WORD,无符号短整数)
l
长整数(long)
h
HANDLE(无符号int)
m
类成员变量
fn
函数(function)
dw
双字(DWORD,无符号长整数)
(2)在标识符内,前缀以后就是一个或者多个第一个字母大写的单词,这些单词清楚地指出了源代码内对象的用途。
比如,m_szStudentName表示一个学生名字的类成员变量,数据类型是字符串型。
1.4.2消息
Windows应用程序利用Windows消息(message)与其他的Windows应用程序及Windows系统进行信息交换。
由于Windows应用程序是消息或事件驱动的,因此,Windows消息工作机制就显得很重要了。
Windows中消息由三部分组成:
消息号、字参数和长字参数。
消息号由事先定义好的消息名标识;字参数(wParam)和长字参数(lParam)用于提供消息的附加信息,附加信息的含义与具体消息号的值有关。
在Windows中,消息往往用一个结构体MSG来表示。
结构体MSG的定义如下:
typedefstructtagMSG
{
HWNDbwnd;
UINTmessage;
WPARAMwParam;
LPARAMlParam;
DWORDtime;
POLNTpt;
}MSG;
其中:
hwnd:
窗口句柄,标识该消息属于哪一个窗口。
message:
消息类型(菜单消息、键盘消息、鼠标消息、窗口管理消息、定时器消息等。
一般用字符常数WM_xxx、BN_xxx等来表示。
在Winresrc.h文件中,有如下字符常数定义,在程序设计中,一般直接引用这些字符常量。
#defineWM_COMMAND
0x0111
菜单消息
#defineWM_TIMER
0x0113
定时器消息
#defineWM_MOUSEMOVE
0x0200
鼠标移动消息
#defineWM_LBUTTONDOWN
0x0201
鼠标左键按下消息
#defineWM_LBUTTONUP
0x0202
鼠标左键弹起消息
#defineWM_LBUTTONDBLCLK
0x0203
鼠标左键双击消息
#defineWM_RBUTTONDOWN
0x0204
鼠标右键按下消息
#defineWM_RBUTTONUP
0x0205
鼠标右键弹起消息
#defineWM_RBUTTONDBLCLK
0x0206
鼠标右键双击消息
#defineWM_MBUTTONDOWN
0x0207
鼠标中键按下消息
#defineWM_MBUTTONUP
0x0208
鼠标中键弹起消息
#defineWM_MBUTTONDBLCK
0x0209
鼠标中键双击消息
wParam、lParam是包含有关消息的附加信息,它随着不同的消息而有所不同。
例如,菜单消息中,wParam表示菜单项标识ID。
鼠标消息中,wParam参数表示鼠标操作时键盘Shift和Ctrl键的状态,lParam表示鼠标指针当前坐标(低16位表示x,高16位表示y)。
time:
消息传递的时间。
pt:
表示鼠标指针当前坐标。
在消息结构中,用户一般只关心hwnd、message、wParam、lParam几个参数。
以下介绍部分消息。
在VisualC++中存在几种系统定义的消息分类,不同的前缀符号经常用于消息宏识别消息附属的分类,系统定义的消息宏前缀如下:
前缀
消息分类
BM
按纽控制消息
CB
组合框控制消息
DM
默认下压式按钮控制消息
EM
编辑控制消息
LB
列表框控制消息
SBN
滚动条控制消息
WM
窗口消息
●1.菜单消息
WM_COMMAND
菜单
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第1章 WINDOWS编程 WINDOWS 编程