| 网站首页 | 文章中心 | 电子书下载 | 矢量图库 | 视频教程 | 素材下载 | 程序代码下载 | JS代码 | 论坛 | 
常用软件类:
|杀毒安全 |联络聊天 |网络软件 |多媒体类 |系统工具 |图形图像 |系统工具 |应用软件 |行业软件
开发设计类:
|动画制作 |图像处理 |3D设计 |操作系统 |站长学院 |网络相关 |WEB设计 |数据库类 |程序开发
windows程序的运行原理以及VC++的实现过程
作者:佚名    文章来源:网络    点击数:    更新时间:2006-11-19
 

操作系统以消息机制把输入设备的变化传递给我们的应用程序,操作系统所扮演的角色是神经末梢

        APP

系统调用API 

         OS

 输出       输入

 HARDWARE


操作系统之所以成为操作系统是因为它能够控制硬件的设备,能够控制声卡发出声音,能够控制显卡画一个窗口,但它是如何实现这些功能就不是我们所关心的了,这些是写汇编的人员所要做的事情。操作系统又能够从输入设备获得信息,譬如说,操作系统能够感受到鼠标的移动,并且还能知道鼠标移动后的位置。再比如说操作系统能感受到键盘的按下,并且知道按下的是哪个键,这些都表明操作系统和输入输出设备有一个关系,至于操作系统怎样去控制输入设备以及怎样把输入设备的信息拿到手的,这些我们都不用关心,这些是写操作系统的人或者写驱动程序的人所要干的事。由于应用程序是运行在操作系统上的,我们所关心的是应用程序和操作系统之间有什么样的关系。就仿佛是机器人能够走路,但是机器人要走几步,向哪个方向走,这些是机器人不关心的,它只是说我有走路的能力,至于怎么走需要主人对它发号施令了,如果我们要求机器人向南走5步,机器人才能完成行走的操作。同样对于操作系统来说,操作系统能够控制声卡发出声音,但是具体发出什么样的声音,是美妙的还是悲伤的就由应用程序来告诉操作系统的,应用程序怎样告诉操作系统呢,我们在编写C语言的时候通过调用函数来让操作系统干某事,操作系统能够执行各种各样的功能,它把这些功能都以函数的形式提供给应用程序,应用程序通过调用这些函数来通知操作系统该干什么事情,操作系统的各种各样的功能都对应相应的函数,这些函数的集合叫做API。如控制机器人的函数集合我们叫robot API,像JAVA里也有操作我们的系统的函数,我们把它叫做JAVA API,这里的API与WINDOWS API是没有关系的。

每个应用程序都有一个队列,叫消息队列,什么叫队列呢?其实就是一个缓冲区(就是定义的一个数组,数组有多大,缓冲区就有多大),然后你可以往里面存数,别人就可以从里面取数。先取的是你最先存入的数。就好象寻呼台的寻呼系统,来了一个寻呼信息,就有寻呼小姐将该信息交给发射机发布出去,如果在一秒钟一次来了很多个寻呼请求,发射机就有可能忙不过来,为了不至于把信息丢失,我们就准备一个很大的缓冲区,有100个格子,来一个寻呼请求就往这个缓冲区里放一个,然后由发射机从里面取,总是先取最先放进去的,一个往里面放,一个从里面取,虽然说可能会有些延迟,但我们保证了寻呼的请求没有丢失,这点也体现在我们的操作系统忙的时候我们执行了关闭窗口的命令,可能窗口当时没有立即关闭,但过了一会还是关闭了窗口,这也是队列的应用,队列就好比食堂里的排队买饭,排在前面的先买到饭,第一个买到饭后就离开,而第二个此时就成了第一个,后面的依次往前移动,这就是队列先进先出的特点。我们这里的消息队列存放的是消息,描述这个消息就要用结构体(MSG),因为一个消息要包含一些辅助说明消息的信息。下面讲解MSG,每一个消息都是跟窗口相关联的(也就是一个消息必须由一个窗口接收),这是因为消息都有目标的,这样消息才能正确的到达目标窗口,且该目标窗口此时应具有焦点,如启动两个记事本程序,当按下键盘的时候,消息只能到达具有焦点的窗口上。第二个参数是标识消息的整数,第三四参数是对消息进行补充说明的,如有键盘消息,你到底按下的是哪个键,这些信息都包含在这两个参数中。第五个参数是发出消息的时间,最后一个参数是鼠标所在的位置。用GO TO Definition查看LPARAM等类型的原型。
讲解句柄,我们学习WINDOWS程序就要接触句柄(HANDLE)了。其实句柄就是一个void*,我们可以用GO TO Definition来查看HANDLE,在WINDOWS里面任何一个WINDOWS实体(如窗口、位图、刷子、菜单等)都要在内存中占一块空间,这块空间就应该有一个地址,为了区别于以前普通变量的地址,我们用HANDLE来标识该WINDOWS实体,HANDLE保存的是该WINDOWS实体的地址,以便后面对该WINDOWS实体进行操作,如以后我们要哪个窗口最大化,我必须告诉操作系统我所要操作的窗口,那么我递给操作系统的是一个句柄。我们看到的HWND、HMENU、HBURSH其实都是HANDLE。
我们编的程序是从消息队列里取消息,消息被取出时是以一个MSG结构体提供给用户的,然后对消息进行处理。在消息处理的时候我们又调用了WINDOWS的API函数,如关闭窗口退出程序,当我们点了关闭按钮就收到了WM_CLOSE,然后我们在这个消息里调用了WINDOWS的API函数去销毁窗口,当操作系统真的把窗口销毁后会又报告一个消息回来等候你的应答-WM_DESTROY,这个时候我们又可以干点什么事,你可以真的退出了应用程序,也可以干点别的事,这个过程像一个封闭的环路,不断的从消息队列里取消息,然后你的代码又根据消息调用API函数去响应,这么一个循环的过程,所以有人形容WINDOWS程序无头无尾。我们编写WINDOWS程序首先要懂C语言,然后我们要知道每个消息具体代表什么含义,你不能收到一个键盘按下消息后当做鼠标移动处理,如别人说脚痛,你不能当头痛处理。最后我们收到某个消息想干某件事时,就要知道哪个API函数能实现该功能。但是API函数有三千多个,我们只要知道20%就够了,因为这20%的函数能干80%的事。

