Windows精解:窗口类释疑

原创 2006年11月09日 21:52:00

从上一篇我转载如何进行Windows SDK编程开始,我希望可以借此补充一下Windows编程的一些背景知识。之所以这样,是因为在我前面介绍“SW系统的窗口类”时,假设了读者对Windows界面编程已经有一定的了解。

上一篇主要从介绍“如何用”的角度阐述Windows编程。但是我个人习惯“打破沙锅问到底”,很多东西是靠“悟”,而不是“记”。所以这一篇我们聊聊Windows SDK为何会是如今这个样子的。

对于一个经典的WinMain函数,通常包含三步:

  1. 注册窗口类(RegisterClass)。
  2. 创建并显示窗口(CreateWindow and ShowWindow)。
  3. 消息循环(MessageLoop)。即:取得消息 -> 分派消息 -> 处理消息。

窗口程序需要“创建并显示窗口”,这显而易见。关于“消息循环”也容易理解,并且我们在“SW系统简介”中描述已经得非常详细。

我相信最令人迷惑的是:“窗口类”是什么概念?为什么需要RegisterClass?

有人回答:“窗口类”是同类窗口的公共属性,是这一类窗口的共享数据
有人回答:“窗口类”是同类窗口的默认数据(属性)

回答窗口类数据是共享数据的,错误。因为我们知道每一个窗口都有自己独立的菜单、图标、窗口过程(WindowProc,这个最重要了)等等。它们并不存在共享关系。回答是默认数据(属性)的,正确,但没有回答为什么需要默认属性,更没涉及到更为重要的原因。

我们先来看看CreateWindow与CreateDialog的原型:

HWND CreateWindow(
    LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    
int x,
    
int y,
    
int nWidth,
    
int nHeight,
    HWND hWndParent,
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam
);

 

HWND CreateDialog(      
    HINSTANCE hInstance,
    LPCTSTR lpTemplate,
    HWND hWndParent,
    DLGPROC lpDialogFunc
);

为什么普通窗口(Window)的创建不是象对话框(Dialog)一样,直接把窗口过程(WindowProc)传进去,甚至把其他窗口类相关的数据全部直接在CreateWindow时传入?也许有人回答说,这是为了减少CreateWindow的参数个数。——呵呵,我还真不知道怎么去证明这种说法是错的。但是我固执的认为我下面给出的理由要充分些。

听说过序列化(Searialize)技术吗?有读者马上回答:知道,这是MFC中把对象写入磁盘和从磁盘中读入并还原出这些对象的技术。这个回答我给它4分(满分5分)。是的,序列化(Searialize)是对象持久化和还原的技术。但这不是MFC才开始有,而是DOS下Turbo Vision就已经有的一个技术。

对话框是什么?对话框其实是支持了序列化(Searialize)技术的特殊窗口,它在初始化的时候,从资源中还原(创建)出它的各个子窗口。只是,与普通序列化(Searialize)不太一样的是,对象持久化过程不是对话框做,而是对话框编辑器负责的。

无疑,基于对话框进行可视化编程是相当友好的。那么,从支持这种可视化编程的角度来看,我们需要支持序列化(Searialize),需要从磁盘中创建窗口。我们再回头看看CreateWindow函数的原型,你将发现,这些参数是“可序列化(可存盘)”的。而且,你立刻意识到,窗口过程(WindowProc)是不可序列化的。

我们知道,序列化技术需要RuntimeClass技术进行对象的动态创建。而所谓的RuntimeClass技术,无非是建立了类唯一标识(如类名、GUID等)到类创建函数(其他的附属数据是比较次要的)的映射而已。

现在到了关键:为了支持从磁盘还原窗口对象,Windows需要引入窗口类名,并建立它与窗口过程(WindowProc)的映射。——这正是RegisterClass存在的意义。而RegisterClass中其他的窗口类属性是次要的,并且也许前面说得没错,这些属性的存在,只是为了减少CreateWindow函数的参数个数。

补充:点击这里了解RuntimeClass与Searialize的实现机理

补充:“绅士亦花心”提到了GDI资源的共享问题。应当承认,我前面说“窗口类数据是共享数据”这种说法错误,是比较武断的说法。是的,Windows必须面对GDI资源的共享问题,不同窗口亦存在资源共享的事实。更为合理的说法是:每一个窗口可以独立设置自己的菜单、图标、窗口过程,但菜单/图标等GDI资源是可以共享的。因为我们知道,Windows对GDI资源的共享策略是,窗口不拥有GDI资源(菜单/图标等)的所有权,用户必须为GDI资源的生命周期负责。换句话说,窗口只拥有菜单/图标句柄。

BIOS知识精解及问题释疑大全

  • 2013年12月21日 01:57
  • 104KB
  • 下载

【搬家】【Python】Python 中类的绑定方法与非绑定方法释疑

a
  • tiwoo
  • tiwoo
  • 2014年06月18日 16:02
  • 1155

C++Windows窗口编程方法解

  • 2017年11月29日 00:00
  • 190KB
  • 下载

关于Scala子类继承父类属性的问题释疑---子类构造器参数不要与父类属性同名

今天和朋友聊到scala继承的时候,发现有一些问题,我

opencv学习笔记-加载图像(释疑:非mat类与mat类、头文件引用)

以下两种版本代码,亲测可行。 /*********************************** **OpenCV2.4.10测试项目 * xujia *代码包含两种,一种是非m...

windows(3)修改窗口类实现文字的切换

【摘要】这节课的主要内容是将如何修改窗口类,也就是修改一个创建好的窗口类。本节课实现修改我们自己创建的窗口类,来达到闪烁的文字和窗口背景颜色的效果。当然也可以修改系统创建的窗口类。 修改窗口类,系统已...

windows 窗口类类型

windows编程中,调用创建窗口时 CS_BYTEALIGNCLIENT 指定窗口的客户区域距离边界距离(x轴),这个风格会影响窗口的宽度和水平位置显示 CS_BYTEALIGNWINDOW 指定窗...

一个操作windows窗口的类“clsWindow”,使用非常方便!含源码 V2.0

功能描述 clsWindow是VB6环境下使用的一个操作外部程序窗口的类,比如得到窗口句柄,得到窗口里某个文本框的内容。非常方便,使用它可以让您脱身于一堆api函数,功能强大使用简单! 这个类楼主很...
  • sysdzw
  • sysdzw
  • 2013年06月13日 14:55
  • 3585

windows窗口类的封装——内联汇编传this

先贴一段简单的用 Windows Api创建窗口的代码:  #include LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int ...
  • abelx
  • abelx
  • 2014年12月25日 00:35
  • 357
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Windows精解:窗口类释疑
举报原因:
原因补充:

(最多只允许输入30个字)