当前位置:文档之家› 第二章 Windows窗口设计

第二章 Windows窗口设计

第二章:WIN32 窗体程序设计学习目标⏹Win32编程中需要掌握的一些重要概念⏹详解Win32程序⏹理解Win32程序的消息机制⏹Win32程序对鼠标和键盘的控制Win32编程中需要掌握的一些重要概念学习windows编程是一个比较难的过程,主要的障碍是因为windows程序中很多新的东西,我们一下子不能适应,下面我们就来扫清这些障碍:我们在上一章中看到了一个简单的windows程序,大家会发现windows 程序中有很多全大写定义的东西,这就是我们的障碍之一,因为,太多的东西我们以前没有见过,windows程序中全大写的东西可以分为这样三种:第一种是:windows定义的变量比如这句:LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )这是一个方法的定义,这和我们以前的程序就有太多的不同。

下面的列表是从相应windows的头文件中摘下来的,看完这个后,你是否可以理解上面这句话的意思。

#define FAR far#define NEAR near#define CONST const#define CALLBACK __stdcall#define WINAPI __stdcall#define WINAPIV __cdecl#define APIENTRY WINAPI#define APIPRIVATE __stdcall#define PASCAL __stdcalltypedef unsigned long DWORD;typedef int BOOL;typedef unsigned char BYTE;typedef unsigned short WORD;typedef float FLOAT;typedef FLOAT *PFLOAT;typedef BOOL near *PBOOL;typedef BOOL far *LPBOOL;typedef BYTE near *PBYTE;typedef BYTE far *LPBYTE;typedef int near *PINT;typedef int far *LPINT;typedef WORD near *PWORD;typedef WORD far *LPWORD;typedef long far *LPLONG;typedef DWORD near *PDWORD;typedef DWORD far *LPDWORD;typedef void far *LPVOID;typedef CONST void far *LPCVOID;typedef int INT;typedef unsigned int UINT;typedef unsigned int *PUINT;typedef UINT WPARAM;typedef LONG LPARAM;typedef LONG LRESULT;其实,windows程序把很多变量进行了重新定义,还记得typedef这个类型定义关键字吧!其实上面的UINT、WPARAM、LPARAM,其实都是unsigned int(无符号整数),其实HWND也是无符号整数,后面我们详细介绍HWND,今后,如果大家见到了一个类型是全大写的,那么它一定是在windows的头文件中重新定义了。

还有就是:LRESULT CALLBACK,从上面的表中,大家可以看到他们是返回类型和宏定义,其中,LRESULT是long,而CALLBACK是函数的调用方式__stdcall。

第二种是windows的宏定义:在前面,大家看到了__stdcall是一个宏定义,在windows程序中有大量的宏定义,宏定义用于这样几个地方:◆常量所有的消息都是常量,比如前面看到的 WM_KEYDOWN、WM_PAINT等,所有的键盘标识,如VK_ESCAPE,还有就是我们在函数调用中用到的一些参数:如WS_OVERLAPPEDWINDOW, WHITE_BRUSH、IDI_APPLICATION等都是常量◆简单函数用宏如:#define MAKEWORD(a, b)((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))#define MAKELONG(a,b)((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))#define LOWORD(l) ((WORD)(l))#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) #define LOBYTE(w) ((BYTE)(w))#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) 以上的都是简单的函数,如LOWORD是表示取一个DWORD(32位整数)的低16位,而HIWORD取高16位◆程序结构中用到宏,今后,我们要学习的消息映射中的BEGIN_MESSAGE_MAP、DECLARE_MESSAGE_MAP等就是在程序结构中用到的宏。

第三中是windows中的结构:windows程序中大量使用结构,对这些结构的掌握程度,可以作为衡量一个程序员对windows程序的熟悉程度,windows程序的结构难,而且结构中的成员非常多,是我们学习的难点。

