探索Win32系统之窗口类(Window Classes in Win32)
Kyle Marsh
Microsoft Developer Network Technology Group MSDN技术组
?
摘要
本文主要介绍win32系统里窗口类的运做和使用机制,探索一些细节问题,使win32窗口类的信息更加明朗化。
在本文中,\类\,\窗口类\这两个术语等同,都不是指C++类,而是指和窗口相关的一组信息的集合。
?
简介
窗口类的风格决定了窗口的外观和风格。所有的窗口都会属于某一个窗口类。在创建一个窗口之前,必须注册(register)一个相应的窗口类。32位Windows操作系统类可以注册被系统里所有的程序所使用的窗口类。
大部分开发人员认为窗口类是个麻烦的东西,他们顶多就是从例子或其他代码中拷贝一个RegisterClass函数,修改一下部分参数而已。这仿佛有些轻视了,没有发挥窗口类的作用。本文将对此进行探索,并且描述窗口类如何的使应用程序得到优化。 我们的将讨论的题目包括:
? ? ? ? ?
什么是窗口类(Windows Classes)
系统全局,应用程序全局,应用程序局部类的区别 类里包含了那些信息
这些信息如何影响窗口的表现 应用程序如何使用窗口类信息。
一:窗口类的类型
window系统提供了三种类型的窗口类
系统全局类(System global classes)
? 应用程序全局类(Application global classes) ? 应用程序局部类(Application local classes)
?
1.系统全局窗口类(System Global Classes)
windows 本身注册了几个系统全局类供全部的应用程序使用,这些类包括了以下的常用标准窗口控件
? ? ? ? ? ?
Listbox (列表框)
ComboBox (下拉组合框) ScrollBar (滚动条) Button (按钮) Static (静态标签) Edit (编辑框)
以及其他不那么常用的控件如TabCtrl等. 还有:
? ? ? ? ? ? ?
菜单窗口 桌面窗口 对话框窗口 任务条窗口
题头带图标的窗口
ComboLBox:ComBoBox控件的下拉列表窗口 MDIClient: MDI风格窗口的子窗口
WindowsNT为DDEML(Dynamic Data Exchange Management Library)增加了DDEMLEvent类,因为DDEML功能已经结合到USER里去了。
Windows 95/98不注册类 #32772,因为它不使用题头带图标风格的窗口(由于我用的是win2k操作系统,这一点没有尝试)
所有的win32应用程序都可以使用系统全局类,但不能增加或删除一个这样的类。 应用程序可以通过“子类化”(SubClassing)这些类来改变系统全局类的属性。在Win32
里,应用程序子类化某个系统全局类只会影响本进程内窗口的表现,而不会影响另外一个进程或应用程序。比起相应的操作会影响其他窗口的win16时代,这是一个进步。
在Win32里,Ms鼓励“子类化”系统类的行为。因为这个技术可以非常有效和方便的改变窗口的表现。例如:如果应用程序希望限制edit控件的输入和编辑行为,可以通过子类化edit类并设置一个新的窗口过程(WindowProc)来自己处理处理键盘操作来实现。子类化以后,此应用程序里创建的edit控件将使用新的窗口过程,以代替标准的edit控件窗口过程。
系统全局窗口类实现
现在的win32平台使系统类和各32位进程互不相干,系统类如何实现的并不会直接影响应用程序。本节将描述系统类的实现,当然,跳过此节并不妨碍全文的阅读和理解。
?
在win9x里的实现
系统全局类在win9x和win3.1的实现使相当相象的。在系统启动时,USER模块创建了系统类。win9x和win3.1不同的是:当发现一个应用程序子类化了某个系统类的时候,win9x将进行如下工作:
如果在debug模式下运行,在debug屏幕上显示一个 warning 信息
? 复制一份被子类化的窗口类的信息 。将复制的新类填加到应用程序的“私有”系统类列表里。win9x系统里,系统为每个进程都保持了这样的一个列表,以供系统存放系统全局类的克隆信息。
? 强制进程里所有的子类化过的窗口实例使用这个系统类的拷贝。但这不影响已经存在的窗口,窗口是使用事先已经拷贝到窗口实例数据区的类信息,并非直接使用进程里保存的类的信息。子类化只更新了进程的窗口类列表里的类的信息,而没有更新窗口实例里的类。
?
16位应用程序共享相同的进程空间。在win9x里,16位程序的表现和它在win3.1里是一样的。
?
winNT的实现
winNT则有很多的不同。winNT包括了两个win32子系统:一个服务进程和一个在各
win32进程里运行的动态连接库(DLL)。以edit类为例,winNT在各进程空间里,从DLL里导出和注册edit类。这样,处理EDIT控件的代码可以存在于DLL里,也即在各进程空间里。不需要系统分配局部过程调用来处理Edit控件,应用程序对控件的频繁调用所导致的系统开销也被避免了。因为EDIT 控件实例仅仅在各进程空间里操作自身数据,所以对系统鲁棒性的冲击就降低了。
服务进程管理每个win32应用程序的信息,包括应用程序的公有和私有窗口类。当创建一个win32线程的过程开始(即某个线程调用USER模块或GDI模块的函数时),USER模块检查该线程是否该进程的第一个线程,如果是(一般是主线程),USER模块为该进程注册系统类。当为了任何一个进程而注册一个类(服务模块进程除外),该类就会添加到该进程的公有或私有列表里。为了提高效率,windows为每个进程都注册系统类,并且把类信息的拷贝储存在应用程序的空间里。这增加了鲁棒性,但是比起Windows95,增加了需要使用的内存。windowsNT也由此获得了更高的性能,因为当子类化一个系统类的时候,winNT不需要象window95那样重新分配内存和拷贝类信息。
在winNT里,16位的应用程序依然共享同一进程,也共享所有的系统全局类。16位程序总是不稳定因素的起源。 2.应用程序全局类。
应用程序全局类是注册的时候指定了CS_GLOBALCLASS标志的类(该标志还有后续叙述)。
16位系统比如win3.1的应用程序“全局”类是真正意义的“全局”的,一个DLL或应用程序注册的应用程序全局类,系统内所有的DLL和应用程序都可以使用。一个应用程序全局类在“全局”的意义上和系统全局类一致,只是它是由应用程序创建的而不是系统创建的而已。
Win32的应用系统全局类本质的不同是:应用程序全局类只是在进程内部的“全局”而已。这是什么意思呢?一个DLL或.EXE可以注册一个类,这个类可以让在相同的进程空间里其他.EXE和DLL使用。如果一个DLL注册了一个非应用程序全局类的窗口类,那么,只有该DLL可以使用该类,同样的,.EXE里注册的非应用程序全局类也适用这个规则,即该类只在该.EXE里有效。
作为这个特性的扩展,win32有一项技术,允许一个第三方窗口控件在DLL里实现,然后把这个DLL载入和初始化到每个Win32进程空间里。这项技术的细节是,把DLL的名字写入注册表的指定键值里:
HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows\\APPINIT_DLLS
这样当任意一个win32应用程序加载的时候,系统也同时将该dll加载到进程空间里(这可能有点过于奢侈,因为很多win32程序不一定会使用该控件)。DLL在初始化的时候注册应用程序全局类,这样的窗口类就可以在每个进程空间的.EXE或DLL里使用了。这个技术基于win32系统的这个特性:允许在每个进程空间里自动的(也是强制的)加载特定的DLL(事实上,这也是打破进程边界,把你的代码切入到其他进程里的一种办法)。
3. 应用程序局部类
WIN32应用程序局部类是使用最频繁的类(绝大部分的应用程序为主窗口注册的类都是应用程序局部类),仅仅在声明和注册该类的应用程序模块或DLL自身里使用。注册一个应用程序局部类和应用程序全局类的区别是,局部类不包括CS_GLOBAL CLASS标志。
二:窗口类包含的信息和作用
窗口类都包含些什么信息呢?让我们看以下窗口类结构体。 WNDCLASS结构包含的是一般的窗口类的信息
typedef struct tagWNDCLASS { UINT style;
WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor;
HBRUSH hbrBackground; LPCSTR lpszMenuName; LPCSTR lpszClassName; } WNDCLASS; 成员 style lpfnWndProc cbClsExtra cbWndExtra hInstance hIcon hCursor hbrBackground lpszMenuName lpszClassName 描述 一组标志位的组合。定义比如窗口位置,设备上下文(DC)分配,双击的处理等特征。 指向窗口过程的地址,该窗口过程负责处理窗口类相应的窗口消息 指明需要额外分配的内存数量,单位为byte,系统为该类分配保留指定数量的额外内存 指明需要额外分配的内存数量,单位为byte,系统为每个该类所对应的窗口实例分配保留指定数量的额外内存 标识注册该类的DLL或应用程序实例 当一个属于该类的窗口被最小化的时候,显示的图标. 属于鼠标该类的窗口里显示的指针 定义当程序打开或重画某个属于该类的窗口是,填充窗口客户区的颜色和样式 如果没有显性定义菜单时,窗口的默认菜单 字符串的类名 以下详细讨论各成员的具体意义:
?
Class Styles (style)
Style成员决定了从该类创建出来的窗口的风格,可以使用下列值的一个或几个的组合。 CS_BYTEALIGNCLIENT ,CS_BYTEALIGNWINDOW
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库探索Win32系统之窗口类(Window Classes in Win32)在线全文阅读。
相关推荐: