首页 VC++技术内幕(第四版)

VC++技术内幕(第四版)

举报
开通vip

VC++技术内幕(第四版)第一章:MicrosoftWindows和VisualC++1,Windows应用程序中一定要有WinMain函数,用来完成某些特殊的任务,其中最主要的是创建应用次序的主窗口。2,DOS下,所有次序的目标模块在创建过程中都被静态连接起来。而Windows允许动态连接,即一些特定结构的库(DLL)可以在运行过程中被装入和连接,并且被多个应用程序共享。3,项目是一些相互关联的源文件的集合,这些源文件经过编译、连接,然后被组合在一起形成可执行的Wwindows应用程序或DLL。4,几个重要DeveloperStudio创...

第一章:MicrosoftWindows和VisualC++1,Windows应用程序中一定要有WinMain函数,用来完成某些特殊的任务,其中最主要的是创建应用次序的主窗口。2,DOS下,所有次序的目标模块在创建过程中都被静态连接起来。而Windows允许动态连接,即一些特定结构的库(DLL)可以在运行过程中被装入和连接,并且被多个应用程序共享。3,项目是一些相互关联的源文件的集合,这些源文件经过编译、连接,然后被组合在一起形成可执行的Wwindows应用程序或DLL。4,几个重要DeveloperStudio创建的中间文件:CLW(支持ClassWizard) DSP(项目文件)DSW(工作空间文件)  NCB(支持ClassView)OPT(保持工作空间的配置) PLG(建立日志文件)5,AppWizard是一个代码生成器,它会按照用户通过对话框指定的特性、类名、及源代码文件名来产生Windows应用程序工作架构。AppWizard所产生的代码只是一些最基本的代码,它完成的功能完全由应用程序的基类所决定。第二章:Microsoft基本类库应用程序框架1,按照惯例,MFC库类名用大写“C”打头。2,类CMyApp的对象theApp就代 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 一个应用程序。当运行该应用程序的时候,WINDOWS自动调用程序框架内部的WinMain函数,WinMain函数会去查找该应用程序的全局构造对象(theApp),该对象是有CWinApp类派生类的对象。C++中,全局对象在主程序被运行之前就已经构造好了。3,当WinMain发现该应用程序对象(theApp)时,会自动调用虚拟成员函数CWinApp::InitInstance(),该函数会进一步调用相应的函数来完成主窗口的构造和显示工作。由于基类CWinApp中不知道我们实际需要的什么样的窗口,所以我们必须在派生出的应用程序类CMyApp中重载InitInstance()函数(CMyApp::InitInstance()),由多态性,当调用CWinApp::InitInstance()时候,会自动转向MyApp::InitInstance().4,WinMain函数调用完InitInstance()函数后,就调用CWinApp::Run函数,CWinApp::Run函数被隐藏在基类中负责传递应用程序的消息给相应的窗口,从而维护应用程序的运转。5,关闭应用程序(对单一框架程序来说),首先CMyFrame对象被删除,然后退出Run,进而退出WinMain,最后删除CMyApp对象(theApp)。6,一些Windows类库在基类为鼠标事件消息以及其他一些标准消息定义一些虚函数,如果需要,派生类会对这些函数进行重载。MFC库应用程序框架没有采用虚函数来处理Windows消息,而是通过一些宏来将特定的消息映射到派生类中相应的成员函数上。(原因:P21。C++类对程序中用到的每一个派生类都要求有一张虚函数分发表VTABLE,在BTABLE中每个虚函数都需要有一个4字节的入口项,而不管该函数会不会在派生类中被重载。)MFC消息控件函数要求提供函数原型,函数体,以及在消息映射中的入口。7,文档-视图结构将数据从用户对数据的观察中分离出来,这样就允许对同一数据可以有多个视图。MFC库应用程序中,文档和视图是由C++类的实例来描述的。文档基类代码通常和FILEOPEN,FILESAVE菜单项关联,而派生文档类则一般用来完成对文档对象数据的实际读写工作。视图基类通常表示一个包含于框架窗口中的窗口,而派生视图类则常用来和稳当类相联系,负责应用程序的显示和打印机I/O。派生视图类及其基类共同处理WINDOWS的消息,而MFC库则协调文档,视图,框架窗口,以及应用程序之间的相互作用关系,这种协调多用虚函数来实现。文档对象既可以与一次可全部读入内存的磁盘文件相关联,也可以同数据库相关联。第三章:从“Hello,world!”着手学习AppWizard1,视图:从用户角度看,视图是一个普通的窗口;从程序员角度看,试图是一个从MFC库中CView类所派生的类的对象。视图对象的行为完全由类的成员函数和数据成员决定,其中包括派生类的特定成员和基类的继承而来的成员。2,CEx03aView类最重要的基类是CWnd和CView。CWnd提供CEx03aView的窗口属性,而CView提供它和应用程序框架其它部分之间的联系,特别是和文档及框架窗口之间的联系。3,视图类中OnDraw成员函数:OnDraw成员函数被 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 成一个虚成员函数,每次当视窗需要被重绘时候,应用程序都要调用OnDraw函数。当用户改变了窗口尺寸,或当前窗口恢复了先前被遮盖的部分,或当前应用程序改变了窗口的数据的时候,窗口都需要被重绘。当用户改变了窗口尺寸,或窗口需要恢复被遮盖的部分,则应用程序自动去调用OnDraw函数。但注意,如果程序中某个函数修改了窗口数据,则它必须通过调用视图所继承的Invalidate(InbalidateRect)成员函数来通知Windows,调用Invalidate后会触发对OnDraw函数的调用。4,WINDOW中不允许直接访问显示硬件,必须通过和窗口相关联的“设备环境”跟显示硬件通讯。MFC中设备环境由CDC类对象来表示。5,利用Win32Debug模式和Win32Release模式开发应用程序。(默认情况不出现BUILD工具栏,可从TOOLS菜单选择Customize项,设置显示Build工具栏,VC6中也可在工具栏上直接点击右键选择Build工具栏)  Win32Release模式 Win32Debug模式   源码调试 不能   编译器连接器都允许MFC诊断宏 不能(定义了NDEBUG) 可以(定义了_DEBUG)库连接  MFCRelease库  MFCDebug库编译优化 速度优化(学习版不能) 没有优化(快速编译)我们应在Win32Debug模式下开发应用程序,然后在发布或交付前用Win32Release模式重建应用程序。in32Release模式下建立的EXE文件又小又快。6,诊断宏TRACE宏对监测程序状态特别有用。这些宏要求在允许追踪的情况下才有效,允许追踪是默认设置。(问题:TRACE宏的应用事例与运行原理。宏TRACE的输出在在哪显示呢?在output输出框下选择Debug项,调试运行程序即可看到TRACE宏输出。)7,预编译头文件代表了编译器在源代码特定行上进行‘快照’。在MFC库程序中,快照常紧接在#include"stdafx.h"后进行。文件StdAfx.h包含了MFC库头文件的#include语句。该文件的内容取决于运行AppWizard时候所做的选择。文件StdAfx.cpp只包含#include"stdafx.h"语句。StdAfx.cpp文件用来在相应项目的目录下产生预编译头文件(PCH文件)。编译开关/Yc只用于StdAfx.cpp文件,导致产生预编译头文件(PCH),而其它源文件的/Yu编译开关使可以使用一个存在的PCH文件。开关/Fp用来指定专门的PCH文件名,默认情况下为相应目标输出文件目录下与项目同名扩展名为PCH的文件。(VC6下具体设置参见:[ProjectSettings属性框][c/c++]属性页[Project Options]、[SourceFileOptions]项)(注意:在VC6 [ProjectSettings属性框]中查看StdAfx.cpp文件[SourceFileOptions]项时候,可以看到[ProjectSettings,and/Yc"stdafx.h"],这里说明一下,StdAfx.cpp文件的[/Yc"stdafx.h" ]的设置覆盖了[ProjectOptions]设置中的[/Yu"stdafx.h"])第四章:基本事件处理、映射模式和滚动视图1,消息映射:如在视窗中按下鼠标做键,会自动发送WM_LBUTTONDOWN消息,如果要对这消息有所反应的话,需//{{AFX_MSG(CEx04aView) afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);//头文件声明消息响应函数原型。//}}AFX_MSGDECLARE_MESSAGE_MAP()//头文件BEGIN_MESSAGE_MAP(CDrawView,CView)//代码文件 //{{AFX_MSG_MAP(CEx04aView) ON_WM_LBUTTONDOWN()//该消息映射宏将OnLButtonDown函数和应用程序框架联系在一起 //}}AFX_MSG_MAPEND_MESSAGE_MAP()voidCDrawView::OnLButtonDown(UINTnFlags,CPointpoint)//代码文件{ //eventprocessingcodehere}说明:为了方便ClassWizard,AppWizard生成了一些注释行。它把消息映射函数原型放在两个AFX_MSG“刮弧对”之间,在AFX_MSG_MAP“刮弧对”之间添加消息映射入口,并在代码文件中给出完整的OnLButtonDown成员函数框架。2,视图中的OnDraw()是根据视图当前状态来绘制图象的,用户的操作可以改变这中状态。在完整的MFC库应用程序中,文档的对象掌握在应用程序(视图)的状态。3,如果用全程变量来保存视图状态,这将在多视图情况下会遇到麻烦;(待体会)4,CWnd::InvalidateRect函数能够触发WM_PAINT消息,该消息被窗口类如CView映射后,引起对OnDraw函数调用,从而重绘无效矩形区域。优化窗口的绘制过程:1)设置的无效区域越小,重画的速度就越快;2)执行无效区域外的绘制纯属于浪费时间,OnDraw函数可以调用CDC的成员函数GetClipBox得到无效区域大小。注意:OnDraw函数不仅仅响应InValidate*之类的调用,它也会在窗口改变大小和窗口显露时被调用。5,本章重要介绍函数PtInRect(..);//测试一个点是否落在某个矩形内。PtInRegion(..);//判断一个点是否落在椭圆(CRgn对象)内//Aregionisanellipticalorpolygonalareawithinawindow.GetClientRect(..);//获得客户矩形坐标并保持在CRect对象中SelectStockObject(..);//选择thepredefinedstockpens,brushes,orfonts到DC中,函数返回先前的CGdiObject对象指针。6,在构造函数中对类数据成员初始化。CEx04aView::CEx04aView():m_rectEllipse(0,0,200,200)//注意这种初试化方式,m_rectEllipse是CEx04aView类数据成员CRect类对象{ m_nColor=GRAY_BRUSH;}7,[致WIN32程序员]: 标准的基于WINDOWS应用程序会首先登记一个窗口类(不同于C++类[补:实际是个_WNDCLASS结构体]),同时在处理过程中,还需要对每个类指定窗口过程(WINDOWSPROCEDURE)。每次应用程序调用CreateWindow建立一个窗口时候,都要指定一个窗口类做为参数,这样就把新建立的窗口和窗口过程函数连接起来了。每次Windows给窗口发送消息时候,这个函数就会被调用(补:消息循环中DispatchMessage(&msg)分派消息到窗口的回调函数处理,OS调用窗口回调函数进行处理),以检查用参数传送进来的消息码,并执行适当的代码来处理该消息。 MFC库应用程序框架有一个适用于大多数窗口类型的简单窗口类和窗口过程函数。该窗口过程函数会根据参数传进来的窗口句柄,在MFC的句柄映射表(handlemap)中查找,从而得到对应的C++窗口对象指针。然后,该窗口过程函数用MFC运行时类(runtimeclass)系统来决定窗口对象的C++类。下一步,它从由消息分发映射函数生成的静态表中找到消息处理函数,最后用正确的窗口对象调用消息处理函数。8,映射模式:1)MM_TEXT映射模式:坐标被映射到象素,X值向右递增,Y值向下递增。可用它来表示[设备坐标]。CDC::SetMapMode(..)//设置映射模式CDC::GetMapMode(..)CDC::SetViewportOrg(..)//设置视口原点CDC::GetViewportOrg(..)CDC::SetWindowOrg(..)//设置屏幕原点CDC::GetWindowOrg(..)2)固定比例映射模式(MM_HIENGLISH,MM_HIMETRIC,MM_LOMETRIC,MM_LOENGLISH,MM_TWIPS)固定比例映射模式均X值向右递增,Y值向下递增,它们之间唯一差别是实际的比例因子。如下:MM_HIENGLISH  Eachlogicalunitisconvertedto0.001inch.MM_HIMETRIC  Eachlogicalunitisconvertedto0.01millimeter.MM_LOENGLISH  Eachlogicalunitisconvertedto0.01inch.MM_LOMETRIC  Eachlogicalunitisconvertedto0.1millimeter.MM_TWIPS  Eachlogicalunitisconvertedto1/20ofapoint(磅).(Becauseapointis1/72inch,atwipis1/1440inch.)//MM_TWIPS常常用于打印机。        3)可变比例映射模式:(MM_ISOTROPIC,MM_ANISOTROPIC)这两种模式用许我们改变它们的比例因子和坐标原点。应用这两中模式,如用户改变窗口的尺寸,绘制的图形大小也会发生响应的变化具体如下:TheMM_HIENGLISH,MM_HIMETRIC,MM_LOENGLISH,MM_LOMETRIC,andMM_TWIPSmodesareusefulforapplicationsthatmustdrawinphysicallymeaningfulunits(suchasinchesormillimeters).TheMM_ISOTROPICmodeensuresa1:1aspectratio,whichisusefulwhenitisimportanttopreservetheexactshapeofanimage.TheMM_ANISOTROPICmodeallowsthex-andy-coordinatestobeadjustedindependently常一起使用的函数:SetWindowExt(..)//Setsthex-andy-extentsofthewindowassociatedwiththedevicecontext.SetViewportExt(..)//Setsthex-andy-extentsoftheviewportofthedevicecontext. 注意:Whenthefollowingmappingmodesareset,callstoSetWindowExtandSetViewportExtfunctionsareignored: MM_HIENGLISH,MM_HIMETRIC,MM_LOENGLISH,MM_LOMETRIC,MM_TEXT,MM_TWIPSWhenMM_ISOTROPICmodeisset,anapplicationmustcalltheSetWindowExtmemberfunctionbeforecallingSetViewportExt.9,坐标变换:(具体参见P54)许多MFC库函数只能在设备坐标下工作(尤其CRect类成员函数)。可以认为CDC的所有成员函数都一逻辑坐标作参数。可以认为CWnd的成员函数都以设备坐标做参数。(所有在实际窗口上点击获得的坐标都是逻辑坐标)。在设置了设备环境的映射模式及相应的参数以后,CDC的LPtoDP和DPtoLP函数可以用来在逻辑坐标系和设备做表系之间进行转换。在CView的虚函数OnPrepareDC中设置映射模式要比在OnDraw函数中要好。//*注意:CView::OnPrepareDCvirtualvoidOnPrepareDC(CDC*pDC,CPrintInfo*pInfo=NULL);应用程序将在调用OnDraw之前调用OnPrepareDC函数。(OnPrepareDC在为屏幕显示而调用OnDraw函数之前,或在为打印或打印预览每一页而调用OnPrint成员函数之前。)10,CScrollView支持滚动条的滚动,但不支持键盘的滚动。通过使用CWnd的ScrollWindow和SetViewportOrg函数,CScrollView类允许将视口原点移到窗口中的任何一个位置,甚至包括窗口区域的上部或窗口的原点的左边。键盘输入是分两步处理的。OS向窗口发送类如WM_KEYDOWN和WM_KEYUP消息时用的是虚拟键盘码,在消息到达窗口之前,被翻译成WM_CHAR消息,该消息带着正常的键码。利用对WM_KEYDOWN消息进行响应,对按键分别调用OnVScroll就可以使应用程序支持键盘的滚动。CWnd::OnVScroll afx_msgvoidOnVScroll(UINTnSBCode,UINTnPos,CScrollBar*pScrollBar);nSBCode:SB_BOTTOM  Scrolltobottom.SB_ENDSCROLL  Endscroll.SB_LINEDOWN  Scrollonelinedown.SB_LINEUP  Scrollonelineup.SB_PAGEDOWN  Scrollonepagedown.SB_PAGEUP  Scrollonepageup.SB_THUMBPOSITION  Scrolltotheabsoluteposition.ThecurrentpositionisprovidedinnPos.SB_THUMBTRACK  Dragscrollboxtospecifiedposition.ThecurrentpositionisprovidedinnPos.SB_TOP  Scrolltotop.////Theframeworkcallsthismemberfunction(OnVScroll)whentheuserclicksthewindow’sverticalscrollbar.11,CView::OnInitialUpdatevirtualvoidOnInitialUpdate();说明:OnInitialUpdate是视图窗口完全建立后框架调用的第一个函数。框架在第一次调用OnDraw前会调用OnInitialUpdate。具体参见下:Calledbytheframeworkaftertheviewisfirstattachedtothedocument,butbeforetheviewisinitiallydisplayed.ThedefaultimplementationofthisfunctioncallstheOnUpdatememberfunctionwithnohintinformation.12,MFC对140种Windows消息直接直接提供了相应的消息控制函数,当然,我们还可以定义自己的消息和相应的消息控制函数。五种特殊Windows消息:WM_CREATE,WM_CLOSE,WM_QUERYENDSESSION,WM_DESTROY,WM_NCDESTROY.(具体参见p62-63页。这两页强烈建议看看,这里简要笔记三个最常用最重要的)1)WM_CREATE消息:TheWM_CREATEmessageissentwhenanapplicationrequeststhatawindowbecreatedbycallingtheCreateWindowExorCreateWindowfunction.Thewindowprocedureofthenewwindowreceivesthismessageafterthewindowiscreated,butbeforethewindowbecomesvisible.ThemessageissentbeforetheCreateWindowExorCreateWindowfunctionreturns.2)WM_CLOSE消息:当关闭窗口或父窗口被关闭时,Windows都会发送WM_CLOSE消息。可以重新定义该消息响应函数OnClose来完全控制关闭过程。3)WM_DESTROY消息:Windows在发送WM_CLOSE消息之后,紧接着就会发送WM_DESTROY消息(响应这个消息的时候,窗口已经消失但还没有销毁)。(可以响应这个消息来做一些销毁当前窗口后的一些事情,例如再弹出其它对话框发送其他的消息)第五章:图形设备接口(GDI)、颜色及字体1,任何时候当程序需要直接在屏幕或打印机上绘图的时候,都需要调用GDI函数,GDI函数包含了一些用于绘制图形、位图以及文本的函数。2,Windows的设备环境是GDI的关键元素,它代表了物理设备。每一个C++设备环境对象都有与之对应的Windows设备环境,并且通过一个32位类型的HDC句柄来标识。3,MFC库设备环境类基类CDC包含了绘图所需要的所有成员函数,并且几乎所有派生类只有构造函数和析构函数不同(CMetaFileDC类除外)。对于显示器来说,常用的派生类有CClientDC和CWindowDC,而对其它设备(如打印机或内存缓冲区),则可以构造一个基类CDC的对象。对于显示器和打印机设备环境对象来说,应用程序框架会直接将句柄附在对象上;而对其它设备环境(如内存设备环境),为了将对象与句柄相联系,在构造完对象之后,还必须调用一个成员函数(进行初试化)。4,CClientDC类和CWindowDC类CClientDC(CWnd*pWnd);//ConstructsaCClientDCobjectthataccessestheclientareaoftheCWndpointedtobypWnd.TheconstructorcallstheWindowsfunctionGetDC.CWindowDC(CWnd*pWnd);//ConstructsaCWindowDCobjectthataccessestheentirescreenarea(bothclientandnonclient)oftheCWndobjectpointedtobypWnd.TheconstructorcallstheWindowsfunctionGetWindowDC.如果构造CClientDC对象,则设备环境的映射区域限于客户区域,不能在客户区域外绘图。原点(0,0)在客户区左上角。《如果创建CWindowDC对象,则设备环境的映射区域为整个窗口(包括标题栏、状态栏、窗口边框等)。原点(0,0)在整个窗口的左上角。》注意:1)视图窗口没有非客户区域.2)视图窗口覆盖在框架窗口之上。3)在《》中的内容,是我根据测试所理解的。翻译原文中映射区域是整个显示屏幕,原点(0,0)在整个屏幕的左上角。这显然是不对的。5,在创建了一个CDC对象后,一定要注意在完成任务后将其删除。(如果用CClientDC或CWindowDC来在堆栈中构造一个DC对象,则不需要我们显式的删除它,CClientDC或CWindowDC对象会在它的生命周期结束的时候自动调用析构函数来完成删除工作)例如:CDC*pDC=GetDC();...RealeaseDC(pDC);说明:CDC*GetDC();//CWnd::GetDC获得与当前窗口相关联的CDC对象指针(映射窗口客户区域)intReleaseDC(CDC*pDC);//CWnd::ReleaseDC释放与当前窗口相关联的设备环境注意:在MFC程序中,千万不能自己添加代码删除作为参数以指针形式传递给OnDraw(CDC*pDC)函数的CDC对象,应用程序会自动控制它的删除。6,当利用CDC对象绘图的时候,所绘制的图形都要依赖于设备环境的状态:如画笔、画刷、字体等GDI绘图对象和当前映射模式的选择等。可以使用CDC成员函数了设置所需要的饿设备环境状态。如:SelectObject()函数可将GDI对象随时选入设备环境中。7,CPaintDC类:当需要重写OnPaint函数的时候,就需要使用CPaintDC类。默认的OnPaint函数会使用已经设置好的设备环境来调用OnDraw函数注意:CPaintDC类的构造函数和析构函数所完成的工作都是针对显示用的。例:voidCMyView::OnPaint(){CPaintDCdc(this);OnPrepareDC(&dc);dc.TextOut(0,0,"forthedisplay,nottheprinter");OnDraw(&dc);}说明:1)CPaintDC(CWnd*pWnd);//CPaintDC::CPaintDCConstructsaCPaintDCobject,preparestheapplicationwindowforpainting,andstoresthePAINTSTRUCTstructureinthem_psmembervariable.2)CPaintDC类的构造函数自动调用BeginPaint,而它的析构函数会自动调用EndPaint.3)CDC*BeginPaint(LPPAINTSTRUCTlpPaint);//CWnd::BeginPaintPreparesCWndforpaintingandfillsaPAINTSTRUCTdatastructurewithinformationaboutthepainting.voidEndPaint(LPPAINTSTRUCTlpPaint);//CWnd::EndPaintMarkstheendofpaintinginthegivenwindow.TheEndPaintmemberfunctionisrequiredforeachcalltotheBeginPaintmemberfunction,butonlyafterpaintingiscomplete.问题:1)在View类中一旦定义了OnPaint()函数,则WM_PAINT消息由OnPaint函数来响应。OnDraw函数不再被调用。原因?8,GDI对象:Class  WindowshandletypeCPen  HPENCBrush  HBRUSHCFont  HFONTCBitmap HBITMAPCPalette HPALETTECRgn  HRGN说明:Eachgraphic-objectclassintheclasslibraryhasaconstructorthatallowsyoutocreategraphicobjectsofthatclass,whichyoumusttheninitializewiththeappropriatecreatefunction,suchasCreatePen.Eachgraphic-objectclassintheclasslibraryhasacastoperatorthatwillcastanMFCobjecttotheassociatedWindowshandle.Theresultinghandleisvaliduntiltheassociatedobjectdetachesit.Usetheobject’sDetachmemberfunctiontodetachthehandle.9,CGdiObject类有一个虚析构函数,在其派生类的析构函数将与C++对象相关联的WINDOWSGDI对象删除掉。如果构造了一个CGdiObject派生类对象,则在退出程序之前,必须将其删除掉。利用CDC类的SelectObject成员函数把自己的GDI对象选进DC的同时,保存原来的GDI对象,当任务完成后,恢复原来的GDI对象,这样就可以将自己的GDI对象的删除掉。如:GDIStyle*poldGdiObject=pDC->SelectObject(&newGdiObject);...//完成任务pDC->SelectObject(poldGdiObject);10,Windows对任何企图删除库存GDI对象的行为都不予理会。可以利用SelectObject函数把库存GDI对象选入,从而删除当前GDI对象。原因:ThisfunctionSelectObjectmayreturnapointertoatemporaryobject.ThistemporaryobjectisonlyvalidduringtheprocessingofoneWindowsmessage.如:pDC->SelectObject(&newGdiObject);...pDC->SelectStockObject(StockCGdiObject);//如:BLACK_BRUSH11,对于显示设备环境,在消息处理函数内部所进行GDI选择在函数退出后不再有效,因此在进入其他处理函数的时候,每次都必须重新设置设备环境。Windows句柄是唯一能够持久存在的GDI标识。可以使用GDI对象指针调用GetSafeHandle函数可以获得它Windows句柄,再利用GDI对象类的FromHandle函数将句柄转化为对应的GDI对象。如:CFont*pOldFont=pDC->SelectObject(&newFont);m_hOldFont=(HFONT)pOldFont->GetSafeHandle();//m_hOldFont为数据成员,保存先前字体对象句柄...pDC->SelectObject(CFont::FromHandle(m_hOldFont));//可在其他函数中,恢复m_hOldFont句柄对应的字体对象。说明:1)staticCFont*PASCALFromHandle(HFONThFont);//CFont::FromHandleReturnsapointertoaCFontobjectwhengivenanHFONThandletoaWindowsGDIfontobject.IfaCFontobjectisnotalreadyattachedtothehandle,atemporaryCFontobjectiscreatedandattached.2)CGdiObject::GetSafeHandle();//ReturnAHANDLEtotheattachedWindowsGDIobject;otherwiseNULLifnoobjectisattached.12,每一种Windows颜色都是通过8位的红(R)、绿(G)、蓝(B)的值祝贺来表示的。面向颜色的GDI函数可以接收32位的COLORREF参数。Windows的RGB宏可以将8位的红绿蓝值转化成COLORREF参数。说明:1)TheCOLORREFvalueisa32-bitvalueusedtospecifyanRGBcolor.2)16种标准VGA纯色参见P70页;256显示卡多增加4种标准色参见P71页。13,字体是GDI对象,在使用上和其它的GDI对象完全一样。CDC::GetTextMetrics BOOLGetTextMetrics(LPTEXTMETRIClpMetrics)const;//测量字体高度等参数14,GetDeviceCaps();//Retrievesawiderangeofdevice-specificinformationaboutthedisplaydevice.第六章:模式对话框和Windows通用控件1,对话框也是窗口,它不当可以接受消息,而且还可以被移动和关闭,甚至可以在它的客户区中进行绘图操作。2,模式对话框在被关闭之前,用户无法在同一应用程序的其它地方进行工作。模式对话框更易于编程。无模式对话框在它仍保留在屏幕的同时,用户还可以在应用程序的其它窗口进行工作。3,对话框控件既可以通过CWnd指针来引用,也可以通过资源文件定义的索引值(和#define常量相关联)来引用。对话框控件本身就是一个窗口。控件通过向上级对话框发送消息来响应用户的动作。利用ClassWizard可以帮助产生CDialog派生类,还可以使对话框类数据成员和对话框控件相联系。4,在现存在项目中添加模式对话框步骤:1)用对话框编辑器创建包含各种控件的对话框资源。对话框编辑器会对项目的资源文件更新,使之包含新的对话框资源,并且该项目的resource.h文件也会被更新,以便能够包含新的#define常量。2)利用ClassWizard创建CDialog派生类,并将它和第一步所创建的资源相连接。3)利用ClassWizard添加控件消息响应函数,并进行编辑。4)在其它类中需要使用地方先构造该对话框类对象,再调用DoModal显示模式对话框。说明:1)在产生的对话框头文件中包含一个枚举类型常量IDD,用于设置该对话框资源ID。枚举常量IDD的使用减弱了CPP文件对资源ID的依赖。2)《在其它类中显示模式对话框后,只有当模式对话框退出后,才继续执行该类显示模式对话框代码后的代码。》5,在组合筐中Data属性页下,添加一条后按CTRL+RETURN来结束(或添加下条item)。(VC6中按?键可以获取相关帮助提示的)。组合框有Simple,Dropdown,DropList三中风格,可以是Styles中选择。列表筐中,用户只能用鼠标选择选择一个条目,而且在对话框编辑器中不能输入列表框的初始选择条目。在静态文本控件中可以内置'&'符号。运行时候,&符号后面的字符下将有一个下划线。用户在按下ALT键后同时按下相应带下划线的字母,则就可以跳转到相应的控件上去。注意同一对话框中跳转字符不能重复。6,当DoModal被调用后,实际在幕后引起一系列如下的动作:CDialog::DoModal->CEx06Dialog::OnInitDialog->其它的初始化->CDialog::OnInitDialog->CWnd::UpdateData(FALSE)->CEx06Dialog::DoDataExchange用户输入数据...用户单击OK按钮CEx06Dialog::OnOk->...其它的确认处理...->CDialog::OnOk->CWnd::UpDateData(TURE)->CEx06Dialog::DoDataExchange->CDialog::EndDialog(IDOK)说明:1)virtualBOOLOnInitDialog();//CDialog::OnInitDialogThismemberfunctioniscalledinresponsetotheWM_INITDIALOGmessage.ThismessageissenttothedialogboxduringtheCreate,CreateIndirect,orDoModalcalls,whichoccurimmediatelybeforethedialogboxisdisplayed.//Overridethismemberfunctionifyouneedtoperformspecialprocessingwhenthedialogboxisinitialized.2)BOOLUpdateData(BOOLbSaveAndValidate=TRUE);//CWnd::UpdateData:Callthismemberfunctiontoinitializedatainadialogbox,ortoretrieveandvalidatedialogdata.//bSaveAndValidate:Flagthatindicateswhetherdialogboxisbeinginitialized(FALSE)ordataisbeingretrieved(TRUE).//BydefaultUpdateData(TRUE)iscalledinthedefaultCDialog::OnOKhandlerandUpdateData(FALSE)iscalledinthedefaultCDialog::OnInitDialog.3)virtualvoidDoDataExchange(CDataExchange*pDX);//CWnd::DoDataExchange Calledbytheframeworktoexchangeandvalidatedialogdata.//Nevercallthisfunction(DoDataExchange)directly.ItiscalledbytheUpdateDatamemberfunction.//CallUpdateDatatoinitializeadialogbox’scontrolsorretrievedatafromadialogbox.4)voidEndDialog(intnResult);//CDialog::EndDialog makesthedialogboxinvisiblebutdoesnotdestroyit.//Callthismemberfunctiontoterminateamodaldialogbox.ThismemberfunctionreturnsnResultasthereturnvalueofDoModal(IDOK表示接受对话框数据,IDCANCEL表示取消对话框数据).YoumustusetheEndDialogfunctiontocompleteprocessingwheneveramodaldialogboxiscreated.//注意:IfyouimplementtheOKbuttoninamodelessdialogbox,youmustoverridetheOnOKmemberfunctionandcallDestroyWindowfromwithinit.5)当DoModal函数返回的时候,对话框窗口不再存在。我们可以在堆栈中创建模式对话框对象,这样就可以保证当程序控制转向到C++对话框对象所在的范围之外时,它及时的删除掉。7,代码解释:voidCEx06aDialog::DoDataExchange(CDataExchange*pDX){ CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CEx06aDialog) DDX_Text(pDX,IDC_BIO,m_strBio);// DDX_Radio(pDX,IDC_CAT,m_nCat); ... DDV_MinMaxInt(pDX,m_nSsn,0,999999999); //}}AFX_DATA_MAP}说明:1)DoDataExchange、DDX_(交换)、DDV_(确认)函数都具有双向性。如果调用UpdateData(FALSE)(参数为FALSE),则这些数据就会将与控件相关联(值关联)的数据成员的值传递给对话框中的控件;相反,如果UpDateData(TURE)(参数是TURE),则这些函数会将数据从对话框控件中传递给与之相关联(值关联)的数据成员。2)这里DDX_Text函数被重载,具体参阅MSDN。TheDDX_Textfunctionmanagesthetransferofint,UINT,long,DWORD,CString,float,ordoubledatabetweenaneditcontrolinadialogbox,formview,orcontrolviewandaCStringdatamemberofthedialogbox,formview,orcontrolviewobject.其它DDX_函数参阅MSDN。8,Enter键触发OnOk函数调用:当用户按下ENTER键后,OS会自动去查找输入焦点落在哪个按钮上,获得焦点的按钮四周将被点线矩形框包围。如果所有的按钮都没获得输入焦点,则OS会自动去寻找程序或资源所指定的默认按钮(默认按钮边框较粗)。如果对话框没有默认按钮,那么即使对话框中没有OK按钮,OnOk函数也会自动被调用。由于OnOk函数是虚函数,可以重写OnOk函数,将其函数体置空,变可以使使ENTER键无效。分离OK按钮:改写OK按钮ID,并除掉其默认按钮(DefaultButton)的设置。9,p107至WIN32程序员:强烈建议看看,下为简要笔记。对话框控件会向他们父对话框发送WM_COMMAND通告消息。大多数窗口程序处理函数都是通过一个嵌套的switch结构了处理这些通告消息的,而MFC则更直接了当地把这些控件通知消息和其它的Windows消息放在同一个层次上处理。10,Esc键触发OnCancel函数的调用,导致控制从对话框中退出,如果是模式对话框则DoModal的还返回IDCANCEL值。其消除方法同ENTER键。11,事例代码涉及的一些主要函数及补充说明:1)CWnd*GetDlgItem(intnID)const;//可用它来获取对话框上控件指针(返回的时候,强制转换成所需要的控件指针),注意临时性。  voidCWnd::GetDlgItem(intnID,HWND*phWnd)const;//Retrievesapointertothespecifiedcontrolorchildwindowinadialogboxorotherwindow.ThepointerreturnedisusuallycasttothetypeofcontrolidentifiedbynID.说明:如果需要包CWnd指针转化成一个控件ID,则可以使用MFC中CWnd类GetDlgCtrlID成员函数。2)GetScrollPos Retrievesthecurrentpositionofascrollbox.  SetScrollPos Setsthecurrentpositionofascrollbox.  GetScrollRange Retrievesthecurrentminimumandmaximumscroll-barpositionsforthegivenscrollbar.  SetScrollRange Setsminimumandmaximumpositionvaluesforthegivenscrollbar.3)afx_msgvoidOnHScroll(UINTnSBCode,UINTnPos,CScrollBar*pScrollBar);//CWnd::OnHScroll afx_msgvoidOnVScroll(UINTnSBCode,UINTnPos,CScrollBar*pScrollBar);//CWnd::OnVScroll 3)所有的水平滚动条都绑在WM_HSCROLL消息控制函数,所有的竖直滚动条则都绑在一个WM_VSCROLL消息控制函数上。(一般控件都有自己的独立的消息控制函数,但[滚动条控件]有点不同,所以对同一个对话框多个滚动条消息处理的时候,一般都将它们的滚动范围设置一致,方便编程)///P109-125页内容笔记待续12,每个控件在显示之前会向其父对话框发送WM_CTLCOLOR消息,对话框本身也会发送该消息。《对话框和对话框控件都是窗口,也可以在这些窗口中进行绘图操作。(添加OnPaint函数,调用Invalidate/UpdateWindow让窗口重绘)》13,在运行时加入对话框控件:一般步骤:1)在对话框类中添加一个内嵌的控件窗口数据成员。一个内嵌控件C++对象将与相应的对话框对象一起被构造和删除。2)从View菜单中选择ResourceSymbols,为新的控件添加一个ID常量。(也可以在Resource.h中用定义)3)用ClassWizard映射WM_INITDIALOG消息覆盖(Override)基类CDialog::OnInitDialog函数。在该函数里调用控件窗口的Create成员函数,并显示新的控件(可以用ShowWindow函数)。Windows回在删除对话框窗口的同时也删除该控件窗口。4)在派生对话框类里,为新控件手工加入必要的通知消息控制函数。(三步:消息控制函数原型说明,消息映射,消息处理函数)14,Win32编程经验:父窗口和控件之间是通过Windows消息进行通信的(如MFC中象CListBox::InserString函数),但适用于所有窗口类型的控件类成员函数并不发送消息,而是调用Win32函数。15,Windows通用控件:Win95引进的象[进度指示器],[滑杆条],[微调按钮控件],[列表控件]和[树状控件]。这些控件的代码在Windows的COMCTL32.DLL文件中,其中包括了每个控件的窗口过程函数,及每个控件的注册窗口类的代码,这些注册代码在DLL加载时候被调用。当应用程序初始化对话框时,将使用对话框资源中符号化的类名,来连接到DLL里的窗口过程函数上。这样应用程序就有了控件的窗口,但代码实际上在DLL里。除了ActiveX控件,大多数控件都是用这种方法实现的。16,WM_NOTIFY   idCtrl=(int)wParam;//控件ID   pnmh=(LPNMHDR)lParam;//指向NMHDR结构指针,该结构由控件管理。说明:1)Sentbyacommoncontroltoitsparentwindowwhenaneventhasoccurredinthecontrolorthecontrolrequiressomekindofinformation.2)Notallcontrolswil
本文档为【VC++技术内幕(第四版)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 已有0 人下载
最新资料
资料动态
专题动态
is_549963
暂无简介~
格式:doc
大小:115KB
软件:Word
页数:
分类:工学
上传时间:2011-11-22
浏览量: