19.1 MDI 的概念

摘录于《Windows程序(第5版,珍藏版).CHarles.Petzold 著》P905

        虽然 MDI 规范从 Windows 2.0 就有了,但是那时写一个 MDI 程序是很难的,需要写很多繁杂难懂的代码。但是,从 Windows 3.0 开始,你要做的大部分工作已经事先做好了。这个改进在 Windows 95 中得到了进一步增强,并随后代入了 Windows 98 和 Windows NT。

19.1.1  MDI 的构成元素

        MDI 程序的主应用窗口和传统程序一样:有标题栏、菜单、大小可调的边框、系统菜单图标以及最大化、最小化、关闭按钮。不同的是,客户区并不直接显示程序输出,这个区域也常称为“工作区”。工作区中可以有多个子窗口(也叫文档窗口),也可以没有子窗口,每个子窗口用于显示一个文档

        这些子窗口的外观和通常的应用程序窗口以及 MDI 程序的主应用窗口很类似。它们也拥有标题栏、可调边框、系统菜单图标和最大化、最小化、关闭按钮,甚至还可以有滚动条。不同的地方在于这些文档窗口自己没有菜单。主窗口上的菜单会应用于这些子窗口

        任何时候只能有一个文档窗口是活动窗口,它的标题栏会呈现为高亮,并且活动窗口会排列在其他文档窗口的上面。所有的文档窗口都被限定在工作区内,不会在主窗口之外显示。

        对 Windows 程序员来说,MDI 初看起来好像很简单直观。只需要为每个文档创建一个 WS_CHILD 窗口,并把程序的主窗口设成它们的父窗口即可。但是随着深入了解现有的 MDI 应用程序,就会发现有些应用程序需要复杂的编程。

  • MDI 文档窗口可以最小化,变成位于工作区底部的一个带图标的小标题栏。通常,MDI 程序的主窗口和每一种文档窗口会使用不同的图标。
  • MDI 文档窗口可以最大化。这时,文档窗口的标题栏(通常用于显示窗口里文档的文件名)会消失,文件名则将附加在其主窗口标题栏的应用程序名之后。它的系统菜单图标会出现在主窗口顶级菜单的最前面。文档窗口的关闭按钮则相应地出现在主窗口顶级菜单的最后面,靠最右端的地方。
  • 关闭文档窗口的系统快捷键和关闭主窗口的快捷键类似,只是用 Ctrl 键替换了 Alt 键。也就是说,Alt+F4 关闭整个程序,而 Ctrl+F4 只关闭当前文档窗口。此外,Ctrl+F6 可以用于在多个子文档窗口之间进行切换。Alt-空格键可以调出主窗口的系统菜单。Alt+-(减号)可以调出当前活动子文档窗口的系统菜单。
  • 通常,使用光标键在菜单上移动时,焦点会从系统菜单转到菜单栏的第一项上。对于 MDI 程序来说,焦点则会从主窗口系统菜单转到活动文档窗口的系统菜单,进而到菜单栏的第一项上。
  • 如果程序能支持多种类型的子窗口(例如 Excel 中的工作表和图表文档),那么菜单要能够反映出与对应文档类型相符的操作。这就需要在切换到一个不同类型的文档窗口时更新菜单。此外,如果没有打开的文档,主窗口菜单则要缩减到只显示必要的操作,如打开或者创建新文档。
  • 顶级菜单栏有一项是【窗口】。根据惯例,它应该是顶级菜单栏中除【帮助】外的最后一项。【窗口】子菜单通常提供用于在客户区中安排文档窗口位置的功能。多个文档窗口可以从左上角开始“堆叠”起来显示,也可以“平铺”显示以便每个文档窗口都能看到。这个子菜单下还有一个列表,包含了所有文档窗口,在其中选取就可以将对应的文档窗口提到前台来。

        所有的这些 MDI 的特性 Windows 98 都支持。当然了,写程序时还是需要一些额外的工作的(后面的范例程序中会看到)。不过,这比起完全自己写代码来支持所有这些要容易得多。

