一千个是什么 - Windows窗口、控件和对话框
2008-11-10 21:14
387 查看
Windows应用程序是通过窗口(Window)、控件(Control)和对话框(Dialog Box)来和用户交互的,Windows系统预定义了很多基本的交互行为和外观,也预定义了很多共用的控件和对话框,让应用程序开发者更容易开发出一致的、标准的交互界面,降低最终用户的学习曲线,并提高用户体验。
MFC(Microsoft Foundation Classes)是对Windows API的一套封装,特别是和Visual Studio的结合,它曾一度简化了Windows应用程序的开发,风靡一时。
随着技术的不断发展,Windows原有的一套界面技术已经逐渐被.NET Windows Forms或WPF(Windows Presentation Foundation)取代,但窥探其中的一些基本概念和机制,对维护遗留系统和理解新的技术,都是有一定积极作用的。
窗口是什么?窗口类又是什么?
窗口是Windows系统中基本的界面元素,由线程来创建。窗口的创建通过CreateWindow()或CreateWindowEx(),需要提供一个窗口类的名字,标明该窗口属于特定的窗口类。窗口类定义了一些共有属性,包括图标(Icon)、窗口的风格(Window Style)、消息处理函数(Window Procedure)等。窗口类需要先通过RegisterClass()注册到系统中,而窗口类的使用范围也是有区别的,分为Application Local、Application Global和System Defined,系统查找窗口类的顺序也是如此。
Windows控件、对话框、窗口的关系是什么?它们的本质区别是什么?
Windows系统启动以后会启动桌面(Desktop Window),这是Windows系统实现的,当应用程序启动时一般会创建一个窗口,它包含标题栏(Title Bar)、菜单(Menu),边框(Border)等等,这个窗口常常被称为主窗口(Main Window)。
当然应用程序还需要创建很多别的窗口来完成用户交互,比如对话框,而对话框往往又包含很多控件。
控件和对话框从本质上说都属于窗口,或者可以理解成窗口的子类。
窗口分为以下这几个类型:
Overlapped Window
Pop-up Window
Child Window
Layered Window
Message-only Window
其实主窗口就属于Overlapped窗口,而对话框属于Pop-up窗口,控件属于Child窗口。
反应在程序上就是对应于不同的窗口风格(Window Style):WS_OVERLAPPED, WS_POPUP, WS_CHILD。
窗口之间的关系?窗口之间的消息路由是怎样的?
窗口有一个父窗口(Parent)属性,一个窗口只能有一个父窗口。
在创建窗口时如果不指定父窗口那么这个窗口就是顶层的窗口(Top-level Window)。主窗口应该是一个顶层窗口,它会和Windows系统的任务栏(Task Bar)绑定,在任务栏显示其图标和标题,同时只有一个窗口处于激活状态,称为激活窗口(Active Window)。
而对于激活窗口内,包括其所有子窗口的在内,只会有一个窗口拥有焦点(Focus),拥有焦点的窗口是当前响应消息的窗口。
而通常,主窗口可能会拥有某些对话框,对话框又包含一些控件。控件是Child窗口,所以一定属于某个父窗口。所以的窗口都有自己的消息处理函数(Window Procedure),所以当拥有焦点的窗口处理消息时,它可以选择是否通知父窗口。一般来说消息是不会发送到父窗口的,除非这个控件的状态是Disable的,其父窗口负责处理消息并决定是否Enable这个控件。
控件从何而来?如何创建控件?
Windows系统预定义了很多类型的控件,包括按钮(Button)、文本框(Edit)、树视图(Tree View)等,这些被称为公共控件(Common Controls),它们被定义在Comctl32.dll中,并且其版本也一直在更新。
可以想象对每一种控件Windows系统都注册了特定的窗口类,在创建控件时只要指定窗口类名称即可,比如按钮的窗口类名称为“Button”。
对话框从何而来?如何创建对话框?
Windows系统实际没有为对话框定义多种窗口类,它其实是一种容器(Container),多变的是它管理的控件。但是,Windows系统却预定义和很多基本功能的对话框,比如打开文件、打印、提取日期时间等等。
Windows系统对对话框提供了一定的封装,创建对话框有两类函数:DialogBox()和CreateDialog()。
这两类函数分别创建模态对话框(Model Dialog Box)和非模态对话框(Modeless Dialog Box)。模态对话框创建后,要求用户完成特定任务后才能返回先前的窗口,比如打印设置对话框,而非模态对话框允许用户切换回原来的窗口但它还是浮动在最上方,比如查找对话框。
在创建对话框时,还需要提供两个重要的参数,一个是对话框模板(Template),另一个是对话框的消息处理函数(Dialog Box Procedure)。
先看看模板,其实就是所谓的资源(Resource)。它其实就是一段二进制数据,用来描述对话框的一些属性和其中包含的控件,创建对话框的函数根据这些数据创建相应的对话框和控件,通过定义资源,可以简化创建对话框的编码工作,同时比较容易维护。
在编辑资源时,微软为其定义了一套语法,通过文本的方式定义,当然借助IDE可以通过图形化的方式生成这些文本。最后编译器会将资源文本编译成资源文件并链接到模块中(Module)。除了这种方式,对话框的模板也可以动态的在内存中生成。
再来看看对话框处理函数,它和窗口处理函数有什么区别呢?这里只是另一种封装,对话框是一种窗口也有自己的窗口处理函数,不过系统预实现了这个函数来调用对话框的处理函数。在对话框处理函数中,如果一个消息得到处理则返回TRUE,否则返回FALSE,这是窗口处理函数会再处理这些消息。
一般来说对话框处理函数中仅处理WM_INITDIALOG,WM_COMMAND,WM_PARENTNOTIFY, 和Color Change等消息,很多消息都由窗口处理函数的默认实现处理了。
资源还有其他什么类型?
资源其实就是一段二进制数据,可以是自定义的任何内容。常见的资源有:图标(Icon),光标(Cursor),菜单(Menu),对话框(Dialog Box),字符串表(String Table),加速键(Accelerator),版本信息(Version)等等。
可以用FindResource()来定位资源,LoadResource()来加载资源,也有一些特定的函数比如LoadMenu()、LoadString()等来处理特定的资源。
如何修改窗口的处理函数?
窗口创建后,消息处理函数的地址会被拷贝到窗口对象的本地来。因此,可以通过SetWindowLongPtr()来针对窗口的实例,而SetClassLong()可以改变窗口类的处理函数地址。
同时,也可以通过GetClassInfo()获得预定义的窗口类信息,从而通过修改来进行特化。可以用来改变默认的控件或对话框属性。
--------------------------------------------------
参考资料:
Windows 游戏编程大师技巧 (第一卷)[André LaMothe]
Win32 and COM Development: User Interface [MSDN]
相关文章推荐
- windows 窗口创建,消息泵,对话框,控件常用API
- Windows编程基础--第8节 MFC对话框控件访问的七种方法(上)
- 对话框控件被窗口背景遮挡住的问题
- UDP协议做的windows窗口聊天程序---此处是单向的"同步"多线程对话框通信
- windows moblie wtl 从CStdDialogImpl继承的窗口,domodal出来,任务栏中的叉,点了叉不知道触发了什么事件。临时解决办法,隐藏它
- VB6.0 在代码中直接调用 文件打开对话框,不使用windows控件
- 获得窗口(对话框)中的所有控件
- C++windows内核编程笔记day09_day10,对话框和窗口基本控件等的使用
- Windows常见窗口样式和控件风格
- 修改对话框中所有控件的窗口样式
- Windows程序设计 读书笔记 - 子窗口控制(控件)。
- MFC中,如何获得对话框控件相对于父窗口(对话框窗口)的位置 及Invalidate(TRUE)的闪屏问题
- 对话框与子窗口之间的切换,以及如何卡入到控件里
- ATL编写的带窗口的控件,无论VC6(ATL3.0) VC7.1(ATL7.0) 在Windows 7 或 Server 2008 下,WinForm调用时发生的问题
- vc6代码实现: 怎样判断一个点是否在一个窗口(或对话框或控件)内?
- Windows常见窗口样式和控件风格
- MFC基本对话框中,窗口最大化后,子控件也等比例放大!
- Windows常见窗口样式和控件风格
- Xceed Docking Windows for .NET 是一款窗口停靠和浮动、窗口自动隐藏、窗口分组控件
- FAQ2:Windows下拦截其他进程弹出的对话框该用什么钩子?