孙鑫VC学习.docx
- 文档编号:23327273
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:33
- 大小:38.80KB
孙鑫VC学习.docx
《孙鑫VC学习.docx》由会员分享,可在线阅读,更多相关《孙鑫VC学习.docx(33页珍藏版)》请在冰豆网上搜索。
孙鑫VC学习
孙鑫VC++讲座笔记-
(1)Windows程序内部运行机制
分类:
孙鑫VC++讲座笔记2005-10-1022:
48 9119人阅读 评论(7) 收藏 举报
windowsvc++functionstructurethreadcallback
思考:
1、理解SDK编程、API、动态链接库、导入库等等概念
(1)SoftwareDevelopmentKit的缩写,中文意思就是“软件开发工具包”
SDK编程指调用rawAPI进行Windows编程(即直接调用windows的API进行编程,而不是通过MFC等类库),编程语言为C。
(2)首先要接触的是“API”,也就是ApplicationProgrammingInterface,其实就是操作系统留给应用程序的一个调用接口,应用程序通过调用操作系统的API而使操作系统去执行应用程序的命令(动作
(3)DLL,即DynamicLinkLibrary(动态链接库)。
我们经常会看到一些.dll格式的文件,这些文件就是动态链接库文件,其实也是一种可执行文件格式。
跟.exe文件不同的是,.dll文件不能直接执行,他们通常由.exe在执行时装入,内含有一些资源以及可执行代码等。
其实Windows的三大模块就是以DLL的形式提供的(Kernel32.dll,User32.dll,GDI32.dll),里面就含有了API函数的执行代码。
为了使用DLL中的API函数,我们必须要有API函数的声明(.H)和其导入库(.LIB),函数的原型声明不难理解,那么导入库又是做什么用的呢?
我们暂时先这样理解:
导入库是为了在DLL中找到API的入口点而使用的。
(4)由于SDK包含了使用API的必需资料,所以人们也常把仅使用API来编写Windows应用程序的开发方式叫做“SDK编程”。
而API和SDK是开发Windows应用程序所必需的东西,所以其它编程框架和类库都是建立在它们之上的,比如VCL和MFC,虽然他们比起“SDK编程”来有着更高的抽象度,但这丝毫不妨碍它们在需要的时候随时直接调用API函数。
2、理解windows程序驱动运行的机理:
事件驱动、消息结构、Windows程序入口、消息循环、窗口回调函数WindowProc、DC句柄
1,windows程序设计是种事件驱动方式的程序设计,主要基于消息的。
当用户需要完成某种功能时,需要调用OS某种支持,然后OS将用户的需要包装成消息,并投入到消息队列中,最后应用程序从消息队列中取走消息并进行响应。
2,消息结构:
typedefstructtagMSG{ //msg
HWND hwnd; //接收消息的窗口句柄。
和哪个窗口相关联。
UINT message; //消息标识。
消息本身是什么。
WPARAMwParam; //消息的附加信息。
具体取决于消息本身。
LPARAMlParam;
DWORD time; //消息投递时间。
POINT pt; //消息投递时,光标在屏幕上的位置。
}MSG;
3,消息队列:
每个应用程序OS都为它建立一个消息队列,消息队列是个先进先出的缓冲区,其中每个元素都是一个消息,OS将生成的每个消息按先后顺序放进消息队列中,应用程序总是取走当前消息队列中的第一条消息,应用程序取走消息后便知道用户的操作和程序的状态,然后对其处理即消息响应,消息响应通过编码实现。
4,使用VC编程除了良好的C基础外还需要掌握两方面:
一,消息本身。
不同消息所代表的用户操作和应用程序的状态。
二,对于某个特定的消息来说,要让OS执行某个特定的功能去响应消息。
5,Window程序入口:
intWINAPIWinMain(
HINSTANCEhInstance, //当前事例句柄。
HINSTANCEhPrevInstance, //先前事例句柄。
LPSTRlpCmdLine, //命令行指针
intnCmdShow //(窗口)显示的状态
);
说明:
WinMain函数是Windows程序入口点函数,由OS调用,当OS启动应用程序的时候,winmain函数的参数由OS传递的。
6,创建一个完整的窗口需要经过下面四个操作步骤:
一,设计一个窗口类;如:
WNDCLASSwndcls;
二,注册窗口类; 如:
RegisterClass(&wndcls);
三,创建窗口; 如:
CreateWindow(),CreateWindowEX();
四,显示及更新窗口。
如:
ShowWindow(),UpdateWindow();
说明:
创建窗口的时候一定要基于已经注册的窗口类.
7,Windows提供的窗口类:
typedefstruct_WNDCLASS{
UINT style; //窗口的类型
WNDPROClpfnWndProc; //窗口过程函数指针(回调函数)
int cbClsExtra;//窗口类附加字节,为该类窗口所共享。
通常0。
int cbWndExtra;//窗口附加字节。
通常设为0。
HANDLE hInstance; //当前应用程序事例句柄。
HICON hIcon; //图标句柄LoadIcon();
HCURSORhCursor; //光标句柄LoadCursor();
HBRUSH hbrBackground;//画刷句柄(HBRUSH)GetStockObject();
LPCTSTRlpszMenuName; //菜单名字
LPCTSTRlpszClassName;//类的名字
}WNDCLASS;
8,窗口类注册:
ATOMRegisterClass(
CONSTWNDCLASS*lpWndClass //addressofstructurewithclass
//data
);
9,创建窗口:
HWNDCreateWindow(
LPCTSTRlpClassName, //pointertoregisteredclassname
LPCTSTRlpWindowName,//pointertowindowname
DWORDdwStyle, //windowstyle
intx, //horizontalpositionofwindow
inty, //verticalpositionofwindow
intnWidth, //windowwidth
intnHeight, //windowheight
HWNDhWndParent, //handletoparentorownerwindow
HMENUhMenu, //handletomenuorchild-windowidentifier
HANDLEhInstance, //handletoapplicationinstance
LPVOIDlpParam //pointertowindow-creationdata
);
10,显示和更新窗口窗口:
BOOLShowWindow(
HWNDhWnd, //handletowindow
intnCmdShow //showstateofwindow
);
BOOLUpdateWindow(
HWNDhWnd //handleofwindow
);
11,消息循环:
MSGmsg;
while(GetMessage(&msg,...)) //从消息队列中取出一条消息
{
TranslateMessage(&msg);//进行消息(如键盘消息)转换
DispatchMessage(&msg); //分派消息到窗口的回调函数处理,(OS调用窗口回调函数进行处理)。
}
其中:
//**TheGetMessagefunctionretrievesamessagefromthecallingthread'smessagequeueandplacesitinthespecifiedstructure.
//**IfthefunctionretrievesamessageotherthanWM_QUIT,thereturnvalueisnonzero.IfthefunctionretrievestheWM_QUITmessage,thereturnvalueiszero.Ifthereisanerror,thereturnvalueis-1.
BOOLGetMessage(
LPMSGlpMsg, //addressofstructurewithmessage
HWNDhWnd, //handleofwindow
UINTwMsgFilterMin, //firstmessage
UINTwMsgFilterMax //lastmessage
);
//TheTranslateMessagefunctiontranslatesvirtual-keymessagesintocharactermessages.Thecharactermessagesarepostedtothecallingthread'smessagequeue,tobereadthenexttimethethreadcallstheGetMessageorPeekMessagefunction.
BOOLTranslateMessage(
CONSTMSG*lpMsg //addressofstructurewithmessage
);
//TheDispatchMessagefunctiondispatchesamessagetoawindowprocedure.
LONGDispatchMessage(
CONSTMSG*lpmsg //pointertostructurewithmessage
);
12,窗口过程函数(回调函数)原型:
TheWindowProcfunctionisanapplication-definedfunctionthatprocessesmessagessenttoawindow.TheWNDPROCtypedefinesapointertothiscallbackfunction.WindowProcisaplaceholder(占位符)fortheapplication-definedfunctionname.
LRESULTCALLBACKWindowProc( //这里WindowProc是个代号名字。
HWNDhwnd, //handletowindow
UINTuMsg, //messageidentifier
WPARAMwParam, //firstmessageparameter
LPARAMlParam //secondmessageparameter
);
说明:
两种函数调用约定(__stdcall和__cdecl):
#defineCALLBACK __stdcall
//__stdcall标准调用预定,是PASCAL调用约定,象DELPHI使用的就是标准调用约定
#defineWINAPIV __cdecl
//__cdecl是C语言形式的调用约定。
主要区别:
函数参数传递顺序和对堆栈的清除上。
问题:
除了那些可变参数的函数调用外,其余的一般都是__stdcall约定。
但C/C++编译默然的是__cdecl约定。
所以如果在VC等环境中调用__stdcall约定的函数,必须要在函数声明的时加上__stdcall修饰符,以便对这个函数的调用是使用__stdcall约定(如使用DELPHI编写的DLL时候)。
(VC中可通过这途径修改:
project|settings..|c/c++|...)
在窗口过程函数中通过一组switch语句来对消息进行处理:
如:
LRESULTCALLBACKWindowProc(
HWNDhwnd,
UINTuMsg,
WPARAMwParam,
LPARAMlParam
)
{
switch(uMsg)
{
caseWM_PAINT:
...
break;
case...
break;
caseWM_CLOSE:
//DestroyWindow(hwnd);
//销毁窗口,并发送WM_DESTROY消息。
break;
caseWM_DESTROY:
//PostQuitMessage(0);
//发送WM_QUIT消息到消息队列中,请求终止。
//GetMessage()取到WM_QUIT消息后,返回0,退出消息循 // 环,从而终止应用程序。
break;
default:
returnDefWindowProc(hwnd,uMsg,wParam,lParam);
//用缺省的窗口过程处理我们不感兴趣的消息(其它消息)。
//这是必须的。
}//switch
return0;
}//WindowProc
13,DestroyWindow()函数和PostQuitMessage()函数原型:
//**TheDestroyWindowfunctiondestroysthespecifiedwindow.ThefunctionsendsWM_DESTROYandWM_NCDESTROYmessages。
BOOLDestroyWindow(
HWNDhWnd //handletowindowtodestroy
);
//**ThePostQuitMessagefunctionindicatestothesystemthatathreadhasmadearequesttoterminate(quit).ItistypicallyusedinresponsetoaWM_DESTROYmessage.
//**ThePostQuitMessagefunctionpostsaWM_QUITmessagetothethread'smessagequeueandreturnsimmediately;thefunctionsimplyindicates(预示,通知)tothesystemthatthethreadisrequestingtoquitatsometimeinthefuture.
WhenthethreadretrievestheWM_QUITmessagefromitsmessagequeue,itshouldexititsmessageloopandreturncontroltothesystem.
VOIDPostQuitMessage(
intnExitCode //exitcode
);
14,关于DC句柄获取:
a)使用BeginPaint(),EndPaint()对。
注意只能在响应WM_PAINT消息时使用。
b)使用GetDc(),ReleaseDC()对。
注意他们不能在响应WM_PAINT中使用
CDC类定义的是设备上下文对象的类。
CDC对象提供处理显示器或打印机等设备上下文的成员函数,以及处理与窗口客户区对应的显示上下文的成员。
通过CDC对象的成员函数进行所有的绘图。
类对设备上下文操作提供了成员函数,处理绘图工具。
安全型图形设备接口(GDI)对象收集,以及处理颜色和调色板。
它还为获取和设置绘图属性、映射,处理视点、窗口扩展、转换坐标,处理区域、剪贴、绘制直线及绘制简单椭圆和多边形等形状提供了成员函数。
另外还为绘制文本、处理字体,使用打印机跳转,滚动和播放元文件提供成员函数。
使用CDC对象时要构造它,然后调用与它平等的、使用设备上下文的Windows函数的成员函数。
为了特定用途,Microsoft基本类库提供了几个CDC派生类。
CPaintDC包括BeginPaint和EndPaint调用。
CClientDC管理窗口用户区对应的显示上下文。
CWindowDC管理与整个窗口对应的显示上下文,包括它的结构和控件。
CMetaFileDC与带元文件的设备上下文对应。
15、补充:
请问MFC中的DC、CDC、HDC、句柄、设备上下文究竟是什么意思?
楼主你没有了解MFC的运行机制就去看他写他所以你先要了解他的机制已经各个CPP.H都是什么下面我就给你说下。
在MFC程序中,我们并不经常直接调用WindowsAPI,而是从MFC类创建对象并调用属于这些对象的成员函数.也就是说MFC封装了WindowsAPI你说你喜欢C++而MFC换一种说法就是一个用C++写的一个函数库然后你来调用只不过这个类不是你写的MFC提供数百个类,最重要的、也是编写任何VC++应用程序都必不可少的两个类CWinApp和CFrameWnd,这两个类是编写复杂庞大应用程序的基石。
1>封装特性:
构成MFC框架的是MFC类库而MFC类库又是C++的一个类库。
这些类封装WIN32应用程序编程接口,OLE(ObjectLinkEmbed对象链接嵌入)特性,ODBC和DAO数据访问的功能。
2>继承特性:
MFC抽象出了众多类的共同特性,并设计出一些基类作为实现其他类的基础,这些类中最重要的类是CObject类和CCmdTarget类,程序员可以从适当的MFC类中派生出自己的类,实现特定的功能达到编程的目的。
3>虚拟和消息映射:
MFC是以C++为基础,当然支持虚函数,但作为一个编程框架必须要解决的是效率问题:
如果MFC仅仅通过虚函数来支持动态约束必然会产生大量的虚函数表这样编程框架过于臃肿而且消耗更多的内存。
但是MFC建立了消息映射机制这样降低了内存的使用却大大提高了效率消息映射是一个将消息和成员函数相互关联的表,当应用程序的框架窗口接收到一个消息时,MFC将搜索该窗口的消息映射,如果存在一个处理消息的处理程序,那么就调用该处理程序.它通过宏来实现消息到成员函数的映射,而且这些函数不必是虚拟的成员函数,这样不需要为消息映射函数生成一个很大的虚拟函数表(V表),节省内存。
MFC消息映射机制:
将消息与消息处理函数联系起来,形成一一对应的机制。
消息映射宏声明:
DECLARE_MESSAGE_MAP
定义:
BEGIN_MESSAGE_MAP{
ON_COMMAND
ON_CONTROL
ON_MESSAGE}END_MESSAGE_MAPMFC主要组成部分:
类、宏和全局函数。
类是MFC中最主要的内容。
MFC类是以层次结构方式组织起来的。
MFC中的类分成两部分,除了一些辅助类,大多数的MFC类是直接或间接从根类CObject派生而来。
MFC宏主要功能:
消息映射、运行时对象类型服务、诊断服务、异常处理。
MFC约定:
全局函数以“Afx”为前缀,全局变量以“afx”为前缀MFC类的层次关系CObject项目类)->CCmdTarget(消息响应类)->{
CWinThread(线程类)->CWinApp(Window应用程序类)
CDocument(文档类)
CWnd(窗体类)->[
CFrameWnd(框架类)
CView(视图类)]}
CObject类由于MFC中大部分类是从CObject类继承而来的,CObject类描述了几乎所有的MFC类的一些公共特性,CObject类为程序员提供了对象诊断、运行时类型识别和序列化等功能。
CCmdTarget类由CObject类直接派生而来,它负责将消息发送到能够响应这些消息的对象。
它是所有能进行消息映射的MFC类的基类。
CWinApp类在任何MFC应用程序中有且仅有一个CWinApp派生类的对象,它代表了程序中运行的主线程,也代表了应用程序本身。
CWinApp类取代了WinMain()主函数在SDK应用程序中的地位。
传统SDK应用程序WinMain()函数完成的工作。
现在由类CWinApp的InitApplication(),InitInstance()和Run()三个成员函数承担。
CWnd类由CCmdTarget类直接派生而来,该类及其派生类的实例是一个窗口。
CWnd类代表了MFC中最基本的GUI对象,它是一个功能最完善、成员函数最多的MFC类。
CFrameWnd类是CWnd类的派生类,主要用来掌管一个窗口,它取代了SDK应用程序中窗口函数WndProc()的地位。
CFrameWnd类的对象是一个框架窗口,包括边框、标题栏、菜单、最大化按钮、最小化按钮和一个激活的视图。
CDocument类在应用程序中作为用户文档类的基类,它代表了用户存储或打开的一个文件。
CView类是MFC中一个很基本的类,它作为其它MFC视图类和用户视图派生类的基类。
从API编程到MFC编程的过渡:
WinMain(){
初始化WNDCLASS
注册窗体结构
创建窗口->>>>>>>>应用程序类CwinApp
显示窗口
消息循环}
WndProc(){switch(…)->>>>>>>>>框架窗口类CFrameWnd
}
MFCObject和WindowsObject的对应关系:
描述Windows句柄MFCObject窗口(对象)
HWNDCWnd
设备上下文HDCCDC
菜单HMENUCMenu
笔HPENCPen
刷子HBRUSHCBrush
字体HFONTCFont
位图HBI
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 孙鑫 VC 学习