读书人

Windows程式开发设计指南-视窗和消息

发布时间: 2012-09-16 17:33:17 作者: rapoo

Windows程式开发设计指南--视窗和讯息

3. 视窗和讯息

在前两章,程式使用了同一个函式MessageBox来向使用者输出文字。MessageBox函式会建立一个「视窗」。在Windows中,「视窗」一词有确切的含义。一个视窗就是萤幕上的一个矩形区域,它接收使用者的输入并以文字或图形的格式显示输出内容。

MessageBox函式建立一个视窗,但这只是一个功能有限的特殊视窗。讯息视窗有一个带关闭按钮的标题列、一个选项图示、一行或多行文字,以及最多四个按钮。当然,必须选择Windows提供给您的图示与按钮。

MessageBox函式非常有用,但下面不会过多地使用它。我们不能在讯息方块中显示图形,而且也不能在讯息方块中添加功能表。要添加这些物件,就需要建立自己的视窗,现在就开始。

自己的视窗
 

建立视窗很简单,只需呼叫CreateWindow函式即可。

好啦,虽然建立视窗的函式的确名为CreateWindow,而且您也能在/Platform SDK/User Interface Services/Windowing/Windows/Window Reference/Window Functions找到此文件,但您将发现CreateWindow的第一个参数就是所谓的「视窗类别名称」,并且该视窗类别连接所谓的「视窗讯息处理程式」。在我们呼叫CreateWindow之前,有一点背景知识会对您大有帮助。

总体结构
 

进行Windows程式设计,实际上是在进行一种物件导向的程式设计(OOP)。这一点在Windows中使用得最多的物件上表现最为明显。这种物件正是Windows之所以命名为「Windows」的原因,它具有人格化的特徵,甚至可能会在您的梦中出现,这就是那个叫做「视窗」的东西。

桌面上最明显的视窗就是应用程式视窗。这些视窗含有显示程式名称的标题列、功能表甚至可能还有工具列和卷动列。另一类视窗是对话方块,它可以有标题列也可以没有标题列。

装饰对话方块表面的还有各式各样的按键、单选按钮、核取方块、清单方块、卷动列和文字输入区域。其中每一个小的视觉物件都是一个视窗。更确切地说,这些都称为「子视窗」或「控制项视窗」或「子视窗控制项」。

作为物件,使用者会在萤幕上看到这些视窗,并通过键盘和滑鼠直接与它们进行交互操作。更有趣的是,程式写作者的观点与使用者的观点极其类似。视窗以「讯息」的形式接收视窗的输入,视窗也用讯息与其他视窗通讯。对讯息的理解将是学习如何写作Windows程式所必须越过的障碍之一。

这有一个Windows的讯息范例:我们知道,大多数的Windows程式都有大小合适的应用程式视窗。也就是说,您能够通过滑鼠拖动视窗的边框来改变视窗的大小。通常,程式将通过改变视窗中的内容来回应这种大小的变化。您可能会猜测(并且您也是正确的),是Windows本身而不是应用程式在处理与使用者重新调整视窗大小相关的全部杂乱程式。由於应用程式能改变其显示的样子,所以它也「知道」视窗大小改变了。

应用程式是如何知道使用者改变了视窗的大小的呢?由於程式写作者习惯了往常的文字模式程式,作业系统没有设置将此类讯息通知给使用者的机制。问题的关键在於理解Windows所使用的架构。当使用者改变视窗的大小时,Window给程式发送一个讯息指出新视窗的大小。然後程式就可以调整视窗中的内容,以回应大小的变化。

「Windows给程式发送讯息。」我们希望读者不要对这句话视而不见。它到底表达了什么意思呢?我们在这里讨论的是程式码,而不是一个电子邮件系统。作业系统怎么给程式发送讯息呢?

其实,所谓「Windows给程式发送讯息」,是指Windows呼叫程式中的一个函式,该函式的参数描述了这个特定讯息。这种位於Windows程式中的函式称为「视窗讯息处理程式」。

无疑,读者对程式呼叫作业系统的做法是很熟悉的。例如,程式在打开磁片档案时就要使用有关的系统呼叫。读者所不习惯的,可能是作业系统呼叫程式,而这正是Windows物件导向架构的基础。

程式建立的每一个视窗都有相关的视窗讯息处理程式。这个视窗讯息处理程式是一个函式,既可以在程式中,也可以在动态连结程式库中。Windows通过呼叫视窗讯息处理程式来给视窗发送讯息。视窗讯息处理程式根据此讯息进行处理,然後将控制传回给Windows。

更确切地说,视窗通常是在「视窗类别」的基础上建立的。视窗类别标识了处理视窗讯息的视窗讯息处理程式。使用视窗类别使多个视窗能够属於同一个视窗类别,并使用同一个视窗讯息处理程式。例如,所有Windows程式中的所有按钮均依据同一个视窗类别。这个视窗类别与一个处理所有按钮讯息的视窗讯息处理程式(位於Windows的动态连结程式库中)联结。

在物件导向的程式设计中,物件是程式与资料的组合。视窗是一种物件,其程式是视窗讯息处理程式。资料是视窗讯息处理程式保存的资讯和Windows为每个视窗以及系统中那个视窗类别保存的资讯。

