windows程序设计_第三章_窗口和消息_笔记.doc_第1页
windows程序设计_第三章_窗口和消息_笔记.doc_第2页
windows程序设计_第三章_窗口和消息_笔记.doc_第3页
windows程序设计_第三章_窗口和消息_笔记.doc_第4页
windows程序设计_第三章_窗口和消息_笔记.doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

窗口和消息在Windows中,窗口一词有确切的含义。一个窗口就是屏幕上的一个矩形区域,它接收使用者的输入并以文字或图形的格式显示输出内容。总体结构作为对象,使用者会在屏幕上看到这些窗口,并通过键盘和鼠标直接与它们进行交互操作。更有趣的是,程序写作者的观点与使用者的观点极其类似。窗口以消息的形式接收窗口的输入,窗口也用消息与其它窗口通讯。程序建立的每一个窗口都有相关的窗口消息处理程序。这个窗口消息处理程序是一个函数。更确切地说,窗口通常是在窗口类别的基础上建立的。窗口类别标识了处理窗口消息的窗口消息处理程序。使用窗口类别使多个窗口能够属于同一个窗口类别,并使用同一个窗口消息处理程序。Windows给窗口发送的消息经常是告知窗口,使用者正使用键盘或者鼠标进行输入。这正是按键时窗口知道它被按下的奥妙所在。在窗口大小改变,或者窗口表面需要重画时,由其它消息通知窗口。Windows程序开始执行后,Windows为该程序建立一个消息队列。这个消息队列用来存放该程序可能建立的各种不同窗口的消息。程序中有一小段程序代码,叫做消息循环,用来从队列中取出消息,并且将它们发送给相应的窗口消息处理程序。有些消息直接发送给窗口消息处理程序,不用放入消息队列中。HELLOWIN程序 /*- HELLOWIN.C - Displays Hello, Windows 98! in client area -*/ #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) static TCHAR szAppName = TEXT (HelloWin) ; HWND hwnd ; MSG msg ; WNDCLAS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuNam = NULL ; wndclass.lpszClassName= szAppName ; if (!RegisterClass (&wndclass) MessageBox ( NULL, TEXT (This program requires Windows NT!), szAppName, MB_ICONERROR) ; return 0 ; hwnd = CreateWindow( szAppName, / window class name TEXT (The Hello Program), / window caption WS_OVERLAPPEDWINDOW, / window style CW_USEDEFAULT,/ initial x position CW_USEDEFAULT,/ initial y position CW_USEDEFAULT,/ initial x size CW_USEDEFAULT,/ initial y size NULL, / parent window handle NULL, / window menu handle hInstance, / program instance handle NULL) ; / creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wParam ; LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) case WM_CREATE: PlaySound (TEXT (hellowin.wav), NULL, SND_FILENAME | SND_ASYNC) ; return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT (Hello, Windows 98!), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; return DefWindowProc (hwnd, message, wParam, lParam) ; 您注意:如果您使用Microsoft Visual C+ 为此程序建立新项目,那么您得加上连结程序所需的链接库文件。从Project菜单选择 Setting选项,然后选取Link页面标签。从 Category清单方块中选择General,然后在 Object/Library Modules文字方块添加WINMM.LIB(Windows multimediaWindows多媒体)。通盘考量Windows函数呼叫 LoadIcon 加载图标供程序使用。 LoadCursor 加载鼠标光标供程序使用。 GetStockObject 取得一个图形对象(在这个例子中,是取得绘制窗口背景的画刷对象)。 RegisterClass 为程序窗口注册窗口类别。 MessageBox 显示消息框。前缀类别CS窗口类别样式CW建立窗口DT绘制文字IDI图示IDIDC游标IDMB消息框SND声音WM窗口消息WS窗口样式表3-1 CreateWindow 根据窗口类别建立一个窗口。 ShowWindow 在屏幕上显示窗口。 UpdateWindow 指示窗口自我更新。 GetMessage 从消息队列中取得消息。 TranslateMessage 转译某些键盘消息。 DispatchMessage 将消息发送给窗口消息处理程序。 PlaySound 播放一个声音文件。 BeginPaint 开始绘制窗口。 GetClientRect 取得窗口显示区域的大小。 DrawText 显示字符串。 EndPaint 结束绘制窗口。 PostQuitMessage 在消息队列中插入一个退出程序消息。结构含义MSG消息结构WNDCLASS窗口类别结构PAINTSTRUCT绘图结构RECT矩形结构 DefWindowProc 执行内定的消息处理。 大写字母标识符前缀指示该常数所属的类别,如表3-1所示。新的数据型态HELLOWIN还使用了Windows表头文件中定义的四种数据结构这些数据结构如表3-2所示。句柄简介表3-2句柄是一个(通常为32位的)整数,它代表一个对象。注册窗口类别窗口依照某一窗口类别建立,窗口类别用以标识处理窗口消息的窗口消息处理程序。不同窗口可以依照同一种窗口类别建立。窗口类别定义了窗口消息处理程序和依据此类别建立的窗口的其它特。在建立窗口时,要定义一些该窗口所独有的特征。WNDCLASS结构 typedef struct UINT style ; WNDPROC lpfnWndProc ; int cbClsExtra ; int cbWndExtra ; HINSTANCE hInstance ; HICON hIcon ; HCURSOR hCursor ; HBRUSH hbrBackground ; LPCTSTR lpszMenuName ; LPCTSTR lpszClassName ; WNDCLASS, * PWNDCLASS ; 在WinMain中为WNDCLASS定义一个结构,通常像这样:WNDCLASS wndclass ; 初始化该结构的10个字段wndclass.style = CS_HREDRAW | CS_VREDRAW ;窗口类别样式标识符。wndclass.lpfnWndProc = WndProc ;将这个窗口类别的窗口消息处理程序设定为WndProc。wndclass.cbClsExtra = 0 ; 在窗口类别结构内部保存的一些额外空间wndclass.cbWndExtra = 0 ; 在Windows窗口结构中预留一些额外空间 wndclass.hInstance = hInstance ; 程序的执行实体句柄 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; 窗口图标 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; 加载一个预先定义的鼠标光标 wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ; 传回一个白色画刷的句柄 wndclass.lpszMenuName = NULL ; HElLOWIN没有应用程序菜单 wndclass.lpszClassName = szAppName ; 给出一个类别名称 在初始化该结构的10个字段后,HELLOWIN呼叫RegisterClass来注册这个窗口类别。if (!RegisterClass (&wndclass) MessageBox ( NULL, TEXT (This program requires Windows NT!), szAppName, MB_ICONERROR) ; return 0 ; 建立窗口窗口类别定义了窗口的一般特征,因此可以使用同一窗口类别建立许多不同的窗口。实际呼叫CreateWindow建立窗口时,可能指定有关窗口的更详细的信息。Windows程序设计新手有时会混淆窗口类别和窗口之间的区别,以及为什么一个窗口的所有特征不能被一次设定好。实际上,以这种方式分开这些样式信息是非常方便的。例如,所有的按钮窗口都可以依据同样的窗口类别来建立,与这个窗口类别相关的窗口消息处理程序位于Windows内部。由窗口类别来负责处理按钮的键盘和鼠标输入,并定义按钮在屏幕上的外观形象。从这一点看来,所有的按钮都是以同样的方式工作的。但是并非所有的按钮都是一样的。它们可以有不同的大小,不同的屏幕位置,以及不同的字符串。后面的这样一些特征是窗口定义的一部分,而不是窗口类别定义的。传递给RegisterClass函数的信息会在一个数据结构中设定好,而传递给CreateWindow函数的信息会在函数单独的参数中设定好。下面是HELLOWIN.C中的CreateWindows呼叫,每一个字段都做了完整的说明:hwnd = CreateWindow (szAppName, TEXT ( The Hello Program), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; 此程序建立的窗口含有一个标题列,标题列左边有一个系统菜单按钮,标题列右边有缩小、放大和关闭图示,四周还有一个表示窗口大小的边框。这是标准样式的窗口,名为WS_OVERLAPPEDWINDOW,出现在CreateWindow的窗口样式参数中。如果看一下WINUSER.H,您将会发现此样式是几种位旗标的组合:#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED| WS_CAPTION|WS_SYSMENU| WS_THICKFRAME|WS_MINIMIZEBOX |WS_MAXIMIZEBOX) window caption是显示在标题列中的文字。显示窗口在CreateWindow呼叫传回之后,Windows内部已经建立了这个窗口。这就是说,Windows已经配置了一块内存,用来保存在CreateWindow呼叫中指定窗口的全部信息跟一些其它信息,而Windows稍后就是依据窗口句柄找到这些信息的。显示窗口:ShowWindow (hwnd, iCmdShow) ; 第一个参数是刚刚用CreateWindow建立的窗口句柄。第二个参数是作为参数传给WinMain的iCmdShow。它确定最初如何在屏幕上显示窗口,是一般大小、最小化还是最大化。SW_SHOWNORMAL,则窗口的显示区域就会被窗口类别中定义的背景画刷所覆盖。区域UpdateWindow (hwnd) ;它发送给窗口消息处理程序一个WM_PAINT消息来重画窗口。消息循环呼叫UpdateWindow之后,窗口就出现在视讯显示器上。程序现在必须准备读入使用者用键盘和鼠标输入的数据。Windows为当前执行的每个Windows程序维护一个消息队列。在发生输入事件之后,Windows将事件转换为一个消息并将消息放入程序的消息队列中。程序通过执行一块称之为消息循环的程序代码从消息队列中取出消息:while (GetMessage (&msg, NULL, 0, 0) TranslateMessage (&msg) ; DispatchMessage (&msg) ; msg变量是型态为MSG的结构,型态MSG在WINUSER.H中定义如下:typedef struct tagMSG HWND hwnd ; UINT message ; WPARAM wParam ; LPARAM lParam ; DWORD time ; POINT pt ; MSG, * PMSG ; POINT数据型态也是一个结构,它在WINDEF.H中定义如下:typedef struct tagPOINT LONG x ; LONG y ; POINT, * PPOINT; 消息循环以GetMessage呼叫开始,它从消息队列中取出一个消息:GetMessage (&msg, NULL, 0, 0) 这一呼叫传给Windows一个指标,指向名为msg的MSG结构。第二、第三和第四个参数设定为NULL或者0,表示程序接收它自己建立的所有窗口的所有消息。Windows用从消息队列中取出的下一个消息来填充消息结构的各个字段,结构的各个字段包括: hwnd 接收消息的窗口句柄。在HELLOWIN程序中,这一参数与CreateWindow传回的hwnd值相同,因为这是该程序拥有的唯一窗口。 message 消息标识符。这是一个数值,用以标识消息。对于每个消息,均有一个对应的标识符,这些标识符定义于Windows表头文件(其中大多数在WINUSER.H中),以前缀WM(window message,窗口消息)开头。例如,使用者将鼠标光标放在HELLOWIN显示区域之内,并按下鼠标左按钮,Windows就在消息队列中放入一个消息,该消息的message字段等于WM_LBUTTONDOWN。这是一个常数,其值为0x0201。 wParam 一个32位的消息参数,其含义和数值根据消息的不同而不同。 lParam 一个32位的消息参数,其值与消息有关。 time 消息放入消息队列中的时间。 pt 消息放入消息队列时的鼠标坐标。 只要从消息队列中取出消息的message字段不为WM_QUIT(其值为0x0012),GetMessage就传回一个非零值。WM_QUIT消息将导致GetMessage传回0。TranslateMessage (&msg) ; 将msg结构传给Windows,进行一些键盘转换。DispatchMessage (&msg) ; 又将msg结构回传给Windows,windows呼叫消息处理程序。处理完消息之后,WndProc传回到Windows。此时,Windows还停留在DispatchMessage呼叫中。在结束DispatchMessage呼叫的处理之后,Windows回到HELLOWIN,并且接着从下一个GetMessage呼叫开始消息循环。窗口消息处理程序以上我们所讨论的都是必要的负担:注册窗口类别,建立窗口,然后在屏幕上显示窗口,程序进入消息循环,然后不断从消息队列中取出消息来处理。实际的动作发生在窗口消息处理程序中。窗口消息处理程序确定了在窗口的显示区域中显示些什么以及窗口怎样响应使用者输入。在HELLOWIN中,窗口消息处理程序是命名为WndProc的函数。一个Windows程序可以包含多个窗口消息处理程序。一个窗口消息处理程序总是与呼叫RegisterClass注册的特定窗口类别相关联。CreateWindow函数根据特定窗口类别建立一个窗口。但依据一个窗口类别,可以建立多个窗口。窗口消息处理程序总是定义为如下形式:LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 注意,窗口消息处理程序的四个参数与MSG结构的前四个字段是相同的。程序通常不直接呼叫窗口消息处理程序,窗口消息处理程序通常由Windows本身呼叫。通过呼叫SendMessage函数,程序能够直接呼叫它自己的窗口消息处理程序。处理消息窗口消息处理程序所接受的每个消息均是用一个数值来标识的,也就是传给窗口消息处理程序的message参数。Windows表头文件WINUSER.H为每个消息参数定义以WM(窗口消息)为前缀开头的标识符。一般来说,Windows程序写作者使用switch和case结构来确定窗口消息处理程序接收的是什么消息,以及如何适当地处理它。窗口消息处理程序在处理消息时,必须传回0。窗口消息处理程序不予处理的所有消息应该被传给名为DefWindowProc的Windows函数。从DefWindowProc传回的值必须由窗口消息处理程序传回。窗口消息处理程序的结构如下:switch (iMsg) caseWM_CREATE : 处理WM_CREATE消息 return 0 ; caseWM_PAINT : 处理WM_PAINT消息 return 0 ; caseWM_DESTROY : 处理WM_DESTROY消息 return 0 ; return DefWindowProc (hwnd, iMsg, wParam, lParam) ; 呼叫DefWindowProc来为窗口消息处理程序不予处理的所有消息提供内定处理,这是很重要的。不然一般动作,如终止程序,将不会正常执行。WM_PAINT消息这个消息在Windows程序设计中是很重要的。当窗口显示区域的一部分显示内容或者全部变为无效,以致于必须更新画面时,将由这个消息通知程序。在最初建立窗口的时候,整个显示区域都是无效的,因为程序还没有在窗口上画什么东西。第一条WM_PAINT消息(通常发生在WinMain中呼叫UpdateWindow时)指示窗口消息处理程序在显示区域上画一些东西。在使用者改变HELLOWIN窗口的大小后,显示区域的显示内容重新变得无效。当使用者将HELLOWIN最小化,然后再次将窗口恢复为以前的大小时,Windows将不会保存显示区域的内容。在图形环境下,窗口显示区域涉及的数据量很大。因此,Windows令窗口无效,窗口消息处理程序接收一条WM_PAINT消息,并自动恢复其窗口的内容。在移动窗口以致其相互重迭时,Windows不保存一个窗口中被另一个窗口所遮盖的内容。在这一部分不再被遮盖之后,它就被标志为无效。窗口消息处理程序接收到一条WM_PAINT消息,以更新窗口的内容。对WM_PAINT的处理几乎总是从一个BeginPaint呼叫开始:hdc = BeginPaint (hwnd, &ps) ; 而以一个EndPaint呼叫结束:EndPaint (hwnd, &ps) ;第一个参数都是程序的窗口句柄,第二个参数是指向型态为PAINTSTRUCT的结构指针。PAINTSTRUCT结构中包含一些窗口消息处理程序,可以用来更新显示区域的内容。在BeginPaint呼叫中,使用注册窗口类别的WNDCLASS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论