19.1.2  MDI 支持

        在介绍 MDI 支持之前需要先了解一些新术语。主应用程序窗口被称作“框架窗口”。和一般的 Windows 程序一样,这是一个 WS_OVERLAPPEDWINDOW 样式的窗口。

        MDI 程序还会创建一个基于预定义的窗口类 MDICLIENT 的“客户窗口”。客户窗口是通过用这个窗口类调用 CreateWindows 并传入 WS_CHILD 样式创建的。CreateWindow 的最后一个参数是一个指向 CLIENTCREATESTRUCT 结构的指针。创建的客户窗口占据整个框架窗口的客户区,它负责支持大部分的 MDI 行为。客户窗口的颜色使用系统颜色 COLOR_APPWORKSPACE。

        你可能已经注意到,文档窗口也被称为“子窗口”。创建它们需要初始化一个 MDICREATESTRUCT 结构,然后向客户窗口发送一个 WM_MDICREATE 消息,并用一个指针指向这个被创建的结构。

        文档窗口是客户窗口的子窗口,客户窗口则是框架窗口的子窗口。各窗口的父子关系如图 19-1 所示。

图 19-1  MDI 程序窗口的层次结构

        框架窗口需要一个对应的窗口类(和窗口过程),每个类型的子窗口也是一样的。而客户窗口不需要窗口过程,因为它的窗口类已经预先注册好。

        Windows 98 的 MDI 支持包括一个窗口类、五个函数、两个数据结构以及十二个消息。前面已经提到了窗口类 MDICLIENT 和数据结构 CLIENTCREATESTRUCT 以及 MDICREATESTRUCT。五个函数里有两个是用来替代在 MDI 应用程序中的 DefWindowProc 的。对所有未处理的消息,不再调用 DefWindowProc,而是在框架窗口过程中调用 DefFrameProc,在子窗口窗口过程中调用 DefMDIChildProc。另一个 MDI 特有的函数是 TranslateMDISysAccel,它和 TranslateAccelerator 的使用方法一样,后者在第 10 章中已经介绍过。MDI 支持还包括 ArrangeIconicWindows,不过有一个特殊的 MDI 消息使我们可以不用这个函数了。

        第五个 MDI 函数是 CreateMDIWindow,用于在一个独立的执行线程中创建子窗口。在单线程程序中不需要这个函数,接下来我会演示。

        在即将给出的范例程序中,我会演示十二个 MDI 消息中的九个(其他三个不常用)。这些消息都有一个前缀 WM_MDI。框架窗口向客户窗口发送这些消息来进行子窗口的操作或者获取子窗口的信息。(例如,框架窗口向客户窗口发送 WM_MDICREATE 消息来创建子窗口。)WM_MDIACTIVE 消息略有不同。框架窗口可以向客户窗口发送这个消息来激活某个子窗口,而客户窗口既会把这个消息发送给被激活的子窗口,也会发送给从活动状态进入后台的那个子窗口,来通知它们这个变化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Winform MDI是指使用Windows窗体应用程序中的多文档界面(Multiple Document Interface, MDI)功能。MDI允许在一个父窗体中打开多个子窗体,以在一个应用程序中同时处理多个文档或任务。MDI窗体的设置非常简单,只需要将窗体的属性IsMdiContainer设置为True即可。 要在MDI中打开子窗体,需要先创建子窗体对象,并将子窗体的MdiParent属性设置为父窗体,然后调用子窗体的Show方法显示子窗体。例如,可以使用以下代码在MDI中打开Form1窗体: Form1 f3 = new Form1(); f3.MdiParent = this; f3.Show(); 在MDI中,还可以使用MdiLayout枚举值来定义子窗体的布局。具体包括Cascade层叠排列子窗体、TileHorizontal水平平铺子窗体和TileVertical垂直平铺子窗体。这些布局可以根据用户的需求来选择适合的方式来排列子窗体。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [WinForm——MDI窗体](https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/105633316)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [C#winform 之MDI容器](https://blog.csdn.net/qq_57798018/article/details/128232962)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值