第二章 Windows程序设计.docx
- 文档编号:26383844
- 上传时间:2023-06-18
- 格式:DOCX
- 页数:23
- 大小:129.03KB
第二章 Windows程序设计.docx
《第二章 Windows程序设计.docx》由会员分享,可在线阅读,更多相关《第二章 Windows程序设计.docx(23页珍藏版)》请在冰豆网上搜索。
第二章Windows程序设计
第二章Windows程序基础
在本学习情境中主要掌握:
(1)Windows程序结构
(2)Windows控件使用
2.1Windows程序结构
2.1.1WinMain函数
C语言中的main()函数一样,Windows程序是从WinMain()函数开始和结束的.WinMain()函数是在WINBASE.H中定义的,如图1所示。
图1WinMain函数头文件
其原形如下:
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnShowCmd)
其中第一个参数(HINSTANCEhInstance)是程序的实例句柄,这个实例句柄是程序的唯一标识.
第二个参数(HINSTANCEhPrevInstance)是用做检查是否有多个程序实例运行,但由于Windows9X和NT(包括更高版本)是32位操作系统,所以这个参数总是NULL.
第三个参数(LPSTRlpCmdLine)是一个指向字符串的指针,用来保存运行程序时的命令行参数.
第四个参数(intnShowCmd)用来指定程序开始的时候如何显示.
2.1.2窗口创建过程
第一步:
定义并注册窗口类。
在Windows中要创建一个窗口首先要定义窗口类然后注册这个窗口类.定义窗口类要通过填充WNDCLASS结构体来完成,此结构体是在WINUSER.H中定义的,其原形如下:
typedefstructtagWNDCLASSA
{
UINTstyle;
WNDPROClpfnWndProc;
intcbClsExtra;
intcbWndExtra;
HINSTANCEhInstance;
HICONhIcon;
HCURSORhCursor;
HBRUSHhbrBackground;
LPCSTRlpszMenuName;
LPCSTRlpszClassName;
}WNDCLASS;
第一个成员变量style指定这一类型窗口的样式,这些样式可通过按位或操作组合起来。
常用样式如下:
CS_HREDRAW:
当水平长度改变或移动窗口时,重画整个窗口
CS_VREDRAW:
当垂直长度改变或移动窗口时,重画整个窗口
CS_DBLCLKS:
允许向窗口发送双击鼠标键的消息
CS_NOCLOSE:
禁止系统菜单的关闭选项
第二个成员变量lpfnWndProc是一个函数指针,指向窗口过程函数,窗口过程函数是一个回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应。
针对Windows的消息处理机制,窗口过程函数被调用的过程如下:
(1)在设计窗口类的时候,将窗口过程函数的地址赋值给lpfnWndProc成员变量。
(2)调用RegisterClass(&wndclass)注册窗口类,系统就拥有了窗口过程函数的地址。
(3)当应用程序接收到某一窗口的消息时,调用DispatchMessage(&msg)将消息回传给系统。
系统则利用先前注册窗口类时得到的函数指针,调用窗口过程函数对消息进行处理。
lpfnWndProc成员变量的类型是WNDPROC的定义:
typedefLRESULT(CALLBACK*WNDPROC)(HWND,UINT,WPARAM,LPARAM);
WNDPROC是函数指针类型。
第三个成员变量cbClsExtra指定紧随在WNDCLASS数据结构后分配的字节数。
系统将其初始化为零。
第四个成员变量cbWndExtra:
指定紧随在窗口实例之后分配的字节数,系统将其初始化为零。
第五个成员变量hInstance标识该窗口类的窗口过程所在的模块实例的句柄,不能为NULL。
第六个成员变量hIcon:
标识该窗口类的图标。
hIcon字段必须是一个图标的句柄;若hIcon字段为NULL,那么系统将提供一个默认的图标。
在为hIcon变量赋值时,可以调用LoadIcon函数来加载一个图标资源,返回系统分配给该图标的句柄。
函数原型声明如下所示:
HICONLoadIcon(HINSTANCEhInstance,LPCTSTRlpIconName);
第七个成员变量hCursor标识该窗口类的光标,hCursor必须是一个光标资源的句柄。
若hCursor字段为NULL,则无论何时鼠标移到应用程序窗口时,应用程序必须显式设置光标形状。
在为hCursor变量赋值时,可以调用LoadCursor函数来加载一个光标资源,返回系统分配给该光标的句柄。
函数原型声明如下:
HCURSORLoadCursor(HINSTANCEhInstance,LPCTSTRlpCursorName);
第八个成员变量hbrBackground:
标识了该窗口类的背景画笔。
hbrBackground字段必须是用于绘制背景的物理刷子的句柄,也可以为其指定一个标准的系统颜色值。
可以调用GetStockObject函数来得到系统得标准画刷。
GetStockObject函数的原型声明如下:
HGDIOBJGetStockObject(intfnObject);
GetStockObject函数可以返回多种资源对象的句柄,还可以用于获取画笔、字体和调色板的句柄。
第九个成员变量lpszMenuName指向NULL结束的字符串,该字符串描述菜单的资源名,如同在资源文件里显示的名字一样。
若使用一个整数标识菜单,可以使用MAKEINTRESOURCE宏。
如果lpszMenuName为NULL,那么该窗口类的窗口将没有默认菜单。
第十个成员变量lpszClassName指向NULL结束的字符串,指定窗口类的名字。
设计完窗口类(WNDCLASS)后,需要调用RegisterClass函数对其进行注册,注册成功后,才可以创建该类型的窗口,注册函数的原型声明如下:
ATOMRegisterClass(CONSTWNDCLASS*lpWndClass);
该函数只有一个参数,即上面所设计的窗口类对象的指针。
例:
if(!
RegisterClass(&wndclass))
return0;
第二步:
创建并显示窗口
在完成了定义窗口类和注册窗口类,现在要来创建这个窗口并显示它。
创建一个窗口要使用CreateWindow()函数来完成,具体方法如下:
hwnd=CreateWindow(LPCTSTRlpClassName,//窗口类名
LPCTSTRlpWindowName,//窗口标题
DWORDdwStyle,//窗口样式
intx,//窗口最初的X位置
inty,//窗口最初的Y位置
intnWidth,//窗口最初的X大小
intnHeight,//窗口最初的Y大小
HWNDhwndParent,//父窗口句柄
HMENUhMenu,//窗口菜单
HANDLEhInstance,//应用程序实例句柄
LPVOIDlpParam//附加的数据指针
);
参数lpClassName指定窗口类的名称,即WNDCLASS中第十个成员变量lpszClassName成员指定的名称。
参数lpWindowName指定窗口的名字。
如果窗口样式指定了标题栏,那么这里指定的窗口名字将显示在标题栏上。
参数dwStyle指定创建的窗口的样式。
要注意区分WNDCLASS类中的style成员与CreateWindow函数的dwStyle参数,前者是指定窗口类的样式,基于该窗口类创建的窗口都具有这些样式,后者是指定某个具体的窗口的样式。
可以给创建的窗口指定WS_OVERLAPPEDWINDOW类型,该类型的定义为:
#defineWS_OVERLAPPEDWINDOW(WS_OVERLAPPED|\
WS_CAPTION|\
WS_SYSMENU|\
WS_THICKFRAME|\
WS_MINIMIZEBOX|\
WS_MAXIMIZEBOX)
WS_OVERLAPPED:
产生一个层叠的窗口,一个层叠的窗口有一个标题栏和边框。
WS_CAPTION:
创建一个有标题栏的窗口。
WS_SYSMENU:
创建一个在标题栏上带有系统菜单的窗口,要和WS_CAPTION类型一起使用。
WS_THICKFRAME:
创建一个具有可调边框的窗口。
WS_MINIMIZEBOX:
创建一个具有最小化按钮的窗口,必须同时设定WS_SYSMENU类型。
WS_MAXIMIZEBOX:
创建一个具有最大化按钮的窗口,必须同时设定WS_SYSMENU类型。
CreateWindow函数的参数x,y,nWidth,nHeight分别指定窗口左上角的x,y坐标,窗口
的宽度、高度。
如果参数x被设定为CW_USEDEFAULT,那么系统为窗口选择默认的左上角坐标并忽略y参数。
如果参数nWidth被设为CW_USEDEFAULT,那么系统为窗口选择默认的宽度和高度,参数nHeight被忽略。
参数hwndParent指定被创建窗口的父窗口的句柄。
参数hMenu指定窗口菜单的句柄。
参数hInstance指定窗口所属的应用程序实例的句柄。
参数lpParam作为WM_CREATE消息的附加参数lParam传入的数据指针。
在创建多文档界面的客户窗口时,lpParam必须指向CLIENTCREATESTRUCT结构体。
多数窗口的这个参数设置为NULL。
如果窗口创建成功,CreateWindow函数将返回系统为该窗口分配的句柄,否则,返回NULL。
需要注意的是,在创建窗口之前应先定义一个窗口句柄变量来接收窗口之后返回的句柄值。
第三步:
显示及更新窗口
窗口创建以后,可以调用ShowWindow函数来显示窗口,函数的原型声明如下:
BOOLShowWindow(
HWNDhWnd,
intnCmdShow
);
参数hWnd即CreateWindow函数返回的窗口句柄。
参数nCmdShow指定窗口的显示状态。
常用的显示状态:
SW_SHOWNORMAL:
激活并显示窗口。
SW_SHOW:
在窗口原来的位置以原来的尺寸激活和显示窗口。
SW_HIDE:
隐藏窗口并激活其他窗口。
SW_SHOWMAXIMIZED:
激活窗口并将其最大化显示。
SW_SHOWMINIMIZED:
激活窗口并将其最小化显示。
在调用ShowWindow函数后,接着调用UpdateWindow来刷新窗口,函数的原型声明如下:
BOOLUpdateWindow(
HWNDhWnd);
参数hWnd指CreateWindow函数返回的窗口句柄。
2.1.3消息循环
在创建窗口、显示窗口、更新窗口后,需要编写一个消息循环,不断地从消息队列中取出消息,并进行响应。
要从消息队列中取出消息,需要调用GetMessage()函数,函数原型声明如下:
BOOLGetMessage(
LPMSGlpMsg,
HWNDhWnd,
UINTwMsgFilterMin,
UINTwMsgFilterMax
);
参数lpMsg指向一个消息(MSG)结构体,GetMessage从线程的消息队列中取出的消息将保存在该结构体对象中。
typedefstructtagMSG{
HWNDhwnd;
UINTmessage;
WPARAMwParam;
LPARAMlParam;
DWORDtime;
POINTpt;
}MSG;
第一个成员变量hwnd表示消息所属的窗口。
我们通常开发的程序都是窗口应用程序,一个消息一般都是与某个窗口相关联的。
例如,在某个活动窗口中按下鼠标左键,产生的按键消息就是发给该窗口的。
在Windows程序中,用HWND类型的变量来标识窗口。
第二个成员变量message指定了消息的标识符。
在Windows中,消息是由一个数值来表示的,不同的消息对应不同的数值。
但是由于数值不便于记忆,所以Windows将消息对应的数值定义为WM_XXX宏(WM是WindowMessage的缩写)的形式,XXX对应某种消息的英文拼写的大写形式。
例如,鼠标左键按下消息是WM_LBUTTONDOWN,键盘按下消息是WM_KEYDOWN,字符消息是WM_CHAR,等等。
在程序中我们通常都是以WM_XXX宏的形式来使用消息的。
第三、第四个成员变量wParam和lParam,用于指定消息的附加信息。
例如,当我们收到一个字符消息的时候,message成员变量的值就是WM_CHAR,但用户到底输入的是什么字符,那么就由wParam和lParam来说明。
wParam、lParam表示的信息随消息的不同而不同。
第五、第六个两个变量time和pt分别表示消息投递到消息队列中的时间和鼠标的当前位置。
Windows会为每一个当前运行的程序建立一个消息队列,用来完成用户与程序的交互.为了让程序能够处理这个消息队列,我们要使用一个消息循环从消息队列中取出消息:
while(GetMessage(msg,NULL,0,0))
{
TranslateMessage(msg);
DispatchMessage(msg);
}
消息循环从GetMessage()函数开始,首先从消息队列中取出一个消息,然后通过TranslateMessage(msg)函数将msg结构传递给Windows进行转换,最后使用DispatchMessage(msg)函数将msg结构回传给Windows,再由Windows将此消息发送到相应的窗口过程中进行处理.
2.1.4编写窗口过程函数
窗口过程函数要处理Windows发来的消息,就需要定义一个窗口过程函数.在填充wndclass结构的时候我们定义了窗口的消息处理函数
wndclass.lpfnWndProc=WndProc;
WndProc,这个函数就是用来处理窗口消息的窗口过程函数.其定义形式如下:
LRESULTCALLBACKWndProc(HWNDhwnd,UNITmessage,WPARAMwParam,LPARAMlParam)
这四个参数和MSG结构的前四个域是相同的。
第一个参数(HWNDhwnd)是接收消息的窗口句柄,它和CreateWindow()函数的返回值相同。
第二个参数(UNITmessage)是用来标识该消息的数字。
第三个参数和第四个参数是32位的消息参数,用来提供消息的更多信息。
在定义完窗口过程函数后,我们就可以在窗口过程函数中来处理由Windows发来的窗口消息。
一般使用switch和case语句来判断收到的是什么消息,并相应的处理这个消息。
switch(message)
{
caseWM_CREATE:
......
return0;
caseWM_PAINT:
......
return0;
default:
returnDefWindowProc(hwnd,message,wParam,lParam);
}
2.1.5窗口实现过程
(1)首先建立一个Win32Application类型的工程,如图2所示。
图2建立Win32Application类型的工程
(2)选择AnEmptyProject类型的工程,如图3所示。
图3选择AnEmptyProject类型的工程
(3)为SimpleWin工程增加一个C++SourceFile的源文件,如图4所示。
图4增加C++源文件
(4)在C++源文件中编写程序的相关代码。
#include
//窗口过程函数的声明
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow)
{
//窗口句柄
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="SimpleWin";
//窗口的注册
if(!
RegisterClass(&wndclass))
{
MessageBox(NULL,"窗口注册失败!
","SimpleWin",0);
return0;
}
//窗口的创建
hwnd=CreateWindow("SimpleWin",//窗口类名
"石家庄职业技术学院",//窗口标题
WS_OVERLAPPEDWINDOW,//窗口样式
CW_USEDEFAULT,//窗口最初的X位置
CW_USEDEFAULT,//窗口最初的Y位置
CW_USEDEFAULT,//窗口最初的X大小
CW_USEDEFAULT,//窗口最初的Y大小
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)
{
caseWM_CREATE:
return0;
caseWM_LBUTTONDOWN:
MessageBox(NULL,"你好,VC++!
","提示",0);
return0;
caseWM_DESTROY:
PostQuitMessage(0);
return0;
}
returnDefWindowProc(hwnd,message,wParam,lParam);
}
(5)程序运行结果如图5所示。
图5程序运行结果
2.1.6使用控件
(1)将原来设计的求一元二次方程的根类加入到工程中,如图6所示。
图6将文件加入到工程中
(2)选择Root.h和Root.cpp文件加入到工程中,如图7所示。
图7选择Root.h和Root.cpp文件
其中Root.h中的代码为:
#ifndefCLASS_ROOT_1
#defineCLASS_ROOT_1
classRoot
{
private:
floatRa,Rb,Rc;
doubleroot[2];
public:
Root()
{
}
Root(floata,floatb,floatc)
{
Ra=a;
Rb=b;
Rc=c;
}
~Root()
{
}
voidSetRoot(floata,floatb,floatc)
{
Ra=a;
Rb=b;
Rc=c;
}
intGetRoot();
doubleRoot1();
doubleRoot2();
};
#endif
其中Root.cpp中代码为:
#include
#include
#include"Root.h"
intRoot:
:
GetRoot()
{
doubledelta,deltasqrt;
delta=Rb*Rb-4.0*Ra*Rc;
if(delta<0)
{
cout<<"此方程无正实数解"< return0; } deltasqrt=sqrt(delta); if(Ra! =0) { root[0]=(-Rb+deltasqrt)/(2.0*Ra); root[1]=(-Rb-deltasqrt)/(2.0*Ra); return2; } else { if(Rb! =0) { root[0]=root[1]=-Rc/Rb; return1; } else return0; } } doubleRoot: : Root1() { returnroot[0]; } doubleRoot: : Root2() { returnroot[1]; } (3)在SimpleWin的源文件基础上进行修改,代码如下: #include #include #include #include"Root.h" //窗口过程函数的声明 LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM); intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow) { //窗口句柄 HWNDhwnd; //消息结构 MSGmsg; //窗口类 WNDCLASSwndclass; //窗口类的初始化 wndclass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; wndclass.lpfnWndProc=WndProc; wndclass.cbCl
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第二章 Windows程序设计 第二 Windows 程序设计
![提示](https://static.bdocx.com/images/bang_tan.gif)