1. 声明一个结构变量,一般用结构名的小写形式作为变量名。
2. LP和NP在32为操作系统上是一样的。
3. 窗口依照某一窗口类别建立,窗口类别用以标识处理窗口消息的窗口消息处理程序。
不同窗口可以依照同一种窗口类别建立。例如,Windows中的所有按钮窗口-包括按键、复选框,以及单选按钮-都是依据同一种窗口类别建立的。窗口类别定义了窗口消息处理程序和依据此类别建立的窗口的其它特征。在建立窗口时,要定义一些该窗口所独有的特征。
在为程序建立窗口之前,必须首先呼叫RegisterClass注册一个窗口类别。该函数只需要一个参数,即一个指向型态为WNDCLASS的结构指针。WNDCLASS结构中最重要的是第二个和最后一个参数。第二个字段(lpfnWndProc) 是依据这个类别来建立的所有窗口所使用的窗口消息处理程序的地址。在HELLOWIN.C中,这个是WndProc函数。最后一个字段是窗口类别的文字名称。程序写作者可以随意定义其名称。在只建立一个窗口的程序中,窗口类别名称通常设定为程序名称。
4. WNDCLASS结构的第二个字段由以下叙述进行初始化:
wndclass.lpfnWndProc = WndProc ;
这条叙述将这个窗口类别的窗口消息处理程序设定为WndProc,即HELLOWIN.C中的第二个函数。这个过程将处理依据这个窗口类别建立的所有窗口的全部消息。在C语言中,像这样在结构中使用函数名时,真正提供的是指向函数的指针。
5. 画刷是个绘图词汇,指用来填充一个区域的着色样式。Windows有几个标准画刷,也称为「备用(stock)」画刷。
6. 在初始化该结构的10个字段后,HELLOWIN呼叫RegisterClass来注册这个窗口类别。该函数只有一个参数,即指向WNDCLASS结构的指针。实际上,RegisterClassA函数将获得一个指向WNDCLASSA结构的指针.
7. 在32位的Windows中,hPrevInstance总是NULL。此程序代码会正常执行,而实际上也没必要检查hPrevInstance。
8. MessageBoxW是可在Windows 98环境下执行的几个Unicode函数之一。(稍做了解)
9. 窗口类别定义了窗口的一般特征,因此可以使用同一窗口类别建立许多不同的窗口。实际呼叫CreateWindow建立窗口时,可能指定有关窗口的更详细的信息。
10. Windows程序设计新手有时会混淆窗口类别和窗口之间的区别,以及为什么一个窗口的所有特征不能被一次设定好。实际上,以这种方式分开这些样式信息是非常方便的。例如,所有的按钮窗口都可以依据同样的窗口类别来建立,与这个窗口类别相关的窗口消息处理程序位于Windows内部。由窗口类别来负责处理按钮的键盘和鼠标输入,并定义按钮在屏幕上的外观形象。从这一点看来,所有的按钮都是以同样的方式工作的。但是并非所有的按钮都是一样的。它们可以有不同的大小,不同的屏幕位置,以及不同的字符串。后面的这样一些特征是窗口定义的一部分,而不是窗口类别定义的。我的理解:其实就好像原油和各种成品油的概念一样^_^
11. 在建立一个「最上层」窗口,如应用程序窗口时,注释为「父窗口句柄」的参数设定为NULL。通常,如果窗口之间存在有父子关系,则子窗口总是出现在父窗口的上面。应用程序窗口出现在桌面窗口的上面,但不必为呼叫CreateWindow而找出桌面窗口的句柄。
12 .Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。只要从消息队列中取出消息的message字段不为WM_QUIT(其值为0x0012),GetMessage就传回一个非零值。WM_QUIT消息将导致GetMessage传回0。
13. DispatchMessage (&msg) ;
又将msg结构回传给Windows。然后,Windows将该消息发送给适当的窗口消息处理程序,让它进行处理。这也就是说,Windows将呼叫窗口消息处理程序。在HELLOWIN中,这个窗口消息处理程序就是WndProe函数。处理完消息之后,WndProc传回到Windows。此时,Windows还停留在DispatchMessage呼叫中。在结束DispatchMessage呼叫的处理之后,Windows回到HELLOWIN,并且接着从下一个GetMessage呼叫开始消息循环。(有点像绕口令-_!)
14. 在HELLOWIN中,窗口消息处理程序是命名为WndProc的函数(也就是窗口过程)。窗口消息处理程序可任意命名(只要求不和其它名字发生冲突)。一个Windows程序可以包含多个窗口消息处理程序。一个窗口消息处理程序总是与呼叫RegisterClass注册的特定窗口类别相关联。
15. 程序通常不直接呼叫窗口消息处理程序,窗口消息处理程序通常由Windows本身呼叫。通过呼叫SendMessage函数,程序能够直接呼叫它自己的窗口消息处理程序。(有点儿奇怪,留着)
16. 窗口消息处理程序接收的第一个消息-也是WndProc选择处理的第一个消息-是WM_CREATE。当Windows在WinMain中处理CreateWindow函数时,WndProc接收这个消息。就是说,在HELLOWIN呼叫CreateWindow时,Windows将做一些它必须做的工作。在这些工作中,Windows呼叫WndProc,将第一个参数设定为窗口句柄,第二个参数设定为WM_CREATE。WndProc处理WM_CREATE消息并将控制传回给Windows。 Windows然后可以从CreateWindow呼叫中传回到HELLOWIN中,继续在WinMain中进行下一步的处理。WndProc通过从窗口消息处理程序中传回0,结束了整个WM_CREATE的处理。
17. WndProc处理的第二个消息为WM_PAINT。这个消息在Windows程序设计中是很重要的。当窗口显示区域的一部分显示内容或者全部变为「无效」,以致于必须「更新画面」时,将由这个消息通知程序。
显示区域的显示内容怎么会变得无效呢?在最初建立窗口的时候,整个显示区域都是无效的,因为程序还没有在窗口上画什么东西。第一条WM_PAINT消息(通常发生在WinMain中呼叫UpdateWindow时)指示窗口消息处理程序在显示区域上画一些东西。
在使用者改变HELLOWIN窗口的大小后,显示区域的显示内容重新变得无效。读者应该还记得,HELLOWIN中wndclass结构的style字段设定为标志CS_HREDRAW和CS_VREDRAW,这样的格式设定指示Windows,在窗口大小改变后,就把整个窗口显示内容当成无效。然后,窗口消息处理程序将收到一条WM_PAINT消息。
当使用者将HELLOWIN最小化,然后再次将窗口恢复为以前的大小时,Windows将不会保存显示区域的内容。在图形环境下,窗口显示区域涉及的数据量很大。因此,Windows令窗口无效,窗口消息处理程序接收一条WM_PAINT消息,并自动恢复其窗口的内容。
在移动窗口以致其相互重迭时,Windows不保存一个窗口中被另一个窗口所遮盖的内容。在这一部分不再被遮盖之后,它就被标志为无效。窗口消息处理程序接收到一条WM_PAINT消息,以更新窗口的内容。(这一大段没有一句废话,都是重点)
18. BeginPaint呼叫中,如果显示区域的背景还未被删除,则由Windows来删除。BeginPaint呼叫令整个显示区域有效,并传回一个「设备内容句柄」。设备内容是指实体输出设备(如视讯显示器)及其设备驱动程序。EndPaint释放设备内容句柄,使之不再有效。
19. GetClientRect (hwnd, &rect) ;
第一个参数是程序窗口的句柄。第二个参数是一个指标,指向一个RECT型态的rectangle结构。该结构有四个LONG字段,分别为left、top、right和bottom。GetClientRect将这四个字段设定为窗口显示区域的尺寸。left和top字段通常设定为0,right和bottom字段设定为显示区域的宽度和高度(像素点数)。(汗!终于知道RECT的具体意思了)
20. 一旦显示区域变得无效(正如在改变大小时所发生的情况一样),WndProc就接收到一个新的WM_PAINT消息。WndProc通过呼叫GetClientRect取得变化后的窗口大小,并在新窗口的中央显示文字。(在窗口上点击鼠标,移动窗口会不会发生呢?)
21. 假设使用者执行HELLOWIN,并且使用者最终单击了 Close按钮,或者假设用键盘或鼠标从系统菜单中选择了 Close, DefWindowProc处理这一键盘或者鼠标输入,在检测到使用者选择了Close选项之后,它给窗口消息处理程序发送一条WM_SYSCOMMAND消息。WndProc将这个消息传给DefWindowProc。DefWindowProc给窗口消息处理程序发送一条WM_CLOSE消息来响应之。WndProc再次将它传给DefWindowProc。DestroyWindow呼叫DestroyWindow(是不是写错了?)来响应这条WM_CLOSE消息。DestroyWindow导致Windows给窗口消息处理程序发送一条WM_DESTROY消息。WndProc再呼叫PostQuitMessage,将一条WM_QUIT消息放入消息队列中,以此来响应此消息。这个消息导致WinMain中的消息循环终止,然后程序结束。
22. 消息能够被分为「队列化的」和「非队列化的」。队列化的消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化的消息在Windows呼叫窗口时直接送给窗口消息处理程序。也就是说,队列化的消息被「发送」给消息队列,而非队列化的消息则「发送」给窗口消息处理程序。队列化消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP消息)、击键产生的字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出。队列化消息还包含时钟消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT)。非队列化消息则是其它消息。在许多情况下,非队列化消息来自呼叫特定的Windows函数。例如,当WinMain呼叫CreateWindow时,Windows将建立窗口并在处理中给窗口消息处理程序发送一个WM_CREATE消息。当WinMain呼叫ShowWindow时,Windows将给窗口消息处理程序发送WM_SIZE和WM_SHOWWINDOW消息。当WinMain呼叫UpdateWindow时,Windows将给窗口消息处理程序发送WM_PAINT消息。键盘或鼠标输入时发出的队列化消息信号,也能在非队列化消息中出现。例如,用键盘或鼠标选择了一个菜单项时,键盘或鼠标消息就是队列化的,而说明菜单项已选中的WM_COMMAND消息则可能就是非队列化的。
23. 消息是以一种有序的同步的方式进出时,消息与硬件的中断不同。在一个窗口消息处理程序中处理消息时,程序不会被其它消息突然中断。
24. 虽然Windows程序可以多线程执行,但每个执行绪的消息队列只为窗口消息处理程序在该执行绪中执行的窗口处理消息。换句话说,消息循环和窗口消息处理程序不是并发执行的。当一个消息循环从其消息队列中接收一个消息,然后呼叫DispatchMessage将消息发送给窗口消息处理程序时,直到窗口消息处理程序将控制传回给Windows,DispatchMessage才能结束执行。我的理解:每个线程有自己的消息队列,个个消息队列之间相互独立。
25. 当然,窗口消息处理程序能呼叫给窗口消息处理程序发送另一个消息的函数。这时,窗口消息处理程序必须在函数呼叫传回之前完成对第二个消息的处理。那时窗口消息处理程序将处理最初的消息。例如,当窗口过程调用UpdateWindow时,Windows将呼叫窗口消息处理程序来处理WM_PAINT消息。窗口消息处理程序处理WM_PAINT消息结束以后,UpdateWindow呼叫将把控制传回给窗口消息处理程序。
呼!基本上要点都在这里了,作者的用辞十分精炼,有些难点还要再回过头来看看。收获还是蛮多的^_^