Windows通信机制和DLL机制实验报告文档格式.docx
《Windows通信机制和DLL机制实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《Windows通信机制和DLL机制实验报告文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
hInstance:
应用程序当前事例的句柄。
hPrevlnstance:
应用程序的先事例的句柄。
对于同一个程序打开两次,出现两个窗口第一次打开的窗口就是先前实例的窗口。
对于一个32的位程序,该参数总为NULL。
如果需要检测另外一个事例是否已经存在,则使用CreateMutex函数创建一个独一无二的名字。
即使互斥名已经存在,CreateMutex函数也是成功的,但是GetLastError函数将返回ERROR_ALREADY_EXISTS,这就表明在应用程序中有另外一个事例存在,因为它首先创建了互斥名。
lpCmdLine:
指向应用程序命令行的空字符串的指针,不包括函数名。
获得整个命令行,参看GetCommandLine
4>
nCmdShow:
指明窗口如何显示。
该参数可以是下列值之一:
SW_HIOE:
隐藏窗口并且激活另外一个窗口。
SW_MINIMIZE:
最小化指定的窗口,并且激活在系统表中的顶层窗口。
SW_RESTORE:
激活并显示窗口。
如果窗口已经最小化或最大化,系统将以恢复到原来的尺寸和位置显示窗口(与SW_SHOWNORMAL相同)。
SW_SHOW:
激活一个窗口并以原来的尺寸和位置显示窗口。
SW_SHOWMAXIMIZED:
激活窗口并且将其最大化。
SW_SHOWMINIMIZED:
激活窗口并将其目标化。
SW_SHOWMINNOACTIVE:
将一个窗口显示为图标。
激活窗口维持活动状态。
SW_SHOWNA:
以窗口的当前状态显示窗口。
激活窗口保持活动状态。
SW_SHOWNOACTIVATE:
以窗口的最近一次的尺寸和位置显示窗口。
激活窗口维持激活状态。
SW_SHOWNORMAL:
如果窗口最大化或最小化,系统将其恢复到原来的尺寸和位置(与SW_RESTORE相同)。
5>
返回值:
如果函数成功,当它接收到一个WM_QUIT消息时就中止,函数应该返回在该消息的wParam参数的退出值。
如果函数在进入消息循环时退出,应该返回零。
3.1.2窗口类的注册与创建
3.1.2.1窗口类的注册
一个应用程序在创建某个类型的窗口前,必须首先注册该“窗口类”(WindowsClass)。
“窗口类”是Windows系统的数据结构,可以把它理解为Windows系统的类型定义,而Windows窗口则是相应“窗口类”的实例。
Windows使用一个结构来描述“窗口类”,其定义如下:
typedefstruct_WNDCLASSEX{
UINTstyle;
WNDPROClpfnWndProc;
intcbClsExtra;
intcbWndExtra;
HANDLEhInstance;
HICONhIcon;
HCURSORhCursor;
HBRUSHhbrBackground;
LPCTSTRlpszMenuName;
LPCTSTRlpszClassName;
HICONhIconSm;
}WNDCLASSEX;
其中style是窗口样式,通过系统预先定义的一些常量来设置窗口样子,这些常量包CS_BYTEALIGNCLIENT(表示窗口客户区以byte的宽度对齐)、CS_DBLCLKS(如果有双击会向窗口发送消息)、CS_NOCLOSE(无关闭按钮)等。
lpfnWndProc是消息处理函数。
hInstance应该赋值为应用程序的实例。
hIcon,hCursor,hbrBackground,lpszMenuName分别为窗口类的图标、鼠标指针的样式、背景的画刷(COLOR_BACKGROUND、COLOR_WINDOW等,也可以自行建立画刷)、菜单名。
可以从资源获取图标、鼠标指针的样式和菜单。
应用程序在创建自己的窗口时,首先必须注册自己的窗口类。
窗口类的注册虽然只需填充一个结构体,调用一个API函数,但是窗口注册结构
WNDCLASSEX或WNDCLASS结构的设置较复杂,需注意设置的正确性。
3.1.2.2窗口类的创建
WinMain函数调用的InitInstance函数实现了程序主窗口的创建。
CreateWindowCreateWindowEx是用于创建窗口的API函数。
CreateWindow函数
CreateWindow函数的功能是创建一个窗口。
在创建窗口前,需先注册窗口类。
如果创建的窗口是系统控件,那么系统控制的类已经由操作系统注册好,所以不再需要注册。
创建窗口时,通过窗口指定窗口名、窗口样式、窗口的大小和位置、窗口所属的父窗口等。
HWNDCreateWindow(
LPCTSTRlpClassName,
LPCTSTRlpWindowName,
DWORDdwStyle,
intx,
inty,
intnWidth,
intnHeight,
HWNDhWndParent,
HMENUhMenu,
HANDLEhlnstance,
LPVOIDlpParam
);
<
参数lpClassName是窗口所需窗口类的类名。
参数lpWindowName是窗口名,如果窗口有标题栏,窗口名将显示在标题栏上。
参数dwStyle是窗口样式。
窗口是否具有标题栏,是否可改变大小,边框的样式等都通过这个参数设置,
参数x、y指定了窗口创建后的初始位置,编程时可以设置为CW_USEDEFAULT,由系统来设置。
参数nWidth、nHeight,表示窗口的宽和高,以像素点为单位,同样也可以指定为
CW_USEDEFAULT,使用系统默认。
6>
参数hMenu是窗口菜单的句柄,如果设置为NULL,表示使用窗口类的菜单。
hWndParent是窗口的父窗口句柄,当窗口样式有WS_CHILD时需设备父窗口句柄。
7>
参数hInstance是应用程序实例,设置为WinMain函数参数hInstance。
lpParam指定相关参数,指向CREATESTRUCT结构的变量,可以为NULL。
3.1.3窗口处理函数
Windows系统是消息(Message)驱动的。
消息在Windows处理用户交互的过程中具有重要作用。
当用户操作输入设备,产生硬件中断后,系统内核会得到这此硬件中断,硬件在系统中经过复杂的运算和处理最终变成消息。
消息被系统发送给指定窗口。
所有的对用户界面的操作都会产生消息,包括鼠标单击、按钮、菜单选择、窗口创建窗口移动等。
Windows消息种类很多。
在创建窗口时,需指定窗口所属的窗口类,前面提到,每一个窗口类都对应一个消息处理函数,因此每一个窗口都具有自己的消息处理函数。
程序员在开发窗口应用程序时,需编写窗口消息处理函数。
消息处理函数是一个回调(CallBack)函数。
此函数并不是由应用程序调用,而是由系统调用的。
应用程序向系统注册了窗口类,创建了窗口,系统在消息产生后,需要窗口消息处理函数来处理时,调用窗口所对应的消息处理函数。
消息处理函数的功能一般是相应用户在窗口上的操作和输入。
比如用户在菜单中选中了一个菜单项,那么就会产生一个消息。
然后,窗口的消息处理函数就会被调用。
消息处理函数被调用后根据消息的类型和参数判断应该如何处理用户的输入,然后进行相关的处理。
窗口处理函数
消息处理函数是一个回调函数,是注册窗口类时指定(通过函数指针赋值给WNDCLASS结构或WNDCLASSEX结构的lpfnWndProc成员来指定消息处理函数),在有消息需要处理时由系统调用。
LRESULTCALLBACKWindowProc(
HWNDhwnd,
UINTuMsg,
WPARAMwParam,
LPARAMIParam
);
hwnd:
指向窗口的句柄。
uMsg:
指定消息类型。
wParam:
指定其余的、消息特定的信息。
该参数的内容与UMsg参数值有关。
IParam:
该参数的内容与uMsg参数值有关。
返回值:
返回值就是消息处理结果,它与发送的消息有关。
回调函数的函数名任意,但是调用类型、返回值类型、参数类型和顺序必须固定,以使系统可以正常调用消息处理函数。
窗口消息处理
重要消息
(1)WMNOTIFY。
当一个窗口的子窗口被用户操作时,该子窗口会向父窗口发送WMNOTIFY通知
(2)WMDESTROY。
收到WM—DESTROY消息,表示用户单击窗口的关闭按钮。
如果用户单击主窗口的关闭按键,一般情况下表示用户需要结束本程序的运行。
因此在MainWndProc函数收到WM_DESTROY消息后,调用PostQuitMessage函数退出程序运行。
要退出一个进程的运行,也可以调用ExitProcess函数。
(3)WM_COMMAND。
收到WM_COMMAND-般是因为用户通过菜单、按钮等用程序输入命令。
WM_COMMAND消息的wParam的低位WORD是表示用户单击的控件或菜单项的ID
3.2DLL
如图在VC++中新建一个Win32Dynamic-LinkLibrary工程
DLL简介:
动态链接库英文为DLL,是DynamicLinkLibrary的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。
函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
DLL还有助于共享数据和资源。
多个应用程序可同时访问内存中单个DLL副本的内容。
DLL是一个包含可由多个程序同时使用的代码和数据的库。
导出DLL函数
方法一、向导出的DLL函数中添加函数关键字
要使用函数关键字,您必须使用以下关键字来声明要导出的各个函数:
__declspec(dllexport)
要在应用程序中使用导出的DLL函数,您必须使用以下关键字来声明要导入的各个函数:
__declspec(dllimport) 通常下,您最好使用一个包含define语句和ifdef语句的头文件,以便分隔导出语句和导入语句。
方法二、创建模块定义文件(.def)以列出导出的DLL函数
使用模块定义文件来声明
导出的DLL函数。
当您使用模块定义文件时,您不必向导出的DLL函数中添加函数关键字。
在模块定义文件中,您可以声明DLL的LIBRARY语句和EXPORTS语句。
DLL应用原理
首先,语句typedefint(*lpAddFun)(int,int)定义了一个与add函数接收参数类型和返回值
均相同的函数指针类型。
随后,在main函数中定义了lpAddFun的实例addFun;
其次,在函数main中定义了一个DLLHINSTANCE句柄实例hDll,通过Win32API函数
LoadLibrary动态加载了DLL模块并将DLL模块句柄赋给了hDll;
在次,在函数main中Win32API函数GetprocAddress得到了所加载DLL模块中add的地址
并付给了addFun.经由函数指针addFun进行了对DLL中add函数的调用。
最后,应用工程使用完DLL后,在函数main中通过Win32API函数FreeLibrary释放已经
加载的DLL模块。
四源码
DLL部分
event.h
#include<
windows.h>
math.h>
#ifndefLIB_H
#defineLIB_H
extern"
C"
void_declspec(dllexport)setCalculate(HWNDhwnd,HWNDhwnd1,HWNDhwnd2,HWNDhwnd3,HWNDhwnd4);
void_declspec(dllexport)setClearAll(HWNDhwnd1,HWNDhwnd2,HWNDhwnd3,HWNDhwnd4);
#endif
Event.cpp
#include"
event.h"
charMoney[]="
"
;
charRate[]="
charYear[]="
charTotal[]="
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++
+*主函数:
Check+
+*功能:
输入判断函数+
+*参数:
a[]输入的字符串+
+*返回值:
全是数字返回TRUE否则返回FALSE+
++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
BOOLCheck(chara[])
{
inti;
intlen=strlen(a);
for(i=0;
i<
len;
i++)
{
if(a[i]>
'
9'
||a[i]<
0'
)
{
returnFALSE;
}
}
returnTRUE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
setCalculate+
为CalculateButton添加响应+
+输入本金,利率,年输出总钱数+
hwnd父窗口句柄+
+hwnd1本金输入框句柄+
+hwnd2利率输入框句柄+
+hwnd3年数输入框句柄+
+hwnd4输出框句柄+
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
voidsetCalculate(HWNDhwnd,HWNDhwnd1,HWNDhwnd2,HWNDhwnd3,HWNDhwnd4)
GetWindowText(hwnd1,Money,20);
GetWindowText(hwnd2,Rate,20);
GetWindowText(hwnd3,Year,20);
doubletotalMoney;
if(Check(Money)&
&
Check(Rate)&
Check(Year))
totalMoney=atof(Money)*pow(1/atof(Rate)+1,atoi(Year));
gcvt(totalMoney,10,Total);
SetWindowText(hwnd4,Total);
else
MessageBox(hwnd,TEXT("
对不起,你输入的格式不对"
),TEXT("
提示"
),MB_OK);
SetWindowText(hwnd1,"
);
SetWindowText(hwnd2,"
SetWindowText(hwnd3,"
SetWindowText(hwnd4,"
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++
setClearAll+
为ClearButton添加响应+
+清空所有输入框输出框+
hwnd1本金输入框句柄+
+
voidsetClearAll(HWNDhwnd1,HWNDhwnd2,HWNDhwnd3,HWNDhwnd4)
SetWindowText(hwnd1,"
SetWindowText(hwnd2,"
SetWindowText(hwnd3,"
SetWindowText(hwnd4,"
窗口部分
1Window.h
//windows程序的头文件
externcharszTitle[];
//标题条字符串
externcharszWindowClass[];
//窗口类名
externcharszMenuName[];
externintID,ID_1;
//函数原型声明
ATOMInitApplication(HINSTANCE);
//用来注册窗口类
BOOLInitInstance(HINSTANCE,int);
//用来创建主窗口
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
//消息处理函数
intAPIENTRYWinMain(HINSTANCE,HINSTANCE,LPSTR,int);
//主函数
BOOLCreateControl(HINSTANCE,HWND,LPSTR);
//创建文本框
2Window.cpp
#include"
window.h"
//全局变量
charszTitle[]="
Windows通信机制和DLL机制"
CharszWindowClass[]="
w32"
CharszMenuName[]="
NULL"
//菜单名
typedefvoid(*lpsetCalculateFun)(HWND,HWND,HWND,HWND,HWND);
typedefvoid(*lpsetClearAllFun)(HWND,HWND,HWND,HWND);
HWNDhwnd1,hwnd2,hwnd3,hwnd4,calculateButton,clearButton;
HWNDhwnd;
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*主函数WinMain
初始化及注册窗口类,创建窗口,进入消息循环及终止应用程序+
hInstance当前实例+
+hPrevInstance前一个实例+
+lpCmdLine命令行+
+nCmdShow选择显示窗口或图标+
*返回值:
msg.wParam
+++++++++++++++++++++++++++++++*/
intAPIENTRYWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow)
MSGmsg;
//声明消息结构对象
InitApplication(hInstance);
//注册窗口
if(!
InitInstance(hInstance,nCmdShow))//初始化
returnFALSE;
while(GetMessage(&
msg,(HWND)NULL,0,0))//消息循环
TranslateMessage(&
msg);
//检索消息
DispatchMessage(&
//将消息间接传给函数指针
returnmsg.wParam;
//结束消息循环传回PostQuitMesage
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
InitApplication+
用来注册窗口类+
如果成功,返回一个唯一的整数,如果失败,返回0+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
ATOMInitApplication(HINSTANCEhInstance)
WNDCLASSwc;
//声明窗口结构对象
//初始化对象的域值
wc.style=CS_HREDRAWCS_VREDRAW;
//如果大小改变了重绘窗口
wc.lpfnWndProc=WndProc;
//窗口消息处理函数
wc.cbClsExtra=0;
//无附加窗口类内存
wc.cbWndExtra=0;
//无附加窗口内存
wc.hInstance=hInstance;
//当前实例
wc.hIcon=LoadIc