1、如果 windows 一直存在下去,窗口这个话题也许是永恒的1. 一切皆窗口在我看来桌面上的一切都是窗口,桌面本身是窗口,开始菜单是窗口,桌面上永远置顶的播放器是个置顶的窗口,工具栏是个子窗口.不仅我这么看,Spy+ 也这么看,如下图:图 1-1 Spy+和桌面一切都是窗口,窗口错落有致,成为界面树上的翩翩叶子,组织成了我们所看到的整个 Windows 系统用户界面。我们首先通过一个普普通通典型的窗口,来分析一下窗口的组成: 图 1-2 普普通通的窗口一个窗口是有很多界面元素的,比如标题栏,菜单栏,状态栏等等。但实际上可以把这些归为两类,一类是客户区,客户区就是整个窗口中间的部分,在图中已经标
2、示出来。客户区是由程序员负责绘制的,程序员可以在上面写个字或者画个圆这样。而另一类当然是非客户区,除了图上客户区以外的地方,标题栏,水平滚动条等等都是非客户区,这一部分的绘制是由操作系统负责的。界面元素是看的见的,还有一些窗口特性我们用上图是无法表示出来的,比如窗口该如何响应用户的输入?比如窗口的鼠标应该是什么样的,是单箭头或者是其他比较炫的鼠标效果?比如客户区的背景色应该是什么样的等等。归纳起来就是两点:(1) 窗口的界面元素分成两类,一类是客户区,另一类是非客户区;(2) 窗口的特性,看得见的,看不见的,七大姑八大姨的,确实很多。一个成功的窗口需要程序员和操作系统默契配合。操作系统作一些通
3、用的,基础的工作,比如绘制一个标题栏,状态栏这样的事情。程序员作一些特定的工作,比如读一个数据文件,然后用图形化的方式显示在窗口客户区内。2. 窗口的创建前面我说了,窗口的特性是很多的。不是一般的多,而是七大姑八大姨般的多。因此窗口的创建,一般的方法,那就麻烦了。程序员需要一个一个指定这些特性,看得见得要指定,看不见的还要指定。不仅如此,每打算创建一个窗口,你就要指定一次,无论这些窗口有多么类似,你还是要不厌其烦地指定下去。有些人怕麻烦,他指定了三五个特性,最终宣布“这真不是人干的活,老子金盆洗手了”,这些人,我们只有哎 有些人不怕麻烦,他会老老实实一遍一遍指定下去,这些人,我们尊敬他们.还有
4、些人怕麻烦,于是他们想出了新的办法,这些人,我们只有崇拜.技术精英们想出的办法是“把共性的东西,抽象出来”。这句话我在下面会慢慢解释。2.1 把共性的东西,抽象出来在 Windows 操作系统里,我们是用窗口句柄(HWND)来操作一个窗口的。HWND就相当于每个窗口的钥匙。Windows 里 CreateWindow 或者 CreateWindowEx 都是创建一个窗口的函数,它们返回 HWND 类型的一个值,以便程序员继续对窗口进行操作。这个值对应的是桌面上一个一个实实在在的窗口,我们看到这些窗口有很多特性是类似的,比如窗口客户区的背景色都是白色的,鼠标的光标形状都是一样的等等。于是技术精英
5、们就把这些共性的东西抽象出来了,抽象成了一个结构,这个结构我们称之为窗口类(windows class)。typedef struct UINT style;WNDPROC lpfnWndProc;int cbClsExtra;int cbWndExtra;HINSTANCE hInstance;HICON hIcon;HCURSOR hCursor;HBRUSH hbrBackground;LPCTSTR lpszMenuName;LPCTSTR lpszClassName; WNDCLASS, *PWNDCLASS;代码 2-1 窗口类结构体 这里面最为重要的是第二个成员窗口过程,如果把窗
6、口比作有生命的物体,那么窗口过程就注入了灵魂。这个我们需要在消息循环一节当中解释。其他的比较常用的成员变量,比如 hIcon 指定了应用程序的图标,hCursor 指定了鼠标的形状,hbrBackground 指定了客户区的背景色,lpszMenuName 指定了窗口类的菜单,lpszClassName 指定了窗口类的名字等等。这些特性是每个窗口都具备的共性,因此全部抽象成了窗口类的成员变量。窗口类和窗口的关系,在面向对象里我们可以把它们比作类和对象的关系。但是更贴切的比喻,我认为是模具和成品的关系。窗口类好比一个个模具,想要做按钮,我们就拿一个按钮的模具,倒成一个模子,然后再在上面做一些慢工
7、细活,成为一个按钮。想做组合框,我们就拿一个组合框的模具,想做编辑框,我们就拿一个编辑框的模具,想做一个花瓶,我们就拿. 问题来了,操作系统没有提供花瓶的模具,不过也有办法,操作系统会告诉我们,你把模具的特性告诉我,我会给你制作一个花瓶的模具。 有 Win32 经验的程序员都知道,每次创建窗口之前,我们都会调用一个函数RegisterClass,注册窗口类。注册窗口类实际上就是告诉操作系统模具的特性和要求,让操作系统为我们制作一个模具。因此一个标准的窗口创建过程,如下所示: LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wPa
8、ram, LPARAM lParam);int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)static TCHAR szAppName = TEXT(“HelloWin“);HWND hwnd;WNDCLASS wndclass;/ 注册窗口wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWnd
9、Extra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName; if(!RegisterClass(/ 创建窗口并显示窗口hwnd = Cre
10、ateWindow(szAppName,TEXT(“The Hello Program“), WS_OVERLAPPEDWINDOW , CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);ShowWindow(hwnd,nCmdShow);UpdateWindow(hwnd);/ .return 0;LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)return DefWin
11、dowProc(hwnd,message,wParam,lParam);代码 2-2 标准的窗口创建过程但是这个还远没有结束。按照毛主席老人家的话,这是“万里长征第一步”。如果运行一下这个程序,窗口犹如昙花一现,一闪而过。这其中的原因,我们还是要留在后面介绍。操作系统之所以能够找到指定的模具来制作窗口,主要是靠窗口类的类名(lpszClassName)。我们可以看到 CreateWindow 的第一个参数便是窗口类的类名,操作系统根据这个类名去寻找相应的系统窗口类或者是应用程序注册的窗口类。2.2 唏嘘感慨几句说到这里,真的是要唏嘘感慨几句。相信绝大多数程序员都有这个认识,就是 C 语言是过程
12、语言,而 C+是面向对象的语言。但是 Win32 掷地有声地告诉我们,语言只是载体,用 C 语言同样可以写出面向对象思想的程序。窗口类和窗口即是明证。此外,如果你是从 Win32,MFC, WinForm 到现在最为流行的 WPF 一路走来,同样也会感到微软的技术进步带给程序员的便利。我自认为对 Win32 还算是熟悉,但是让我创建一个窗口的时候,我往往也是要从 MSDN 里找出一段代码 Copy 上去,或者是直接利用向导创建一个 HelloWorld。在 MFC 里,事情并没有得到好转,虽然我们可以利用向导直接得到一个单文档,多文档或者是基于对话框的应用程序,但是我们连应用程序的入口(Win
13、Main)都找不到了。相信每个 MFC 程序员,在早期的 MFC 学习当中都是痛苦不堪的。在 WinForm 中创建窗口,真正的变的简单。多简单?一句话。只需要一句话,一个窗口就创建出来了。static void Main()Application.Run(new HelloWorldWinForm();代码 2-3 WinForm 里创建窗口按理说,WinForm 已经简单到了极致。 WPF 没有理由再简单,但他还是做到了。因为在 WPF 里甚至不需要写任何程序,只需要在指定应用程序启动的时候启动那个窗口文件即可。代码 2-4 WPF 里创建窗口所以真的是不从历史这样一步一步走到当代,就看不
14、出进步。这几个例子的源码我都写好了,放在附件文件夹下,各位的机器有 VC6.0 和 VS2008 的环境的话即可运行。3. 窗口的类型注册完窗口类,紧接着就是创建窗口,过去在创建窗口的时候,我很拿不准的就是指定样式(CreateWindow 的第三个参数)。因为窗口的样式确实太多,我简单统计了一下窗口样式有 18 种,也许有人觉得不算多,但是这 18 种还是可以任意组合的。这样就真是无穷无尽了。但是好好的归纳和总结,事情是可以变的简单的。真正的窗口类型只有 5 种,而真正常用的只有 3 种。下面,我需要分别介绍一下这 5 种窗口类型,实际上搞清楚前 3种,大体也就 OK 了。3.1 重叠式窗口
15、( Overlapped Windows)一个重叠式窗口往往是应用程序的主窗口,它有标题栏,边框,客户区,图标,最小化,最大化按钮等等。创建窗口的时候,如果你指定 WS_OVERLAPPED 或者WS_OVERLAPPEDWINDOW 这样的样式,就可以创建一个重叠式窗口。相信一定会有人问,WS_OVERLAPPED 和 WS_OVERLAPPEDWINDOW 有什么区别?我们只要看看两个宏的定义,便可见分晓(窗口样式的宏都定义在 WinUser.h 这个文件当中)。/ 摘自 WinUser.h 文件#define WS_OVERLAPPED 0x00000000L#define WS_POP
16、UP 0x80000000L#define WS_CHILD 0x40000000L#define WS_MINIMIZE 0x20000000L#define WS_VISIBLE 0x10000000L#define WS_DISABLED 0x08000000L#define WS_CLIPSIBLINGS 0x04000000L#define WS_CLIPCHILDREN 0x02000000L#define WS_MAXIMIZE 0x01000000L.#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | “WS_CAPTION | “WS_S
17、YSMENU | “WS_THICKFRAME | “WS_MINIMIZEBOX | “WS_MAXIMIZEBOX)代码 3-1 窗口样式从定义上也能看出 WS_OVERLAPPEDWINDOW 是 WS_OVERLAPPED 和其他样式的一种组合。写到这里,我们不得不岔开一下话题,谈一谈关于程序员“小气和高明”的问题。小气和高明的程序员细心的读者可能已经注意到了,窗口样式的宏定义并不是按照我们常规的方式来定义,比如 WS_OVERLAPPED 用 1 来表示,WS_POPUP 用 2 来表示,以此类推实际上宏定义全部采用的是 16 进制的表示方法,而且在表示也是有讲究的,基本上用的是 1
18、(20),2(21), 4(22), 8(23)这样的数值表示。实际上不仅仅是窗口样式,绝大部分类似窗口样式这种可以组合表示的宏都采用的这种手法。也许还是有相当的新手,不知道这样表示的妙用,我们把他们全部用二进制的表示方法,秘密昭然若揭。表格 3-1 窗口样式的二进制和十六进制表示样式 数值表示(32 位整型数字,2 进制表示) 数值(16 进制)WS_OVERLAPPED 0 0 0 0 0 0 0 0 0x00000000LWS_POPUP 1 0 0 0 0 0 0 0 0x80000000LWS_CHILD 0 1 0 0 0 0 0 0 0x40000000LWS_MINIMIZE
19、0 0 1 0 0 0 0 0 0x20000000LWS_VISIBLE 0 0 0 1 0 0 0 0 0x10000000L. . .WS_POPUP | WS_CHILD1 1 0 0 0 0 0 0 察觉出来没有,程序员没有用一个整型(32 位)来表示一个特定的窗口样式,而是用1 位来表示窗口样式。小气吗?真小气,早期的程序员就像守财奴一样非常吝啬地使用自己的内存。一个 32 位的整型,程序员用其中 1 位来表示一个特定的样式。如果其中有几位都是 1 呢?那么它表示的就是一个样式的组合。因此,我们可以看到WS_OVERLAPPEDWINDOW 可以由几个窗口样式进行或运算组合而成。这
20、样的做法也是一个极其高明的做法。需要组合的这种参数,往往会设计成这样。它们通过或运算组合而成。判断该参数里是否有某一个特定的样式,则用与运算来检验。将样式从某一个组合里剔除出来,则采用与非运算。如下所示:DWORD style = WS_POPUP; 数值为 0x80000000style = style | WS_MINIMIZE; /样式组合成了 WS_POPUP | WS_MINIMIZE 数值为 0x80000000 | 0x20000000为 0xa0000000bool res = style / 判断 style 里是否有 WS_MINIMIZE 返回为真 res = style
21、 /判断 style 里是否有 WS_CHILD 返回为假 style = style /从样式里去掉了 WS_MINIMIZE 样式 数值为 0x80000000代码 3-2 窗口样式运算3.2 弹出式窗口( Popup Window)最典型的弹出式窗口是对话框。弹出式窗口和重叠式窗口还是相当类似的。弹出式窗口和重叠式窗口到底有什么区别呢?一般来说一个应用程序的主窗口是重叠式窗口,而弹出式窗口多用于对话框,消息框这样的窗口。当然还有细节上的问题。(1) WS_OVERLAPPED 样式创建的窗口是含有标题栏的,而 WS_POPUP 样式创建的窗口是不含标题栏的,如果需要创建一个带标题栏的 W
22、S_POPUP 样式的窗口,那么需要运用 WS_POPUP | WS_CAPTION 样式组合;(2) 在创建 WS_OVERLAPPED 样式窗口的时候,CreateWindow 或者CreateWindowEx 函数当中 x,y,nWidth, nHeight 四个参数都可以取CW_USEDEFAULT 默认值,系统会选择一个合适的值。但是创建WS_POPUP 样式的窗口,CW_USEDEFAULT 对这四个参数是无效的,如果程序员一意孤行非要传 CW_USEDEFAULT 值,系统会默认认为这几个参数为 0,那么这个时候整个窗口的大小就为 0。这个时候往往会给程序员造成一种错觉,以为自己
23、的窗口没有创建出来,实际上窗口已经创建出来了,只不过它长宽均为 0 而已。3.3 子窗口( Child Window)类似于按钮这样的窗口,我们称之为子窗口。子窗口的样式为 WS_CHILD,子窗口必须得有一个父窗口。而且子窗口的区域一定限制在父窗口的客户区内。一般一个子窗口默认只有客户区,除非程序员再去显示地为子窗口指定标题栏(WS_CAPTION)或者边框(WS_BORDER)之类的样式。自此,应该说窗口的类型算是基本上介绍完了。无论桌面上的窗口怎么变,有 80%都是在这三种之间变来变去,把弹出窗口加一个标题栏,或者把重叠窗口加上最大最小化按钮啊等等。但确实还有一小撮不属于这三种类型的,但
24、是下面的两种都是属于比较特殊的情况,为了满足各位的好奇心,我们还是把窗口的类型介绍完整。3.4 分层窗口( Layered Window)分层窗口,这样的翻译不知道是否准确。因为这一部分,大家讨论得还是比较少,因此没有什么统一认可的翻译方式。分层窗口是在 Windows2000 之后才出现的。如果大家比较感兴趣可以参考我的另一篇文章分层窗口Windows 进化的中间产物。如果各位体验过 Windows2000 以前的产品,Windows95 或者 Windows98。细心的用户会发现 Windows 为了改进用户体验,在部分细节的地方作了改变,比如鼠标。在Windows2000 以前,鼠标只是
25、一个平面的箭头。而在 Windows2000 和 Windows2000 以后,鼠标下面会增加了一层阴影,以强化其视觉深度。这样使得鼠标更有立体感,在大的显示器甚至是多个显示器上更容易找到那个小小的鼠标。 图 3-1 左图是 Windows200 以前的鼠标,右图是 Windows2000 以后的鼠标,增加了阴影再比如置顶窗口的一个时钟,透明地浮动在窗口,为你显示时间。图 3-2 透明时钟 再比如 Office 助手,这样的小玩意。它浮动在窗口的顶层,可能是一个老头,也可能是一个妙龄少女,或者是一个机器人,你问它答。Office 助手已经完全脱离了传统的窗口样式还有.等等这样的特殊效果,都是分
26、层窗口所致。我再重复一遍,这篇文章我们不讨论太多的这种窗口,如果有兴趣我会再写另一篇文章分层窗口Windows 进化的中间产物。3.5 单一处理消息窗口( Message-Only Windows)Message-Only Windows 这个翻译成单一处理消息窗口,不知道是否妥贴。我一般翻译都不喜欢自创,一般会遵循大家普遍认可的翻译方式,但是 Message-Only Windows 也许大家不够关注,于是缺少一个普遍认可的词汇,不得已只有自己创造之。其实 E 文的名称已经足以说明该窗口是个什么咚咚,就是一个看不见,找不着,专门用来处理消息的窗口。当然如果各位感兴趣的话,我会再写另一篇文章如
27、何创建一个Message-Only Windows。4. 消息循环我们已经运行过代码 2-2。事实是窗口昙花一现,一闪而过;原因是我们缺少最必要的一环就是消息循环。我每回在写一个标准的 Windows 程序时候,等到加消息循环的时候,就会有意停顿一下,因为感觉自己就像一个画龙的画师,等待着给龙点睛2。点睛的龙,会一飞冲天;加上消息循环的窗口,则注入了生命。整个消息循环的代码如下,非常简单,三个函数和一个 While 循环搞定。但是要真正地解释清楚,这里面涉及到应用程序和操作系统的关系,还有消息,消息队列以及窗口过程等重要概念。MSG msg;while (GetMessage(Dispatch
28、Message( 代码 4-1 消息循环的代码事实上,我已经说过所有的应用程序都是系统和程序员进行配合完成的。我在阅读MSDN 关于窗口这一部分文档,结合自己的编程经验,脑海里常常呈现出一幅应用程序和操作系统“你来浇水,我施肥”的和谐共建图。但是每回拿起笔,又感觉颇为艰难。一次无意当中随手随手翻翻侯捷大师的深入浅出 MFC(经典书是常翻的),以前没有注意到的一幅图完全抓住了我的眼球。因为正是我脑海中常常浮现的一幅图,虽然这幅图还是有部分瑕疵,但是瑕不掩瑜,老实说我是画不出来的一幅应用程序和操作系统“你来浇水,我施肥”的和谐共建图 图 4-1 windows 程序与操作系统关系(侯捷, 1997
29、)这幅图,如果简单的归纳只能用十二个字来表示“以消息为基础,以事件驱动之”。如果是 E 文,这更为简洁明了 “message based, event driven”。但是这个就好比“五心向天”这样的口诀,光记下来是没用的,因此我们这一节都是围绕着这个图来解释这十二字真言。前面我们已经说过,当我们注册完窗口类(RegisterClass),创建窗口(CreateWindow)和显示窗口(ShowWindow,UpdateWindow )。一个应用程序就进入了消息循环,这个时候窗口所需要做的事情就是两个字“等待”。操作系统说,“您该重绘了”,于是窗口就把自己重新画一遍,操作系统说“您该响应鼠标消
30、息了”,窗口就响应一下鼠标消息。总之“敌不动,我不动,敌一动,我乱动”。人和人之间交流用语言,留便条或者打手机等等。操作系统和应用程序之间,他们用消息来进行这样的通讯。 操作系统说 “您该重绘了”,它会向应用程序发送一个WM_PAINT 消息;操作系统说 “用户按下鼠标左键了” ,它会向应用程序发送一个“WM_LBUTTONDOWN”消息等等。而窗口收到了这些消息,当然也需要处理这些消息,窗口有一个集中处理消息的办公地点,这个办公地点称之为“窗口过程”函数(WndProc)。实际上在注册窗口类的时候,就将一种特定类型的窗口和窗口过程函数绑定在了一起。倘若不记得,不妨回过头再看看窗口的创建一节。
31、窗口过程函数就好象是一个专门处理消息的部门。当然这个小小的部门也不是所有大事小事都能完全处理,有些消息,窗口可以自己处理,但是有些消息,窗口处理不了。处理不了的事情按照常规当然是要及时上报,于是窗口过程函数的实现都是同一个模子。首先上来 switch.case,处理消息 1,消息 2,消息 3处理不了,那么交给操作系统去处理(default return DefWindowProc),DefWindowProc 函数的意思是让操作系统按照默认的方式处理消息。一个一个消息就好比一件一件公文,最终放到窗口过程函数的桌面上等待处理。但是这些公文的到来,也是有不同的途径。第一种途径当然是一种常规途径,
32、就是按照先来后到的顺序,排成队处理。而第二种途径自然是特权途径,这种就好比领导打个电话或者递个条子语重心长地说“小李啊,这个特事要特办啊”。其实我还是蛮痛恨这种“递条子”现象。但是在计算机这档子事里还真是必须要有这种特权现象存在。4.1 两种不同的消息传递途径百姓苦排队型(进队消息)我们现在来具体说说这两种途径。先说第一种途径,消息要一件一件处理,总要安排个地方给消息排队。因此操作系统为窗口安排了两个消息队列,消息来了统统在这两个消息队列里排队。然后应用程序的消息循环取出消息(GetMessage,TranslateMessage 和DispatchMessage),传给窗口过程函数去处理。两
33、个消息队列分别是系统消息队列(System Message Queue)和应用程序消息队列(Application Message Queue)。注意系统消息队列是唯一的,也就是说一个操作系统也就一个系统消息队列,用户点击鼠标,敲击键盘,由相应的鼠标和键盘驱动将这些外部事件转换为鼠标和键盘消息,然后放在系统消息队列里排队。操作系统非常聪明会知道某个鼠标键盘消息属于哪个窗口,然后把相应的消息放到特定窗口应用程序消息队列中。注意我再重复一遍,系统消息队列会把相应的消息放到特定窗口的应用程序消息队列中。换句话说,消息循环不会从系统消息队列里去取消息,只会从特定窗口的应用程序消息队列中取消息。因此侯先
34、生的这幅图出现了一点小小的瑕疵,它应该修改成如下图。 图 4-2 windows 程序与操作系统关系(作者修改)而应用程序消息队列接受的都是该窗口的鼠标和键盘消息或者菜单消息等等。总之属于该窗口的消息都会最终放置在该窗口的应用程序消息队列里,以应用程序的眼光来看,是不需要知道该消息是放在系统消息队列还是应用程序消息队列,应用程序只需要从应用程序消息队列取消息即可。领导递条子型(非进队消息)第二种途径当然要“牛”很多。这种“牛”体现在两点上。第一这些消息从来不排队,直接抵达窗口过程函数。第二点更“牛”,这种消息到达窗口过程就必须得处理,处理不完就一直等待。幸运的是计算机里我们不需要送美女,送金钱
35、,只需要调用SendMessage,这样消息就直接摆放在窗口过程的桌子上,窗口过程不处理都不行。4.2 几个特殊进队的消息按说进队消息已经没什么特殊,他们都是老老实实地遵循先进先出(first in first out)的原则。但是仍然有些消息会特殊。按照常理来想,如果你要搞特殊,大可不排队,走领导递条子型不就得了。但是这些消息特殊,并不是特殊在他们要特权,他们的问题是太过谦让,看到其他消息总是说“您请先”。现在让我们介绍一下,这几个特殊而高尚的信息。他们分别是WM_PAINT,WM_TIMER 和 WM_QUIT 消息。这三个消息总在谦让,他们谦让的程度让人咂舌。消息队列里只要还有一条消息在
36、排队,他们都不会往前,直到消息队列为空,才会交给窗口过程处理。当系统感觉到窗口需要重绘的时候,比如窗口大小,尺寸等发生变化,会向窗口发送WM_PAINT 消息,告知窗口需要重绘。 WM_PAINT 消息不仅会谦让,而且当消息队列里有多个 WM_PAINT 消息,系统会自动合并成一个 WM_PAINT 消息,同时会将每个WM_PAINT 消息的无效矩形合并成一个大的无效矩形。WM_PAINT 之所以这样做,是因为避免窗口过多地重绘造成的系统低效。关于 WM_PAINT 和无效矩形,我想还得再写一篇文章来说明这个问题。WM_TIMER 是设置了计时器之后,系统会按照计时器规定的间隔时间来定时发送W
37、M_TIMER 消息。由于 WM_TIMER 消息是一个具有“先人后己”道德高尚的消息,因此,我们说这种计时器是不太准的,比如定时器设置了每 50 毫秒发送一次 WM_TIMER消息,但是 50 毫秒的时候,消息队列里还有很多其他兄弟消息,于是 WM_TIMER 就忍让了,可能 51 毫秒或者 52 毫秒的时候 WM_TIMER 消息才会放到消息队列当中。当应用程序需要退出的时候,系统会发送 WM_QUIT 消息。WM_QUIT 的谦让精神和前面的兄弟消息也是一样,就无需多言了。WM_QUIT 的特殊之处,在于 GetMessage 一旦得到的是 WM_QUIT 消息,就返回 0,整个消息循环
38、就结束了,Game Over!4.3 一个消息的完整结构其实我前面有埋一个伏笔,那就是操作系统怎么就能如此聪明,知道哪个消息是属于哪个窗口的呢?其实看看消息的结构,就不难知道答案。typedef struct tagMSG HWND hwnd;UINT message;WPARAM wParam;LPARAM lParam;DWORD time;POINT pt; MSG;消息结构体,总共有六个成员变量。第一个就是窗口句柄 hwnd,这个参数就告诉我们是哪个窗口收到消息,操作系统可以根据这个信息将消息放到合适的窗口应用程序消息队列当中;第二个是消息的标识,比如 WM_PAINT 等;第三和第四
39、参数都是用来存储消息的额外信息;第五个参数记录的是消息被放入到消息队列的时间;第六个参数是消息被放入到消息队列时,鼠标所在的位置。 5. 小结写到最后了,还是小结一下。 Windows 里一切都由窗口组成 窗口类是模具,窗口是成品 窗口的类型样式很多,但归纳起来也就那么几种 消息循环是窗口的灵魂,消息为基础,事件驱动之 有特权的消息不排队,无特权的消息排队 但是总会有那些有谦让精神崇高的消息 -范文最新推荐-17电力安全月工作总结电力安全月工作总结 电力安全月工作总结 2011 年 3 月 1 日至 3 月31 日为我公司的安全生产月,*变电站围绕; 夯实基储提高素质、树立标杆、争创一流;的主
40、题,开展了丰富多彩、形式多样的具体行动:通过看板形式宣传安全第一、预防为主的方针;通过 48+4 的学习机会,进行安全生产大讨论;通过安全活动进行查找本站的隐患的活动,电力安全月工作总结。形成了;人人学会安全,层层尽责保证安全;的良好氛围,使我站的安全生产工作又上了一个新的台阶。本站安全生产月活动具体工作如下:1.开展安全月活动宣传工作,大家坐在一起讨论活动的主题、学习实施纲要、讨论各个实施阶段的活动安排。深刻反思 11.3 事故,汲取事故教训,每人写了一份 11.3 事故反思,并对本站的安全管理、记录报表、规章制度、培训工作、事故隐患每个值班员都谈了自己的看法和建议,对站内管理每个人都倾注了
41、最大的热情,可见 11.3对每一个值班员的触动是刻骨铭心的,安全月的必要开展对变电站各项工作的促进,尤其对值班员安全意识、主人翁精神的影响最为深刻。2.深入开展安全生产大检查活动。在安全生产整顿周活动的基础上,结合秋季安全大检查,进一步查摆了本站安全生产的隐患,特别是各种规章制度的建立、健全、完善和执行情况,对现场运行规程从全面、具体和针对性上进行了修订;制定全站停电的反事故预-范文最新推荐-18案,制定低温天气和防冰闪的反事故措施,进行现场演练。当前正处年底收关和人员调整后的敏感时期,人员思想浮动大,而且本站正在进行新母差与新间隔投运的准备工作,施工人员多,施工人员安全意识和安全防范技能较低
42、,是近阶段我站安全运行的一大隐患,我们会同工作负责人一起讨论施工过程中的存在和潜在的危害,并有针对性地制定防范了措施,保证了施工安全的进行。针对人员素质参差不起,安全意识高低不同,我们制定了*站考核细则 ,制定措施, 明确职责和工作程序,对任何可能发生的情况做了充分的准备工作。3.利用交接- 班的时间,我们查找本站存在的隐患,实行分片分区,责任到人,对查找到的隐患汇总分析,能自己解决的我们都及时认真地消除,对我站能力不足不能解决的,我们纳入工区的职业安全健康体系,由工区负责解决,工作总结电力安全月工作总结 。该报缺陷的上报缺陷,该报危害辨识的报危害辨识,使站内所有设备、所有工作、所有危险点在控
43、、可控、能控。4.对在本月进行的工作、操作等,我们编制事故预案,如 220KV母差保护更换的准备工作和悬垂刷涂工作, 除了工区安排跟踪外,站内根据人员新调整、新人员对设备不熟悉的现状,三班改为两班,加强值班力量, 保证了各项工作的顺利完成。为防止意外发生,我们共同讨论制定出了在工作期间母线故障的反事故预案。5.每个班利用晚饭后的时间讨论检查了我站在遵章守制方面还存在哪些差距,现有规程制度能否满足现场规范化、标准化工作需要,-范文最新推荐-19并在站内宣读并实施了*站考核细则 ,按照个人能力分为 12 大员管理站内事务,规定每个值班员必须按照规章制度工作,否则就严格考核。在个人专业技能与岗位要求
44、存在的差距,站内按人所需制订培训计划,建立心智加油站和个人提升计划的培训平台进行培训。工作日志、检修记录、安全活动、安全用具记录、缺陷记录等班组记录已经和工区进行交流,完善纪录格式。6.对全站值班员进行电力安全工作规程 、本岗位安全职责、工作中的危险点辨识和防范措施及相关专业的规程制度等的培训,选派两名值班员参加工区举办的安规比赛,锻炼值班员具备工作所要求的安全生产技能,熟知各项工作的危险点及防范措施;7.完善三票管理制度,针对本站实际按照运行工区职业安全健康管理体系实施;三票;管理制度,内容完善;;三票;按照规定执行,严格执行倒闸操作;六关; 制度(操作准备关、接令关、操作票填写关、核对图板
45、关、操作监护关、质量检查关) ; ;三票;的填写及执行情况良好。;三票;管理制度健全,制定了;三票; 合格评价标准和考核规定;;三票; 合格评价符合标准要求,对发现的问题能及时提出改进措施,有记录可查;定期对;三票; 的执行情况进行统计、分析和考评。8.重温沧州供电公司运行管理标准及运行相关管理规定。完善我站的综自站的管理规定 ,并制定措施严格执行。查找五防系统管理和软件缺陷,及时上报,并请厂家销缺。查找现场防误闭锁装置的运行情况,缺陷及时报告;建立起完善解锁钥匙的管理制度,严格执行;严格执行操作监护制度,重新修改操作密码,严格密码-范文最新推荐-20管理,使操作监护制度的执行从小操作就具备条
46、件。9.对继电保护及自动装置进行全面检查,核对保护装置定值与定值单相符。规定每月 20 日核对保护压板投切正确,并要求做好记录。检查户外继电器、端子箱等二次设备有防雨、防潮和保护室降温等安全措施。10.现场安全措施方面进行有针对性制定现场三项措施和进行危险点分析;现场作全封闭围网,现场措施落实良好;对每个作业现场做到层层把关,严格执行;三大措施; ,做到责任到位、工作到位、监督到位;对任何违反安全规程的行为立即得到制止。 11.强调安全用具的管理。各类安全用具配置、台账、试验、存放使用符合要求;增加每月 10 日对安全器具进行试验检查,使其保持在完好状态。12.完善消防管理。重新完善消防管理制
47、度,健全消防组织,使新来的值班员在消防组织中找到自己的定位,明确各自的职责;消防设施、器具齐全,布置符合规定,状态完好;培训职工消防器材的使用方法。13.在日常管理中强调安全监督体系,由站长牵头组成安全监督体系,每个值班员都有安全监督责任,明确分工,履行安全监督职责;重新要求运行日志、安全分析记录和安全活动等记录的填写,使其具有针对性和及时性;14.加强输变电设备管理,健全输变电设备台账和技术档案,并做到及时更新。新设备技术培训工作做到及时有效,有效利用嵌入式变电设备巡检系统及按照作业指导书的要求,组织开展变电设-范文最新推荐-21备巡视检查。 ;安全生产月; 活动即将结束,但安全生产是永远没有结束的,而是一个起点,一个契机,今后的工作中我们要继续发扬安全生产月的活动精神,以人为本,从提高人员素质入手,时时保安全,处处要安全,严格按照我公