第二章:WIN32窗体程序设计 ITjob就业培训
POINT pt;
} MSG;
结构中成员的具体含义请看后面的说明。 ? 理解句柄
上一章的程序中,我们看到了这样的类型定义 HINSTANCE HWND
执行实体(程序自身)句柄
窗口句柄
在windows程序中,以H定义开始的变量类型,这个H,我们叫HANDLE(句柄)。handle的本意是把柄,把手的意思。是你与操作系统打交道的东西。举个例子:比如你做了亏心事(我说的是比如,呵呵),不幸让我抓住了把柄,那么我让你做什么你就得做什么,因为你的把柄在我这。我们编程的时候也是这样,比如我们要想操纵一个窗口,那我们就必须\抓住它的把柄\,只有这样,我们才能改变它的属性,改变它的式样,甚至销毁它。
句柄在Windows中使用非常频繁。句柄是一个,句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数。(通常为32位的)整数,这就和我们每个人都会有一个身份证编号,我们用这个编号区分不同的人,同样windows用不同的句柄来区分和使用各种各样的应用程序实例,窗口,控制,位图,GDI对象等,如: HWND
窗口
执行程序实体
HINSTANCE HMENU HDC
菜单 图形设备
位图
HBITMAP HICON
图标
6
第二章:WIN32窗体程序设计 ITjob就业培训
HCURSOR HBRUSH
鼠标游标 画刷
我们也可以把Windows中的句柄看成传统C或者MS-DOS程序设计中使用的文件句柄。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。句柄的实际值对程序来说是无关紧要的。只是,我们要知道在程序中间怎样去使用这个句柄,以后,在很多的函数中,第一个参数就会是该对象句柄,如:ShowWindow,UpdateWindow等函数的第一个参数都是窗口句柄。 如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?
为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。
句柄地址(稳定)→记载着对象在内存中的地址————→对象在内存中的地
7
第二章:WIN32窗体程序设计 ITjob就业培训
址(不稳定)→实际对象
本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。 但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。
8
第二章:WIN32窗体程序设计 ITjob就业培训
详解Win32程序
一个典型的windows程序结构是这样的: WinMain部分:
填充窗口结构 --> 注册窗口信息 --> 建立窗口 --> 显示窗口 --> 消息循环
消息处理部分:
是一个大的switch case 结构,根据不同的消息类型,进行不同的处理。 对于WinMain部分,一般都是固定不变的,我们不需要做太多的变动,只是,我们想改变窗口的一些特性时才需要修改,比如,我们想改变窗口的大小、背景色、图标等,我们就需要更改相应的部分,下面我们看看改动的两个主要地方:
? 窗体结构WNDCLASS
typedef struct tagWNDCLASSA { }
WNDCLASSA, * PWNDCLASSA, NEAR * NPWNDCLASSA, FAR * LPWNDCLASSA ;
9
UINT style ;
WNDPROC lpfnWndProc ; int cbClsExtra ; int
cbWndExtra ;
HINSTANCE hInstance ; HICON hIcon ; HCURSOR hCursor ;
HBRUSH hbrBackground ; LPCSTR lpszMenuName ; LPCSTR lpszClassName ;
第二章:WIN32窗体程序设计 ITjob就业培训
在这里提示一下资料型态和匈牙利表示法:其中的lpfn字首代表「指向函数的长指针」。(在Win32 API中,长指针和短指针(或者近程指针)没有区别。这只是16位Windows的遗物。)cb字首代表「字节数」而且通常作为一个常数来表示一个字节的大小。h字首是一个句柄,而hbr字首代表「一个画刷的句柄」。lpsz字首代表「指向以0结尾字符串的指针」。 假如我们定义了WNDCLASS wndcls;
wndcls.style = CS_VREDRAW|CS_HREDRAW;
style窗口类型定义如下:
#define CS_VREDRAW 0x0001 #define CS_HREDRAW
0x0002
#define CS_KEYCVTWINDOW 0x0004 #define CS_DBLCLKS 0x0008 #define CS_OWNDC 0x0020 。。。
由于每个识别字都可以在一个复合值中设置一个位的值,所以按这种方式定义的识别字通常称为「位旗标」。通常我们只使用少数的窗口类别样式。上面用到的这两个识别字表示,所有依据此类别建立的窗口,每当窗口的水平方向大小(CS_HREDRAW)或者垂直方向大小(CS_VREDRAW)改变之后,窗口要完全重画。
WNDCLASS结构的第二个栏位由以下叙述进行初始化: wndcls.lpfnWndProc = WndProc ;
这条叙述将这个窗口类别的窗口消息处理程序设定为WndProc,即消息过程处理函数。这个过程将处理依据这个窗口类别建立的所有窗口的全部消息。在C语言中,像这样在结构中使用函数名时,真正提供的是指向函数的指针。 下面两个栏位用于在窗口类别结构和Windows内部保存的窗口结构中预留一
10