在上一章的程序中,我们看到的结构有:WNDCLASS、MSG等,学习中,大家应该掌握这些常用结构的常用成员的用法,我们来看看这两个结构typedef struct tagWNDCLASSA {UINT style;WNDPROC lpfnWndProc;int cbClsExtra;int cbWndExtra;HINSTANCE hInstance;HICON hIcon;HCURSOR hCursor;HBRUSH hbrBackground;LPCSTR lpszMenuName;LPCSTR lpszClassName;} WNDCLASSA;typedef struct tagMSG {HWND hwnd;UINT message;WPARAM wParam;LPARAM lParam;DWORD time;POINT pt;} MSG;结构中成员的具体含义请看后面的说明。

理解句柄上一章的程序中,我们看到了这样的类型定义HINSTANCE 执行实体(程序自身)句柄HWND 窗口句柄在windows程序中,以H定义开始的变量类型,这个H,我们叫HANDLE(句柄)。

handle的本意是把柄,把手的意思。

是你与操作系统打交道的东西。

举个例子:比如你做了亏心事(我说的是比如,呵呵),不幸让我抓住了把柄,那么我让你做什么你就得做什么,因为你的把柄在我这。

我们编程的时候也是这样,比如我们要想操纵一个窗口,那我们就必须"抓住它的把柄",只有这样,我们才能改变它的属性,改变它的式样,甚至销毁它。

句柄在Windows中使用非常频繁。

句柄是一个,句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数。

(通常为32位的)整数,这就和我们每个人都会有一个身份证编号,我们用这个编号区分不同的人,同样windows用不同的句柄来区分和使用各种各样的应用程序实例,窗口,控制,位图,GDI对象等,如:HWND 窗口HINSTANCE 执行程序实体HMENU 菜单HDC 图形设备HBITMAP 位图HICON 图标HCURSOR 鼠标游标HBRUSH 画刷我们也可以把Windows中的句柄看成传统C或者MS-DOS程序设计中使用的文件句柄。

应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。

句柄的实际值对程序来说是无关紧要的。

只是,我们要知道在程序中间怎样去使用这个句柄,以后,在很多的函数中,第一个参数就会是该对象句柄,如:ShowWindow,UpdateWindow等函数的第一个参数都是窗口句柄。

如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。

我们知道,所谓指针是一种内存地址。

应用程序启动后,组成这个程序的各对象是住留在内存的。

如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。

但是,如果您真的这样认为,那么您就大错特错了。

我们知道,Windows是一个以虚拟内存为基础的操作系统。

在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。

对象被移动意味着它的地址变化了。

如果地址总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。

Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。

这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。

这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。

句柄地址(稳定)→记载着对象在内存中的地址————→对象在内存中的地址(不稳定)→实际对象本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。

但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。

假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。

详解Win32程序一个典型的windows程序结构是这样的:WinMain部分:填充窗口结构 --> 注册窗口信息 --> 建立窗口 --> 显示窗口 --> 消息循环消息处理部分:是一个大的switch case 结构,根据不同的消息类型,进行不同的处理。

对于WinMain部分,一般都是固定不变的,我们不需要做太多的变动,只是,我们想改变窗口的一些特性时才需要修改,比如,我们想改变窗口的大小、背景色、图标等,我们就需要更改相应的部分,下面我们看看改动的两个主要地方:窗体结构WNDCLASStypedef struct tagWNDCLASSA{UINT style ;WNDPROC lpfnWndProc ;int cbClsExtra ;int cbWndExtra ;HINSTANCE hInstance ;HICON hIcon ;HCURSOR hCursor ;HBRUSH hbrBackground ;LPCSTR lpszMenuName ;LPCSTR lpszClassName ;}WNDCLASSA, * PWNDCLASSA, NEAR * NPWNDCLASSA, FAR * LPWNDCLASSA ;在这里提示一下资料型态和匈牙利表示法:其中的lpfn字首代表「指向函数的长指针」。

相关主题