下面我们开始编写WINDOWS程序:
首先我们要产生一个窗口,有了这个窗口用户才能进行一系列操作。
如同生产汽车一样,产生汽车前我们要干一些准备工作,其实生产汽车是很容易的事,难就难在设计汽车,如果设计好了汽车以后就可以成批量的生产了。设计汽车就要指定汽车的颜色、汽车的发动机、底盘、变速箱等。同样产生窗口我们也要先设计,如窗口的背景是什么、窗口的鼠标指针是什么、窗口的图标是什么、窗口的菜单是什么。设计好了后我们才能根据设计图纸下料批量生产了。这里窗口的设计通过一个结构体来完成:WNDCLASS,第一个参数是STYLE,这个参数对应的二进制只有一位为1(十六进制的一位对应二进制的四位)。这有什么好处呢?比如说第一位是最大化按钮,第二位是最小化按钮,第三位是关闭按钮,如果我们希望窗口有最大化和最小化按钮,我们就把第一位和第二位设置为1,而第三位为0,如果我们又想有关闭按钮了,我们就把STYLE参数与一个代表关闭按钮的整数相或就可以了。

STYLE里有两个参数是CS_HREDRAW和CS_VREDRAW,当我们把窗口的大小发生改变时(最小化、最大化、覆盖一样),显卡要重新给我们把窗口画一遍(窗口是绘出来的),这时候原来在窗口上画的东西就被冲掉了,如果不这么做的话,我们的窗口的大小无法发生改变,这里我们指定两个参数就是指定当窗口水平和垂直方向发生大小改变时需不需要显卡重新画窗口,画窗口的时候显卡会用你定义的窗口的背景颜色进行重画。这就好比我们每到春节的时候要给汽车重新喷漆一样,如果我们不指定这两个参数就是说我不重新喷漆了,只用水冲一下就可以。以在窗口上画线为例进行演示。
 cbClsExtra 、cbWndExtra 是两个补充说明的参数,是当窗口的参数不够的时候用。

hIcon是图标的句柄,可以通过API函数LoadIcon加载,MAKEINTRESOURCE是把一个整数转成字符串的宏。注意字符串就是一个地址,标识一个字符数组常量的首地址。WORD是一个unsigned short, DWORD是一个unsigned long。如果需要使用一个自定义的图标,第一个参数就应该是hInstance,第二个参数是MAKEINTRESOURCE(IDI_ICON1)。在VC中编辑图标,并保存,#include “resource.h“  将script1.rc增加到工程。

hCursor是鼠标指针的句柄。可以通过API函数LoadCursor加载。cursor里的IDC_HAND是定义在win2000的头文件中的,要装win2000 SDK.

hbrBackground是窗口背景刷子的句柄,NULL表示没有刷子。通过API函数GetStockObject得到。注意这里要接触一个近指针和远指针的概念,这些是16位操作系统的产物,是用来标识指针的管理范围的,在32位的操作系统上已经没有意义了,我们可以发现它们都定义成空了。这里GetStockObject的返回值要进行类型转换。(设置一个任意的颜色?)
hInstance是应用程序实例的句柄。我的一个应用程序起动了,应用程序就装在内存中了,成为一个实例(因为应用程序可以启动多个,我们把它们每个应用程序用实例句柄来管理和区分),以后操作系统想控制我的应用程序,我必须把应用程序的句柄传给操作系统。这个应用程序的句柄我们把它叫做实例句柄。我们任何一个窗口都应该属于一个应用程序实例,所以我们在这里要指定应用程序的实例句柄。这个实例句柄是由操作系统分配给我们的。应用程序都有一个入口函数,在DOS里是MAIN函数,在WINDOWS里是WINMAIN函数,我们发现应用程序的实例句柄是操作系统在WINMAIN函数里传给我们的。hPrevInstance是先前的应用程序的实例句柄。通过这个参数我们可以控制一个应用程序只能启动一份。当然我们在这里由于是WIN32的系统无法简单实现只程序启动一份。(WinMain函数是操作系统调用的,所以WinMain的参数是操作系统赋值的。)
lpszMenuName注意菜单不是窗口。用SPY++可以查看。
lpszClassName是窗口类型的名字。如富康988。

 

[1] [2] 下一页


相关文章