首页 孙鑫C++教程(全20讲)PPT讲义

孙鑫C++教程(全20讲)PPT讲义

举报
开通vip

孙鑫C++教程(全20讲)PPT讲义第一章 Windows程序内部运行原理 主讲人:孙鑫 1、Windows应用程序,操作系统,计算机硬件之间的相互关系 2、关于API 向下的箭头③表示应用程序可以通知操作系统执行某个具体的动作,如操作系统能够控制声卡发出声音,但它并不知道应该何时发出何种声音,需要应用程序告诉操作系统该发出什么样的声音。这个关系好比有个机器人能够完成行走的功能,但是,如果人们不告诉它往哪个方向上走,机器人是不会主动行走的。这里的机器人就是操作系统,人们就是应用程序。 那么,应用程序是如何通知操作系统执行某个功能的呢?有过编程经验的读...

孙鑫C++教程(全20讲)PPT讲义
第一章 Windows程序内部运行原理 主讲人:孙鑫 1、Windows应用程序,操作系统,计算机硬件之间的相互关系 2、关于API 向下的箭头③表示应用程序可以通知操作系统执行某个具体的动作,如操作系统能够控制声卡发出声音,但它并不知道应该何时发出何种声音,需要应用程序告诉操作系统该发出什么样的声音。这个关系好比有个机器人能够完成行走的功能,但是,如果人们不告诉它往哪个方向上走,机器人是不会主动行走的。这里的机器人就是操作系统,人们就是应用程序。 那么,应用程序是如何通知操作系统执行某个功能的呢?有过编程经验的读者都应该知道,在应用程序中要完成某个功能,都是以函数调用的形式实现的,同样,应用程序也是以函数调用的方式来通知操作系统执行相应的功能的。操作系统所能够完成的每一个特殊功能通常都有一个函数与其对应,也就是说,操作系统把它所能够完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用就叫做系统调用,这些函数的集合就是Windows操作系统提供给应用程序编程的接口(Application Programming Interface),简称Windows API。如CreateWindow就是一个API函数,应用程序中调用这个函数,操作系统就会按照该函数提供的参数信息产生一个相应的窗口。 3、关于消息及消息队列 向上的箭头④表示操作系统能够将输入设备的变化上传给应用程序。如用户在某个程序活动时按了一下键盘,操作系统马上能够感知到这一事件,并且能够知道用户按下的是哪一个键,操作系统并不决定对这一事件如何作出反应,而是将这一事件转交给应用程序,由应用程序决定如何对这一事件作出反应。好比有个蚊子叮了我们一口,我们的神经末梢(相当于操作系统)马上感知到这一事件,并传递给了我们的大脑(相当于应用程序),我们的大脑最终决定如何对这一事件作出反应,如将蚊子赶走,或是将蚊子拍死。对事件作出反应的过程就是消息响应。 操作系统是怎样将感知到的事件传递给应用程序的呢?这是通过消息机制(Message)来实现的。操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序,参看MSDN。 MSG结构定义如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG; 4、关于句柄 (1)句柄(HANDLE),资源的标识。 (2)操作系统要管理和操作这些资源,都是通过句柄来找到对应的资源。按资源的类型,又可将句柄细分成图标句柄(HICON),光标句柄(HCURSOR),窗口句柄(HWND),应用程序实例句柄(HINSTANCE)等等各种类型的句柄。操作系统给每一个窗口指定的一个唯一的标识号即窗口句柄。 5、从变量的类型区分变量的用途 int x,y; x=30; y=30; //x和y既可以用来表示坐标点,也可以用来表示宽度和高度,还可以用来表示身高和体重。 typedef int WIDTH typedef int HEIGHT WIDTH x; HEIGHT y; //好处:我们从变量的类型上就可以知道x和y是用来表示宽度和高度。 6、WinMain函数 (1)Windows程序的入口函数 int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state ); 7、窗口的创建 创建一个完整的窗口需要经过下面四个操作步骤: (1)设计一个窗口类;(2)注册窗口类;(3)创建窗口;(4)显示及更新窗口。 8、设计窗口类 typedef struct _WNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HANDLE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS; 9、窗口类的类型 在我们的程序中经常要用到一类变量,这个变量里的每一位(bit)都对应某一种特性。当该变量的某位为1时,表示有该位对应的那种特性,当该位为0时,即没有该位所对应的特性。当变量中的某几位同时为1时,就表示同时具有几种特性的组合。一个变量中的哪一位代表哪种意义,不容易记忆,所以我们经常根据特征的英文拼写的大写去定义一些宏,该宏所对应的数值中仅有与该特征相对应的那一位(bit)为1,其余的bit都为0。我们使用goto definition就能发现CS_VREDRAW=0x0001,CS_HREDRAW=0x0002,CS_DBLCLKS =0x0008,CS_NOCLOSE=0x0200。他们的共同点就是只有一位为1,其余位都为0。如果我们希望某一变量的数值既有CS_VREDRAW特性,又有CS_HREDRAW特性,我们只需使用二进制OR(|)操作符将他们进行或运算相组合,如style=CS_VREDRAW | CS_HREDRAW | CS_NOCLOSE。如果我们希望在某一变量原有的几个特征上去掉其中一个特征,用取反(~)之后再进行与(&)运算,就能够实现,如在刚才的style的基础上去掉CS_NOCLOSE特征,可以用style & ~CS_NOCLOSE实现。 10、窗口过程函数 第二个成员变量lpfnWndProc指定了这一类型窗口的过程函数,也称回调函数。回调函数的原理是这样的,当应用程序收到给某一窗口的消息时(还记得前面讲过的消息通常与窗口相关的吗?),就应该调用某一函数来处理这条消息。这一调用过程不用应用程序自己来实施,而由操作系统来完成,但是,回调函数本身的代码必须由应用程序自己完成。对于一条消息,操作系统到底调用应用程序中的哪个函数(回调函数)来处理呢?操作系统调用的就是接受消息的窗口所属的类型中的lpfnWndProc成员指定的函数。每一种不同类型的窗口都有自己专用的回调函数,该函数就是通过lpfnWndProc成员指定的。 举例:汽车厂家生产汽车好比应用程序创建窗口,用户使用汽车好比操作系统管理窗口,某种汽车在销售前就指定好了修理站(类似回调函数),当用户的汽车出现故障后(类似窗口收到消息),汽车用户(类似操作系统)自己直接找到修理站去修理,不用厂家(类似应用程序)亲自将车送到修理站去修理,但修理站还得由厂家事先建造好。 第二章 掌握C++ 1、C++的标准输入输出流 C++中提供了一套输入输出流类的对象,它们是cin 、cout和cerr,对应c语言中的三个文件指针stdin、stdout、stderr,分别指向终端输入、终端输出和标准出错输出(也从终端输出)。cin与>>一起完成输入操作,cout、cerr与<<一起完成输出与标准错误输出。利用cin和cout比C语言中的scanf和printf要方便得多,cin和cout可以自动判别输入输出数据类型而自动调整输入输出格式,不必像scanf和printf那样一个个由用户指定。使用cin,cout不仅方便,而且减少了出错的可能性。对于输出来说,我们像以上方式调用就可以了,对于输入来说,我们以如下方式调用即可: int i; cin>>i; 注意箭头的方向。在输出中我们还使用endl(end of line),表示换行,注意最后一个是字符‘l’,而不是数字1,endl相当于C语言的'\n',表示输出一个换行。 2、C++的特性 2.1构造函数 (1)构造函数最重要的作用是创建对象本身 。 (2)C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。 (3)C++又规定,如果一个类没有提供任何的构造函数,则C++提供一个默认的构造函数(由C++编译器提供),这个默认的构造函数是一个不带参数的构造函数,它只负责创建对象,而不做任何的初始化工作。 (4)只要一个类定义了一个构造函数,不管这个构造函数是否是带参数的构造函数,C++就不再提供默认的构造函数。也就是说,如果为一个类定义了一个带参数的构造函数,还想要无参数的构造函数,则必须自己定义。 2.2析构函数 (1)当一个对象生命周期结束时,其所占有的内存空间就要被回收,这个工作就由析构函数来完成。 (2)析构函数是“反向”的构造函数,析构函数不允许有返回值,更重要的是析构函数不允许带参数,并且一个类中只能有一个析构函数。 (3)析构函数的作用正好与构造函数相反,对象超出其作用范围,对应的内存空间被系统收回或被程序用delete删除时,析构函数被调用。 (4)根据析构函数的这种特点,我们可以在构造函数中初始化对象的某些成员变量,给其分配内存空间(堆内存),在析构函数中释放对象运行期间所申请的资源。 2.3函数的重载 (1)重载构成的条件:函数的参数类型、参数个数不同,才能构成函数的重载。 (2) 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 以下两种情况,是否构成函数的重载。 第一种情况:(1)void output(); (2)int output(); 第二种情况:(1)void output(int a,int b=5); (2)void output(int a); 2.4this指针 (1)this指针是一个隐含的指针,它是指向对象本身,代表了对象的地址 (2)一个类所有的对象调用的成员函数都是同一代码段。那么成员函数又是怎么识别属于同一对象的数据成员呢?原来,在对象调用pt.output(10,10)时,成员函数除了接受2个实参外,还接受到了一个对象s的地址。这个地址被一个隐含的形参this指针所获取,它等同于执行this=&pt。所有对数据成员的访问都隐含地被加上前缀this->。例如:x=0; 等价于 this->x=0。 小技巧:在以后的MFC编程中,如果在成员函数中想调用同类中的某个成员,可以使用VC++提供的自动列出成员函数功能,使用this->,VC++将列出该类中的所有成员,我们可以从列表中选择我们想调用的成员。 自动列出成员函数功能,可以提高编写速度,减少拼写错误。我们经常不能完全记住某个函数的完整拼写,但却能够从列表中辨别出该函数,自动列出成员函数的功能在这时就显得更加有用了。事实上,在各种IDE编程环境中,我们通常都不可能记住也没有必要记住所有的函数,只要将常用的函数记住,其他不常用的函数只要记住其大概的写法和功能,在调用该函数时可以从自动列出成员函数中选取,这样可以大大节省我们的学习时间。我们不用花费大量的时间去死记硬背许多函数,利用自动列出成员函数功能和帮助系统,就能够在编程时顺利地使用这些函数,等用的次数多了,也就在不知不觉中完全掌握了这些函数。 2.5类的继承 (1)在C++中,给我们提供了一种重要的机制,就是继承。 理解继承是理解面向对象程序设计的关键。 (2)类的继承访问特性 基类的访问特性 类的继承特性 子类的访问特性 Public Protected Private Public Public Protected No access Public Protected Private Protected Protected Protected No access Public Protected Private Private Private Private No access 2.6函数的覆盖 函数的覆盖是发生在父类与子类之间的。 (1)类型转换 (2)Fish对象内存布局 2.7多态性 当C++编译器在编译的时候,发现Animal类的breathe()函数是虚函数,这个时候C++就会采用迟绑定(late binding)的技术,在运行时,依据对象的类型(在程序中,我们传递的Fish类对象的地址)来确认调用的哪一个函数,这种能力就做C++的多态性。 3、引用和指针变量的内存模型 4、VC++程序编译链接原理与过程 第六章 菜单 1、消息的分类 (1)标准消息 除WM_COMMAND之外,所有以WM_开头的消息。从CWnd派生的类,都可以接收到这类消息。 (2)命令消息 来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。从CCmdTarget派生的类,都可以接收到这类消息。 (3)通告消息 由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现。从CCmdTarget派生的类,都可以接收到这类消息。 2、命令消息的路由 3、菜单的结构 4、命令更新 菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,谁捕获CN_UPDATE_COMMAND_UI消息,MFC就在其中创建一个CCmdUI对象。我们可以通过手工或利用ClassWizard在消息映射中添加ON_UPDATE_COMMAND_UI宏来捕获CN_UPDATE_COMMAND_UI消息。 在后台所做的工作是:操作系统发出WM_INITMENUPOPUP消息,然后由MFC的基类如CFrameWnd接管。它创建一个CCmdUI对象,并与第一个菜单项相关联,调用对象的一个成员函数DoUpdate()。这个函数发出CN_UPDATE_COMMAND_UI消息,这条消息带有指向CCmdUI对象的指针。同一个CCmdUI对象就设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。 更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。 第七章对话框 1、对话框控件访问七种方式 (1)GetDlgItem()->Get(Set)WindowText() (2)GetDlgItemText()/SetDlgItemText() (3)GetDlgItemInt()/SetDlgItemInt() (4)将控件和整型变量相关联 (5)将控件和控件变量相关联 (6)SendMessage() (7)SendDlgItemMessage() 2、Z-order 窗口的Z次序表明了重叠窗口堆中窗口的位置,这个窗口堆是按一个假想的轴定位的,这个轴就是从屏幕向外伸展的Z轴。Z次序最上面的窗口覆盖所有其它的窗口,Z次序最底层的窗口被所有其它的窗口覆盖。应用程序设置窗口在Z次序中的位置是通过把它放在一个给定窗口的后面,或是放在窗口堆的顶部或底部。 Windows系统管理三个独立的Z次序——一个用于顶层窗口、一个用于兄弟窗口,还有一个是用于最顶层窗口。最顶层窗口覆盖所有其它非最顶层窗口,而不管它是不是活动窗口或是前台窗口。应用程序通过设置WS_EX_TOPMOST风格创建最顶层窗口。 一般情况下,Windows系统把刚刚创建的窗口放在Z次序的顶部,用户可通过激活另外一个窗口来改变Z次序;Windows系统总是把活动的窗口放在Z次序的顶部,应用程序可用函数BringWindowToTop把一个窗口放置到Z次序的顶部。函数SetWindowPos和DeferWindowPos用来重排Z次序。 3、窗口 (1)兄弟窗口 共享同一个父窗口的多个子窗口叫兄弟窗口。 (2)活动窗口 活动窗口是应用程序的顶层窗口,也就是当前使用的窗口。只有一个顶层窗口可以是活动窗口,如果用户使用的是一个子窗口,Windows系统就激活与这个子窗口相应的顶层窗口。任何时候系统中只能有一个顶层窗口是活动的。用户通过单击窗口(或其中的一个子窗口)、使用ALT+TAB或ALT+ESC组合键来激活一个顶层窗口,应用程序则调用函数SetActiveWindow来激活一个顶层窗口。 (3)前台窗口和后台窗口 在Windows系统中,每一个进程可运行多个线程,每个线程都能创建窗口。创建正在使用窗口的线程称之为前台线程,这个窗口就称之为前台窗口。所有其它的线程都是后台线程,由后台线程所创建的窗口叫后台窗口。用户通过单击一个窗口、使用ALT+TAB或ALT+ESC组合键来设置前台窗口,应用程序则用函数SetForegroundWindow设置前台窗口。如果新的前台窗口是一个顶层窗口,那么Windows系统就激活它,换句话说,Windows系统激活相应的顶层窗口。 第十章 在窗口中贴图 1、创建位图 CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP1); 2、创建兼容 DCCDC dcCompatible; dcCompatible.CreateCompatibleDC(pDC); 3、将位图选到兼容DC中 dcCompatible.SelectObject(&bitmap); 4、将兼容DC中的位图贴到当前DC中 pDC->BitBlt(rect.left,rect.top,rect.Width(), rect.Height( ),&dcCompatible,0,0,SRCCOPY); 第十一章 Lesson11 图形的保存和重绘 1、在OnLButtonUp函数中:①CPtrArray m_ptrArray; ②CGraph graph(…); ③m_ptrArray.Add(&graph) 如何解决这个问题呢? 2、在OnLButtonUp函数中 ①CPtrArray m_ptrArray; ②CGraph *pGraph; ③pGraph=new CGraph(…); ④m_ptrArray.Add(pGraph); 3、坐标空间 (1)Microsoft Windows下的程序运用坐标空间和转换来对图形输出进行缩放、旋转、平移、斜切和反射。 (2)一个坐标空间是一个平面的空间,通过使用两个相互垂直并且长度相等的轴来定位二维对象。 (3)Win32应用程序设计接口(API)使用四种坐标空间:世界坐标系空间、页面空间、设备空间、和物理设备空间。应用程序运用世界坐标系空间对图形输出进行旋转、斜切或者反射。 (4)Win32 API把世界坐标系空间和页面空间称为逻辑空间;最后一种坐标空间(即物理设备空间)通常指应用程序窗口的客户区;但是它也包括整个桌面、完整的窗口(包括框架、标题栏和菜单栏)或打印机的一页或绘图仪的一页纸。物理设备的尺寸随显示器、打印机或绘图仪所设置的尺寸而变化。 4、转换 (1)如要在物理设备上绘制输出,Windows把一个矩形区域从一个坐标空间拷贝到(或映射到)另一个坐标空间,直至最终完整的输出呈现在物理设备上(通常是屏幕或打印机) 。 (2)如果该应用程序调用了SetWorldTransform函数,那么映射就从应用程序的世界坐标系空间开始;否则,映射在页面空间中进行。在Windows把矩形区域的每一点从一个空间拷贝到另一个空间时,它采用了一种被称作转换的算法,转换是把对象从一个坐标空间拷贝到另一个坐标空间时改变(或转变)这一对象的大小、方位、和形态,尽管转换把对象看成一个整体,但它也作用于对象中的每一点或每条线。 (3)下图是运用SetWorldTransform函数而进行的一个典型转换。 5、页面空间到设备空间的转换 (1)页面空间到设备空间的转换是原Windows接口的一部分。这种转换确定与一特定设备描述表相关的所有图形输出的映射方式。 (2)所谓映射方式是指确定用于绘图操作的单位大小的一种量度转换。映射方式是一种影响几乎任何客户区绘图的设备环境属性。另外还有四种设备环境属性:窗口原点、视口原点、窗口范围和视口范围,这四种属性与映射方式密切相关。 (3)页面空间到设备空间的转换所用的是两个矩形的宽与高的比率,其中页面空间中的矩形被称为窗口,设备空间中的矩形被称为视口,Windows把窗口原点映射到视口原点,把窗口范围映射到视口范围,就完成了这种转换,如下图所示: 6、设备空间到物理空间的转换 (1)设备空间到物理空间的转换有几个独特之处:它只限于平移,并由Windows的窗口管理部分控制,这种转换的唯一用途是确保设备空间的原点被映射到物理设备上的适当点上。没有函数能设置这种转换,也没有函数可以获取有关数据。 7、默认转换 (1)一旦应用程序建立了设备描述表,并立即开始调用GDI绘图或输出函数,则运用默认页面空间到设备空间的转换和设备空间到客户区的转换(在应用程序调用SetWorldTransform函数之前,不会出现世界坐标空间到页面空间的转换)。 (2)默认页面空间到设备空间的转换结果是一对一的映射;即页面空间上给出的一点映射到设备空间的一个点。正如前文讲到的,这种转换没有以矩阵指定,而是通过把视口宽除以窗口宽,把视口高除以窗口高而得出的。在默认的情况下,视口尺寸为1x1个象素,窗口尺寸为1x1页单位。 (3) 设备空间到物理设备(客户区、桌面或打印机)的转换结果总是一对一的;即设备空间的一个单位总是与客户区、桌面、或打印机上的一个单位相对应。这一转换的唯一用途是平移。无论窗口移到桌面的什么位置,它永远确保输出能够正确无误地出现在窗口上。 (4)默认转换的一个独特之处是设备空间和应用程序窗口的y轴方向。在默认的状态下,y轴正向朝下,负y方向朝上。 8、逻辑坐标和设备坐标 (1)几乎在所有的GDI函数中使用的坐标值都是采用的逻辑单位。Windows必须将逻辑单位转换为“设备单位”,即像素。这种转换是由映射方式、窗口和视口的原点以及窗口和视口的范围所控制的。 (2)Windows对所有的消息(如WM_SIZE、WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP),所有的非GDI函数和一些GDI函数(例如GetDeviceCaps函数),永远使用设备坐标。 (3)“窗口”是基于逻辑坐标的,逻辑坐标可以是象素、毫米、英寸等单位;“视口”是基于设备坐标(象素)的。通常,视口和客户区是相同的。 (4)缺省的映射模式为MM_TEXT。在这种映射模式下,逻辑单位和设备单位相同。 9、逻辑坐标和设备坐标的相互转换 (1)窗口(逻辑)坐标转换为视口(设备)坐标的两个公式: xViewport=(xWindow-xWinOrg)* +xViewOrg yViewport=(yWindow-yWinOrg)* +yViewOrg (2)视口(设备)坐标转换为窗口(逻辑)坐标的两个公式: xWindow=(xViewPort-xViewOrg)* +xWinOrg yWindow=(yViewPort-yViewOrg)* +yWinOrg 10、在MM_TEXT映射方式下逻辑坐标和设备坐标的相互转换 (1)窗口(逻辑)坐标转换为视口(设备)坐标的两个公式: xViewport = xWindow-xWinOrg+xViewOrg yViewport = yWindow-yWinOrg+yViewOrg (2)视口(设备)坐标转换为窗口(逻辑)坐标的两个公式: xWindow = xViewport-xViewOrg+xWinOrg yWindow = yViewport-yViewOrg+yWinOrg 11、视口和窗口原点的改变 (1)CDC中提供了两个成员函数函数SetViewportOrg和SetWindowOrg,用来改变视口和窗口的原点。 (2)如果将视口原点设置为(xViewOrg,yViewOrg),则逻辑点(0,0)就会被映射为设备点(xViewOrg,yViewOrg)。如果将窗口原点改变为(xWinOrg,yWinOrg),则逻辑点(xWinOrg,yWinOrg)将会被映射为设备点(0,0),即左上角。 (3)不管对窗口和视口原点作什么改变,设备点(0,0)始终是客户区的左上角。 12、关于图形错位的说明 当我们在窗口中点击鼠标左键的时候,得到的是设备坐标(680,390),在MM_TEXT的映射模式下,逻辑坐标和设备坐标是相等的,所以我们利用集合类保存的这个点的坐标是以象素为单位,坐标值为(680,390)。在调用OnDraw函数前,在OnPaint函数中调用了OnPrepareDC函数,调整了显示上下文的属性,将视口的原点设置为了(0,-150),这样的话,窗口的原点,也就是逻辑坐标(0,0)将被映射为设备坐标(0,-150),在画线的时候,因为GDI的函数使用的是逻辑坐标,而图形在显示的时候,Windows需要将逻辑坐标转化为设备坐标,因此,原先保存的坐标点(680,390)(在GDI函数中,作为逻辑坐标使用),根据转换公式xViewport = xWindow-xWinOrg+xViewOrg 和yViewport = yWindow-yWinOrg+yViewOrg,得到设备点的x坐标为680-0+0=680,设备点的y坐标为390-0+(-150)=240,于是我们看到图形在原先显示地方的上方出现了。 13、关于解决方法的说明 首先我们在绘制图形之后,在保存坐标点之前,调用OnPrepareDC函数,调整显示上下文的属性,将视口的原点设置为(0,-150),这样的话,窗口的原点,也就是逻辑坐标(0,0)将被映射为设备坐标(0,-150),然后我们调用DPtoLP函数将设备坐标(680,390)转换为逻辑坐标,根据设备坐标转换为逻辑坐标的公式: xWindow = xViewport-xViewOrg+xWinOrg,yWindow = yViewport-yViewOrg+yWinOrg,得到逻辑点的x坐标为680-0+0=680,y坐标为390-(-150)+0=540,将逻辑坐标(680,540)保存起来,在窗口重绘时,会先调用OnPrepareDC函数,调整显示上下文的属性,将视口的原点设置为了(0,-150),然后GDI函数用逻辑坐标点(680,540)绘制图形,被Windows转换为设备坐标点(680,390),和原先显示图形时的设备点是一样的,当然图形就还在原先的地方显示出来。 14、OnPrepareDC会随时根据滚动窗口的位置来调整视口的原点。 15、CreateCompatibleBitmap返回的位图对象只包含相应设备描述表中的位图的位图信息头,不包含颜色表和象素数据块。因此,选入该位图对象的设备描述表不能像选入普通位图对象的设备描述表一样应用,必须在SelectObject函数之后,调用BitBlt将原始设备描述表的颜色表及象素数据块拷贝到兼容设备描述表。 第十二章 文件操作 1、指向常量的指针 2、指针常量 3二进制文件和文本文件 (1)文件是在计算机内存中以二进制表示的数据在外部存储介质上的另一种存放形式。 (2)文件通常分为二进制文件和文本文件。 (3)二进制文件是包含在 ASCII 及扩展 ASCII 字符中编写的数据或程序指令的文件。一般是可执行程序、图形、图象、声音等等文件。 (4)文本文件(也称为ASCII文件):它的每一个字节存放的是可表示为一个字符的ASCII代码的文件。它是以 “行”为基本结构的一种信息组织和存储方式的文件,可用任何文字处理程序阅读的简单文本文件。 4、文本方式和二进制方式 (1)当我们按照文本方式往文件中写入数据时,一旦遇到换行字符(ASCII为10),则会转换为回车-换行(ASCII为13、10)。在读取文件时,一旦遇到回车-换行的组合(即连续的ASCII 13、10),则会转换为换行字符(ASCII为10)。 (2)当我们按照二进制方式往文件中写入数据,则将数据在内存中的存储形式原样输出到文件中。 5、问题 给你一个整数,例如:98341,将这个整数保存到文件中,要求在以记事本程序打开文件时,显示的是98341。如下图所示: 第十三章 文档与串行化 1、String Table中IDR_MAINFRAME字符串资源中各子串的含义 (1)CDocTemplate::windowTitle,主窗口标题栏上的字符串,MDI程序不需要指定,将以IDR_MAINFRAME字符串为默认值。 (2)CDocTemplate::docName,缺省文档的名称。如果没有指定,缺省文档的名称是无标题。 (3)CDocTemplate::fileNewName,文档类型的名称。如果应用程序支持多种类型的文档,此字符串将显示在"File/New"对话框中。如果没有指定,就不能够在"File/New"对话框处理这种文件。 (4)CDocTemplate::filterName,文档类型的描述和一个适用于此类型的通配符过滤器。这个字符串将出现在“File/Open”对话框中的文件类型列表框中。要和CDocTemplate::filterExt一起使用。 (5)CDocTemplate::filterExt,文档的扩展名。如果没有指定,就不能够在“File/Open”对话框中处理这种文档。要和CDocTemplate::filterName一起使用。 (6)CDocTemplate::regFileTypeId,如果你以::RegisterShellFileTypes向系统的注册表注册文件类型,此值会出现在HEY_CLASSES_ROOT之下成为其子项,并仅供Windows内部使用。如果没有指定,这种文件类型就无法注册。 (7)CDocTemplate::regFileTypeName,这也是存储在注册表中的文件类型名称。它会显示于程序中用以访问注册表的对话框内。 2、Document/View结构 (1)在MFC中,文档类负责管理数据,提供保存和加载数据的功能。视类负责数据的显示,以及给用户提供对数据的编辑和修改功能。 (2)MFC给我们提供Document/View结构,将一个应用程序所需要的“数据处理与显示”的函数空壳都设计好了,这些函数都是虚函数,我们可以在派生类中重写这些函数。有关文件读写的操作在CDocument的Serialize函数中进行,有关数据和图形显示的操作在CView的OnDraw函数中进行。我们在其派生类中,只需要去关注Serialize和OnDraw函数就可以了,其它的细节我们不需要去理会,程序就可以良好地运行。 (3)当我们按下“File/Open”,Application Framework会激活文件打开对话框,让你指定文件名,然后自动调用CGraphicDoc::Serialize读取文件。Application Framework还会调用CGraphicView::OnDraw,传递一个显示DC,让你重新绘制窗口内容。 (4)MFC给我们提供Document/View结构,是希望我们将精力放在数据结构的设计和数据显示的操作上,而不要把时间和精力花费在对象与对象之间、模块与模块之间的通信上。 (5)一个文档对象可以和多个视类对象相关联,而一个视类对象只能和一个文档对象相关联。 第十五章 多线程与聊天室程序的创建 1、程序、进程和线程--程序和进程 (1)程序是计算机指令的集合,它以文件的形式存储在磁盘上。 (2)进程:通常被定义为一个正在运行的程序的实例,是一个程序在其自身的地址空间中的一次执行活动。 (3)进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。 (4)进程由两个部分组成: 1、操作系统用来管理进程的内核对象。内核对象也是系统用来存放关于进程的统计信息的地方。 2、地址空间。它包含所有可执行模块或DLL模块的代码和数据。它还包含动态内存分配的空间。如线程堆栈和堆分配空间。 2、程序、进程和线程--进程 (1)进程是不活泼的。进程从来不执行任何东西,它只是线程的容器。若要使进程完成某项操作,它必须拥有一个在它的环境中运行的线程,此线程负责执行包含在进程的地址空间中的代码。 (2)单个进程可能包含若干个线程,这些线程都“同时” 执行进程地址空间中的代码。 (3)每个进程至少拥有一个线程,来执行进程的地址空间中的代码。当创建一个进程时,操作系统会自动创建这个进程的第一个线程,称为主线程。此后,该线程可以创建其他的线程。 4、程序、进程和线程--进程地址空间 (1)系统赋予每个进程独立的虚拟地址空间。对于32位进程来说,这个地址空间是4GB。 (2)每个进程有它自己的私有地址空间。进程A可能有一个存放在它的地址空间中的数据结构,地址是0x12345678,而进程B则有一个完全不同的数据结构存放在它的地址空间中,地址是0x12345678。当进程A中运行的线程访问地址为0x12345678的内存时,这些线程访问的是进程A的数据结构。当进程B中运行的线程访问地址为0x12345678的内存时,这些线程访问的是进程B的数据结构。进程A中运行的线程不能访问进程B的地址空间中的数据结构,反之亦然。 (3)4GB是虚拟的地址空间,只是内存地址的一个范围。在你能成功地访问数据而不会出现非法访问之前,必须赋予物理存储器,或者将物理存储器映射到各个部分的地址空间。 (4)4GB虚拟地址空间中,2GB是内核方式分区,供内核代码、设备驱动程序、设备I/O高速缓冲、非页面内存池的分配和进程页面表等使用,而用户方式分区使用的地址空间约为2GB,这个分区是进程的私有地址空间所在的地方。一个进程不能读取、写入、或者以任何方式访问驻留在该分区中的另一个进程的数据。对于所有应用程序来说,该分区是维护进程的大部分数据的地方。 5、程序、进程和线程--线程 (1)线程由两个部分组成: 1、线程的内核对象,操作系统用它来对线程实施管理。内核对象也是系统用来存放线程统计信息的地方。 2、线程堆栈,它用于维护线程在执行代码时需要的所有参数和局部变量。 (2)当创建线程时,系统创建一个线程内核对象。该线程内核对象不是线程本身,而是操作系统用来管理线程的较小的数据结构。可以将线程内核对象视为由关于线程的统计信息组成的一个小型数据结构。 (3)线程总是在某个进程环境中创建。系统从进程的地址空间中分配内存,供线程的堆栈使用。新线程运行的进程环境与创建线程的环境相同。因此,新线程可以访问进程的内核对象的所有句柄、进程中的所有内存和在这个相同的进程中的所有其他线程的堆栈。这使得单个进程中的多个线程确实能够非常容易地互相通信。 (4)线程只有一个内核对象和一个堆栈,保留的记录很少,因此所需要的内存也很少。 (5)因为线程需要的开销比进程少,因此在编程中经常采用多线程来解决编程问题,而尽量避免创建新的进程。 6、程序、进程和线程--线程运行 (1)操作系统为每一个运行线程安排一定的CPU时间 —— 时间片。系统通过一种循环的方式为线程提供时间片,线程在自己的时间内运行,因时间片相当短,因此,给用户的感觉,就好像线程是同时运行的一样。 (2)如果计算机拥有多个CPU,线程就能真正意义上同时运行了。 7、单线程程序与多线程程序 8、互斥对象 (1)互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。 (2)互斥对象包含一个使用数量,一个线程ID和一个计数器。 (3)ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。 第十六章 线程同步与异步套接字编程 1、事件对象 (1)事件对象也属于内核对象,包含一个使用计数,一个用于指明该事件是一个自动重置的事件还是一个人工重置的事件的布尔值,另一个用于指明该事件处于已通知状态还是未通知状态的布尔值。 (2)有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程。 2、关键代码段 (1)关键代码段(临界区)工作在用户方式下。 (2)关键代码段(临界区)是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权。 3、线程死锁 (1)哲学家进餐的问题 (2)线程1拥有了临界区对象A,等待临界区对象B的拥有权,线程2拥有了临界区对象B,等待临界区对象A的拥有权,就造成了死锁。 4、互斥对象、事件对象与关键代码段的比较 (1)互斥对象和事件对象属于内核对象,利用内核对象进行线程同步,速度较慢,但利用互斥对象和事件对象这样的内核对象,可以在多个进程中的各个线程间进行同步。 (2)关键代码段是工作在用户方式下,同步速度较快,但在使用关键代码段时,很容易进入死锁状态,因为在等待进入关键代码段时无法设定超时值。 推荐书目:《 Windows核心编程》机械工业出版社 5、基于消息的异步套接字 (1)Windows套接字在两种模式下执行I/O操作,阻塞和非阻塞。在阻塞模式下,在I/O操作完成前,执行操作的Winsock函数会一直等待下去,不会立即返回程序(将控制权交还给程序)。而在非阻塞模式下,Winsock函数无论如何都会立即返回。 (2)Windows Sockets为了支持Windows消息驱动机制,使应用程序开发者能够方便地处理网络通信,它对网络事件采用了基于消息的异步存取策略。 (3)Windows Sockets的异步选择函数WSAAsyncSelect()提供了消息机制的网络事件选择,当使用它登记的网络事件发生时,Windows应用程序相应的窗口函数将收到一个消息,消息中指示了发生的网络事件,以及与事件相关的一些信息。 6、相关函数说明 int WSAEnumProtocols( LPINT lpiProtocols, LPWSAPROTOCOL_INFO lpProtocolBuffer, ILPDWORD lpdwBufferLength ); (1)Win32平台支持多种不同的网络 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 ,采用Winsock2,就可以编写可直接使用任何一种协议的网络应用程序了。通过WSAEnumProtocols函数可以获得系统中安装的网络协议的相关信息。 (2)lpiProtocols,一个以NULL结尾的协议标识号数组。这个参数是可选的,如果lpiProtocols为NULL,则返回所有可用协议的信息,否则,只返回数组中列出的协议信息。 (3)lpProtocolBuffer,[out],一个用WSAPROTOCOL_INFO结构体填充的缓冲区。 WSAPROTOCOL_INFO结构体用来存放或得到一个指定协议的完整信息。 (4)lpdwBufferLength,[in, out],在输入时,指定传递给WSAEnumProtocols()函数的lpProtocolBuffer缓冲区的长度;在输出时,存有获取所有请求信息需传递给WSAEnumProtocols ()函数的最小缓冲区长度。这个函数不能重复调用,传入的缓冲区必须足够大以便能存放所有的元素。这个规定降低了该函数的复杂度,并且由于一个 机器上装载的协议数目往往是很少的,所以并不会产生问题。 SOCKET WSASocket( int af, int type, int protocol, LPWSAPROTOCOL_INFO lpProtocolInfo, GROUP g, DWORD dwFlags ); (1)前三个参数和socket()函数的前三个参数含义一样。 (2)lpProtocolInfo,一个指向WSAPROTOCOL_INFO结构体的指针,该结构定义了所创建的套接字的特性。如果lpProtocolInfo为NULL,则WinSock2 DLL使用前三个参数来决定使用哪一个服务提供者,它选择能够支持规定的地址族、套接字类型和协议值的第一个传输提供者。如果lpProtocolInfo不为NULL,则套接字绑定到与指定的结构WSAPROTOCOL_INFO相关的提供者。 (3)g,保留的。 (4)dwFlags,套接字属性的描述。 int WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct sockaddr FAR *lpFrom, LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ); (1)s,标识套接字的描述符。 (2)lpBuffers,[in, out],一个指向WSABUF结构体的指针。每一个WSABUF结构体包含一个缓冲区的指针和缓冲区的长度。 (3)dwBufferCount, lpBuffers数组中WSABUF结构体的数目。 (4)lpNumberOfBytesRecvd,[out],如果接收操作立即完成,则为一个指向本次调用所接收的字节数的指针。 (5)lpFlags,[in, out],一个指向标志位的指针。 (6)lpFrom,[out],可选指针,指向重叠操作完成后存放源地址的缓冲区。 (7)lpFromlen,[in, out],指向from缓冲区大小的指针,仅当指定了lpFrom才需要。 (8)lpOverlapped,一个指向WSAOVERLAPPED结构体的指针(对于非重叠套接字则忽略)。 (9)lpCompletionRoutine,一个指向接收操作完成时调用的完成例程的指针(对于非重叠套接字则忽略)。 int WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, const struct sockaddr FAR *lpTo, int iToLen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ); (1)s,标识一个套接字(可能已连接)的描述符。 (2)lpBuffers,一个指向WSABUF结构体的指针。每一个WSABUF结构体包含一个缓冲区的指针和缓冲区的长度。 (3)dwBufferCount, lpBuffers数组中WSABUF结构体的数目。 (4)lpNumberOfBytesSent,[out],如果发送操作立即完成,则为一个指向本次调用所发送的字节数的指针。 (5)dwFlags,指示影响操作行为的标志位。 (6)lpTo,可选指针,指向目标套接字的地址。 (7)iToLen,lpTo中地址的长度。 (8)lpOverlapped,一个指向WSAOVERLAPPED结构的指针(对于非重叠套接字则忽略)。 (9)lpCompletionRoutine,一个指向接收操作完成时调用的完成例程的指针(对于非重叠套接字则忽略)。 第十七章 进程间通信 1、进程间通信的四种方式 (1)剪贴板 (2)匿名管道 (3)命名管道 (4)邮槽 2、命名管道 (1)命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信。 (2)命名管道充分利用了Windows NT和Windows 2000内建的安全机制。 (3)将命名管道作为一种网络编程 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 时,它实际上建立了一个客户机/服务器通信体系,并在其中可靠地传输数据。 (4)命名管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系统(Named Pipe File System,NPFS)”接口,因此,客户机和服务器可利用标准的Win32文件系统函数(例如:ReadFile和WriteFile)来进行数据的收发。 (5)命名管道服务器和客户机的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。而客户机只能同一个现成的命名管道服务器建立连接。 (6)命名管道服务器只能在Windows NT或Windows 2000上创建,所以,我们无法在两台Windows 95或Windows 98计算机之间利用管道进行通信。不过,客户机可以是Windows 95或Windows 98计算机,与Windows NT或Windows 2000计算机进行连接通信。 (7)命名管道提供了两种基本通信模式:字节模式和消息模式。在字节模式中,数据以一个连续的字节流的形式,在客户机和服务器之间流动。而在消息模式中,客户机和服务器则通过一系列不连续的数据单位,进行数据的收发,每次在管道上发出了一条消息后,它必须作为一条完整的消息读入。 3、邮槽 (1)邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输。 (2)邮槽是一种单向通信机制,创建邮槽的服务器进程读取数据,打开邮槽的客户机进程写入数据。 (3)为保证邮槽在各种Windows平台下都能够正常工作,我们传输消息的时候,应将消息的长度限制在424字节以下。 第十八章 ActiveX控件 1、容器和服务器程序 (1)容器应用程序是可以嵌入或链接对象的应用程序。Word就是容器应用程序。 (2)服务器应用程序是创建对象并且当对象被双击时,可以被启动的应用程序。Excel就是服务器应用程序。 2、ActiveX控件的四种属性 (1)Stock:为每个控件提供的标准属性,如字体或颜色。 (2)Ambient:围绕控件的环境属性——已被置入容器的属性。这些属性不能被更改,但控件可以使用它们调整自己的属性。 (3)Extended:这些是由容器处理的属性,一般包括大小和在屏幕上的位置。 (4)Custom:由控件开发者添加的属性。 第十九章 动态链接库 1、动态链接库 (1)自从微软推出第一个版本的Windows操作系统以来,动态链接库(DLL)一直是Windows操作系统的基础。 (2)动态链接库通常都不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其它DLL调用来完成某项工作的函数。只有在其它模块调用动态链接库中的函数时,它才发挥作用。 (3)Windows API中的所有函数都包含在DLL中。其中有3个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。 2、静态库和动态库 (1)静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件(.EXE文件)。 (2)在使用动态库的时候,往往提供两个文件:一个引入库和一个DLL。引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL,访问DLL中导出的函数。 3、使用动态链接库的好处 (1)可以采用多种编程语言来编写。 (2)增强产品的功能。 (3)提供二次开发的平台。 (4)简化项目管理。 (5)可以节省磁盘空间和内存。 (6)有助于资源的共享。 (7)有助于实现应用程序的本地化。 4、动态链接库被多个进程访问 5、动态链接库加载的两种方式 (1)隐式链接 (2)显示加载 第二十章 HOOK和数据库访问 1、Windows的消息机制 2、动态链接库被多个进程访问 3、数据库访问技术 (1)ODBC(Open Datab
本文档为【孙鑫C++教程(全20讲)PPT讲义】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_432485
暂无简介~
格式:doc
大小:192KB
软件:Word
页数:16
分类:互联网
上传时间:2011-08-14
浏览量:44