视窗讯息处理程式处理给视窗发送讯息。这些讯息经常是告知视窗,使用者正使用键盘或者滑鼠进行输入。这正是按键视窗知道它被「按下」的奥妙所在。在视窗大小改变,或者视窗表面需要重画时,由其他讯息通知视窗。

Windows程式开始执行後,Windows为该程式建立一个「讯息伫列」。这个讯息伫列用来存放该程式可能建立的各种不同视窗的讯息。程式中有一小段程式码,叫做「讯息回圈」,用来从伫列中取出讯息,并且将它们发送给相应的视窗讯息处理程式。有些讯息直接发送给视窗讯息处理程式,不用放入讯息伫列中。

如果您对这段Windows架构过於简略的描述将信将疑,就让我们去看看在实际的程式中,视窗、视窗类别、视窗讯息处理程式、讯息伫列、讯息回圈和视窗讯息是如何相互配合的。这或许会对您有些帮助。

HELLOWIN程式
 

建立一个视窗首先需要注册一个视窗类别,那需要一个视窗讯息处理程式来处理视窗讯息。处理视窗讯息对每个Windows程式都带来了些负担。程式3-1所示的HELLOWIN程式中整个做的事情差不多就是料理这些事情。

 程式3-1  HELLOWINHELLOWIN.C/*------------------------------------   HELLOWIN.C -- Displays "Hello, Windows 98!" in client area      (c) Charles Petzold, 1998 -----------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT ("HelloWin") ;HWNDhwnd ;MSGmsg ;WNDCLASwndclass ; 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 nameTEXT ("The Hello Program"),// window captionWS_OVERLAPPEDWINDOW,// window styleCW_USEDEFAULT,// initial x positionCW_USEDEFAULT,// initial y positionCW_USEDEFAULT,// initial x sizeCW_USEDEFAULT,// initial y sizeNULL,// 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){HDChdc ;PAINTSTRUCT ps ;RECTrect ;     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 ;          caseWM_DESTROY:PostQuitMessage (0) ;return 0 ;     }   return DefWindowProc (hwnd, message, wParam, lParam) ;}

程式建立一个普通的应用程式视窗,如图3-1所示。在视窗显示区域的中央显示「Hello, Windows 98!」。如果安装了音效卡,那么您还可以听到相应的朗读声音。


 

Windows程式开发设计指南-视窗和消息

图3-1 HELLOWIN视窗

提醒您注意:如果您使用Microsoft Visual C++ 为此程式建立新专案,那么您得加上连结程式所需的程式库档案。从 Project 功能表选择 Setting选项,然後选取 Link页面标签。从 Category清单方块中选择 General,然後在 Object/Library Modules文字方块添加 WINMM.LIB Windows multimedia Windows多媒体)。您这样做是因为HELLOWIN将使用多媒体功能呼叫,而内定的专案中又不包括多媒体程式库档案。不然连结程式报告了错误资讯,表明PlaySound函式不可用。

HELLOWIN将存取档案HELLOWIN.WAV,该档案在本书所附光碟的HELLOWIN目录中。执行HELLOWIN.EXE时,内定的目录必须是HELLOWIN。在Visual C++中执行此程式时,虽然执行档会产生在HELLOWIN的RELEASE或DEBUG子目录中,但执行程式的目录还是必须在HELLOWIN中。

通盘考量
 

实际上,每一个Windows程式码中都包括HELLOWIN.C程式的大部分。没人能真正记住此程式的全部写法;通常,Windows程式写作者在开始写一个新程式时总是会复制一个现有的程式,然後再做相应的修改。您可以按此习惯自由使用本书附带光碟中的程式。

上面提到,HELLOWIN将在其视窗的中央显示字串。这种说法不是完全正确的。文字实际显示在程式显示区域的中央,它在图3-1中是标题列和边界范围内的大片白色区域。这区别对我们来说很重要;显示区域就是程式自由绘图并且向使用者显示输出结果的视窗区域。

如果您认真思考一下,将会发现虽然只有80行程式码,这个视窗却令人惊讶地具有许多功能。您可以用滑鼠按住标题列,在萤幕上移动视窗;可以按住大小边框,改变视窗的大小。在视窗大小改变时,程式自动地将「Hello, Windows 98!」字串重新定位在显示区域的中央。您可以按最大化按钮,放大HELLOWIN以充满整个萤幕;也可以按最小化按钮,将程式缩小成一个图示。您可以在系统功能表中执行所有选项(就是按下在标题列最左端的小图示);也可以从系统功能表中选择 Close 选项,或者单击标题列最右端的关闭按钮,或者双击标题列最左端的图示,来关闭视窗以终止程式的执行。

我们将在本章的余下部分对此程式作一详细的检查。当然,我们首先要从整体上看一下。

与前两章中的范例程式一样,HELLOWIN.C也有一个WinMain函式,但它还有另外一个函式,名为WndProc。这就是视窗讯息处理程式。注意,在HELLOWIN.C中没有呼叫WndProc的程式码。当然,在WinMain中有对WndProc的参考,而这就是该函式要在程式开头附近宣告的原因。

Windows函式呼叫
 

HELLOWIN至少呼叫了18个Windows函式。下面以它们在HELLOWIN中出现的次序列出这些函式以及各自的简明描述:

读书人网 >windows

热点推荐