返回首页


{S0}简介
本文试图解开的许多问题,我一直在询问综合UI应用程序块(问自己)呢??政制事务局。此ACE在微软的模式放大器;实践小组的甲板提供了一个可重用的组件,用于建设复杂,智能客户端的GUI使用最好的(取决于你最好的我猜的定义)的做法的基础框架。从本质上讲,它可以让复杂的图形用户界面使用简单,独立开发,测试和部署的组件。
最初的目标时的WinForms - 尤其是使用C# - 政制事务局现正被更广泛的客户端技术,包括WPF和WPF / E促进当我写在圣诞节后的黑暗和寒冷,一月,在下一个版本中已被暂定为2007年4月宣布的,所以有不长的等待。
希望本文将回答以下问题:这是什么?我为什么要使用它呢?为什么这么复杂?由政制事务局提供哪些位和位我要实施?我该如何使用呢?综合UI应用程序块(CAB)
综合UI应用程序块是创建复杂的GUI框架,模块化的智能客户端应用程序。基本上,它提供了以下内容:一个框架,促进结构化的方法,建立业务线应用程序。独立而互操作模块的动态加载,托管在一个共同的外壳。事件代理松耦合模块和部分模块之间的通信。命令模式的实现。模型 - 视图 - 控制(MVC)模型 - 视图 - 演示者(MVP)模式实现的基类。动态加载的服务的基础设施。例如认证,授权模块的位置,和加载模块。指导包,以纾缓组件的创建。我们应共享一个CAB?
政制事务局主要是为了设计上的使用ca​​sedriven方法的开发团队为基础的业务应用。但是,有没有理由你不应该使用它(孤独的开发者)开发自己的应用。事实上,因为它提供了一个插件框架,它可以让你开发一个应用程序可以在将来添加新的模块,而无需改变主应用程序。
使用一个开发团队构建一个应用程序提出了它自己的特殊问题。团队通常包括:核心开发??建筑师和导致开发商建设的GUI框架,共同服务等设计和编码的业务相关的窗口即执行业务用例的应用程序开发??
团队成员来来去去(并获得由公共汽车运行),因此重要的是,在架构的一致性和免受任何并发症的核心运作应用程序开发。他们可以独立开发,测试和部署他们的模块,并没有太多担心GUI框架本身。 (或与它弄得不好小提琴)。一旦核心开发人员构建的应用程序框架,为应用程序开发人员的学习曲线很短。相反,在核心框架所需的任何变化可能发生(主要是)独立的插件模块。
有必须有已开发的工作一样的CAB建设企业图形用户界面,但如果微软推动政制事务局和最佳做法的看法,它的更容易给我一些他们我通过(无论正确与否GUI框架数百由开发者社区)。(一)CAB成本
是提供一个应用程序开发的绝缘环境的成本。框架的执行情况(CAB应用程序的核心)提供了一个非常广义的机制来处理的事情。在政制事务局的核心是ObjectBuilder的广泛使用依赖注入(又名控制反转)和管道的策略,允许多个操作对象实例化,并准备使用。它也支持通过以相反的顺序执行适当的管道流程控制处理对象实例。这在很大程度上是使用面向方面编程(AOP)和反射,使用上下文属性??所以准备潜入核心的CAB准则。
这使得它很容易简单地标记构造函数,事件处理程序,与相应的属性模块等应用程序的开发者。 (虽然生活是一个小的核心开发强硬!)CAB术语和定义
我不打算太多的细节,否则我会刚刚结束,剽窃其他文本。不过,我将简要总结的基本术语和定义,你会来在这方面和其他物品有关CAB框架跨。
正如我以前说过,政制事务局主要是拟用于开发团队,我会尽力,并指出这些条款的目的是,其职责是执行的那部分。责任有三个不同的领域:政制事务局??提供的CAB框架的一部分。 核心开发(CD)??负责为应用程序框架的开发。应用程序开发人员,AD)??开发商在特定领域的功能或用例工作。
记住,这是唯一代表,但检查材料,以供参考和进一步阅读的链接的网页。请注意各部件之间的关注的明确分离。它的基本的CAB的构造方式,避免了蜘蛛网结构。Shell应用程序(CD)
这是承载该应用程序的容器。它的任务是加载和启动主应用程序壳。壳牌(光盘版)
共同所有的动态加载的模块的主要用户界面的外壳。典型的形式,它始终承载根WorkItem的,这是根访问的所有的服务,模块,和模块注册的WorkItems。工作区(CD)
工作区是一个控制,主要负责控股和显示用户界面元素的WorkItems创建。政制事务局提供了一些标准工作区(标签,MDI,面板等),然而,你可以实现自己的。服务(CD)
服务类封装了客户端应用程序,一个特定的模块或的WorkItems常用的功能。安全和Web服务的访问通常是由服务类处理。模块(光盘公元)
的WorkItems成一个单一的部署单元的逻辑分组是一个模块。这使您可以轻松地分发到现有的应用程序的新的GUI功能。有效的插件。ProfileCatalog(CD)
通常,一个XML配置文件,指定需要加载到应用程序模块和服务。如果你需要从其他地方如加载配置,您可以覆盖默认实现数据库或Web服务。ModuleLoader(CAB)
由政制事务局提供的服务,这是负责加载ProfileCatalog所述的模块。它动态加载程序集,看起来和ModuleInit类进行实例化,如果它被发现。ModuleInit(光盘公元)
每个模块需要ModuleInit的类。这是负责加载模块所需的所有服务的WorkItems和图形用户界面扩展(UIExtensionSite)。UIExtensionSite(CD)
UIExtensionSite是一类菜单,工具条或状态条延长壳牌。WorkItem的(光盘公元)
一个WorkItem是一个类,封装了所有的用例所需的逻辑。从技术上讲,它是一个容器,承载所有的意见和主持人或控制器,状态和命令,如需要的对象。命令(CAB)
A级执行命令模式。政制事务局支持创建手动或声明的命令由命令处理方法的应用[CommandHandler]属性的命令。一个命令,你可以注册多个调用程序。EventPublication
政制事务局提供了一个事件的经纪人,很容易让事件从Module类出版。这提供了一个松散耦合的WorkItems沟通的方式。这是落实使用[EventPublication]标记的属性NET事件。EventSubscription
EventSubscription是一个事件的接收端。希望订阅特定事件的A类只实现了一个事件处理程序 - [EventSubscription]属性标记的一个共同签名的方法。模型/视图/控制器/演示
该模型是一个WorkItem包含业务类和进程。 E.g帐户,客户端。视图是一个用户控件,模型展示给用户,并允许用户修改其内容。控制器/演示链接的模型和视图。政制事务局鼓励MVC或MVP模式,但要么不征收。然而,SCSF是面向一个最有价值球员,并具有向导来生成它们。顺便说一下,PAMP,P女士现在看来是主张作为首选的方法使用WorkItemController。SmartPart
一个SmartPart是另一个[SmartPart]属性标记的一个普通的UserControl的名称。ObjectBuilder的
ObjectBuilder的是一个核心的CAB组件。它基本上是一个用于创建对象需要特定的构建要创建的策略或需要的功能,如被创建时的依赖对象的实例化和初始化的工厂。这是通过使用依赖注入和对象生成器管道。它使用AOP技术,可以通过使用ContextAttributes,使代码可以注射或在运行时更换。这是fundamantal quot;魔术happensquot;成分。智能客户端软件工厂 - SCSF
获取与CAB开始位的使命,有不少你需要做的得到您的应用程序框架内置的几件事情。也创造了新的模块和的WorkItems比它需要更繁琐。 SCSF是VS 2005的扩展,大大简化了这些任务,使用指导包??换句话说向导。它也可以创建自己的自定义指导软件包提供给应用程序开发。因此,让我们建设。
基本上,你有两种选择,以建立一个CAB框架和应用:自己动手从头开始使用智能客户端软件工厂(SCSF)(奇才在老钱)和指导软件包
我选择了从头开始构建一个简单的应用程序,以帮助澄清CAB应用程序是如何构造和使用的各个组成部分结合在一起??SCSF整齐引擎盖下隐藏的东西,我们试图偷看在这篇文章中的引擎盖下。现在有不少的示例应用程序,而不是至少在本文末尾的链接的实验室手中。但谷歌搜索周围,似乎有使用MDIWorkspace没有样品,因此它似乎有用的构建。
我知道,我知道。随着WPF和MDI支持缺乏的到来,因为它呈现的方式只有顶层窗口,MDI可能不是最好的主意。但如果你打算建立一个对​​接框架自定义工作区,它可能是一个良好的开端。
现在,我会抱我的手,现在说这不是一个功能齐全的CAB应用程序,不使用所有由政制事务局提供的设施吗??状态,服务,动态加载模块等,它仅仅是一个例子如何建立一个CAB应用程序恰好使用MDIWorkspace。重点是字简单。 (应用程序,而不是作者)外壳应用程序创建一个新的C#Windows应用程序使用的新建项目向导,并调用它SimpleMDIApp。以下CAB集添加引用。你可以从微软下载或从连接的源和项目文件中提取。

Microsoft.P​​ractices.CompositeUI.dllMicrosoft.P​​ractices.CompositeUI.WinForms.dll Microsoft.P​​ractices.ObjectBuilder.dll重命名的Program.cs以SimpleMDIShellApp.cs替换生成的代码与此。

using System;

using System.Windows.Forms;

using Microsoft.Practices.CompositeUI;

using Microsoft.Practices.CompositeUI.UIElements;

using Microsoft.Practices.CompositeUI.WinForms;

using Microsoft.Practices.CompositeUI.Commands;

using Microsoft.Practices.CompositeUI.Services;



namespace SimpleMDIApp

{

    public class SimpleMDIShellApp : FormShellApplication<WorkItem, 

                                                  SimpleMDIShellForm>

    {

        [STAThread]

        public static void Main()

        {

            new SimpleMDIShellApp().Run();

        }

    }

}


这是最低限度的外壳应用程序,但它需要一个Shell在这种情况下SimpleMDIShellForm - ??提供的菜单,工具栏和工作区。壳牌
重命名现有的,SimpleMDIShellForm.cs产生Form.cs。现在,您可以构建和运行应用程序,但它并不令人兴奋。它只是显示Form1上,但它是在CAB框架中运行。
开放SimpleMDIShellForm.Designer.cs添加一个菜单和状态栏,并改变现有的代码是:{C}
这一切​​基本上是添加一个MenuStrip,StatusStrip和夫妇的MenuItems原始形式代码。它还改变窗体的标题和一些样式。最重要的是所谓fileToolStripmenuItem ToolStripMenuItem。
现在你可以建立,现在运行这个吗??现在它只是一个简单的申请表与无功能菜单和状态条。该模块
虽然这个例子将不使用的模块做任何有用的,我已经包括了它,因为它的重要驾驶室尽量使用它,了解事情发生的顺序。
插入一个新的C#类称为如下SimpleMDIModuleInit:
using System;

using System.Windows.Forms;

using Microsoft.Practices.CompositeUI;

using Microsoft.Practices.CompositeUI.Commands;

using Microsoft.Practices.CompositeUI.SmartParts;

using Microsoft.Practices.ObjectBuilder;



namespace SimpleMDIApp

{

    public class SimpleMDIModuleInit : ModuleInit

    {

        private WorkItem workItem;



        [InjectionConstructor]

        public SimpleMDIModuleInit([ServiceDependency] WorkItem workItem)

        {

            this.workItem = workItem;

        }



        public override void AddServices()

        {

            base.AddServices();

        }



        public override void Load()

        {

            base.Load();

        }

    }

}


这里需要注意的一些有趣的事情。驾驶室ModuleLoader会发现和实例ModuleInit从派生类的一个实例。然后给你机会创造任何公共服务或初始化之前被创建并显示在shell重写AddService和Load方法。政制事务局反映过类,并确定实现这一目标的InjectionConstructor和ServiceDependency属性。模块加载顺序和服务的细节超出了本文的范围。MDI的工作区
完成了壳牌,我们只需要一个工作区??在这种情况下,MDI的工作区。很简单:
namespace SimpleMDIApp

{

    public partial class SimpleMDIShellForm : Form

    {

        private WorkItem m_workItem;

        private IWorkspace m_mdiWorkspace;



        public SimpleMDIShellForm()

        {

            InitializeComponent();

        }



        [InjectionConstructor]

        public SimpleMDIShellForm(WorkItem workItem, 

                 IWorkItemTypeCatalogService workItemTypeCatalog) : this()

        {

            this.m_workItem = workItem;

            m_mdiWorkspace = new MdiWorkspace(this);

        }

    }

}


这增加了一个注入的构造函数(属性),CAB通过反射找到。这就是所谓的,只是之前被创建并显示壳。该构造函数创建一个新成员的MDI工作区和存储工作项。
我们与壳牌和工作区现在几乎已经完成了。我们只需要一种方法来关闭它并创建新的WorkItems(查看/表格)。因此,添加以下命令处理程序,以SimpleMDIShellForm应付这个。
[CommandHandler("FileExit")]

public void OnFileExit(object sender, EventArgs e)

{

    Close();

}



[CommandHandler("FileNewContact")]

public void OnFileNew(object sender, EventArgs e)

{

    ContactWorkItem contactWorkItem = 

           m_workItem.WorkItems.AddNew<contactworkitem />();

    contactWorkItem.Show(m_mdiWorkspace);

}


正如你可以看到,命令处理程序都具有一个共同的签名的方法,标记[CommandHandler]属性标识作为一个字符串命令。我们要创建工作项是所谓ContactWorkItem,这是在OnFileNew命令处理程序中引用。我们将在下一节中创建。
对于这些被调用的方法,我们需要防火命令FileExit和FileNewContact??我们要做壳牌菜单条。修改SimpleMDIShellApp并添加以下两种方法:
protected override void AfterShellCreated()

{

    base.AfterShellCreated();



    // Register the UIExtensionSites

    ToolStripMenuItem fileItem = 

      (ToolStripMenuItem)Shell.MainMenuStrip.Items["fileToolStripMenuItem"];

    RootWorkItem.UIExtensionSites.RegisterSite("FileDropDown", 

                                                  fileItem.DropDownItems);



    AddMenuStripButton(RootWorkItem, "FileNewContact", "New");

    AddMenuStripButton(RootWorkItem, "FileExit", "Exit");

}



private void AddMenuStripButton(WorkItem workItem, string commandName, 

                                string text)

{

    ToolStripButton button = new ToolStripButton();

    button.Text = text;

    button.ToolTipText = text;



    // Add the button to the MainToolBar

    workItem.UIExtensionSites["FileDropDown"].Add(button);



    // Associate the Click event of the button to a command

    workItem.Commands[commandName].AddInvoker(button, "Click");

}


AfterShellCreated是一个重写FormShellApplication的方法称为后壳的形式已创建由政制事务局(相当明显)。我们的实施,得到一个参考的根quot; Filequot;菜单项,注册为quot; FileDropDownquot;和使用我们自己的helper方法AddMenuStripButton关联添加一个菜单项和命令"菜单上,单击"事件相关联的。请注意命令的范围。它们的定义,并在这个文件中添加,但他们接受命令处理程序在SimpleMDIForm。这里的fileToolStripMenuItem字符串是用来参考的文件"菜单上的名称属性。
有很多种方法添加到您的应用程序的菜单和命令。如何在这里完成的是一个非常简单的方法来证明的东西。另一种方法是使用集中定义的命令字符串常量和做UIExtensionSite登记,并在相关的WorkItem的模块菜单/命令工作。您还可以动态加载配置文件基于用户角色和权限的菜单。工作项,视图和控制器
所以现在壳牌和应用程序的完整和核心开发人员的工作已经完成。我们只需要创建一个WorkItem和"窗体"视图显示在MDI工作区??的应用程序开发工作。这代表了我们的应用程序的业务组件,在这种情况下,它只是一种形式,允许用户输入新的详细联系方式。在实践中,这大概也可以用来显示现有的联系人的详细信息以及。
创建一个新的用户控件,称为ContactView.cs,并给它添加一些控件。
生成的代码并修改它是:
using System;

using System.Windows.Forms;

using Microsoft.Practices.CompositeUI;

using Microsoft.Practices.CompositeUI.SmartParts;

using Microsoft.Practices.CompositeUI.UIElements;

using Microsoft.Practices.ObjectBuilder;



namespace SimpleMDIApp

{

    [SmartPart]

    public partial class ContactView : UserControl

    {

        private ContactController controller;



        public ContactView()

        {

            InitializeComponent();

        }



        [CreateNew]

        public ContactController Controller

        {

            set { controller = value; }

        }



    }

}


标准生成的代码和一个CAB启用控制之间的差异是[SmartPart类的属性。智能零件基本上是一个CAB应用程序的可视化组件。此外,这个WorkItem的将使用MVC模式,使控制器属性标记为[CreateNew]属性。驾驶室采用依赖注入连接起来,松散耦合的组件在运行时,在这种情况下查看持有其控制器的参考。
现在创建控制器类叫做ContactController.cs:
using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.Practices.CompositeUI;



namespace SimpleMDIApp

{

    public class ContactController : Controller

    {

        public ContactWorkItem ContactWorkItem

        {

            get { return base.WorkItem as ContactWorkItem; }

        }

    }

}


在这种裸机的例子,此控制器具有的属性,返回其的WorkItem的。
最后一块拼图的WorkItem的本身 - 各种可视和非可视化组件的业务逻辑的类,它封装。创建一个新的类ContactWorkItem:
using System;

using System.Windows.Forms;

using Microsoft.Practices.CompositeUI;

using Microsoft.Practices.CompositeUI.Commands;

using Microsoft.Practices.CompositeUI.SmartParts;

using Microsoft.Practices.CompositeUI.UIElements;

using Microsoft.Practices.CompositeUI.Utility;

using Microsoft.Practices.CompositeUI.WinForms;

using Microsoft.Practices.CompositeUI.EventBroker;

using System.Drawing;



namespace SimpleMDIApp

{

    public class ContactWorkItem : WorkItem

    {

        private static Point pos = new Point(0, 0);

        private ContactView m_contactView;

        private WindowSmartPartInfo m_smartPart;



        public void Show(IWorkspace parentWorkspace)

        {

            m_smartPart = new WindowSmartPartInfo();

            m_smartPart.ControlBox = true;

            m_smartPart.Location = pos;

            m_smartPart.Title = "Untitled - Contact";

            pos = Point.Add(pos, new Size(10, 10));

            m_contactView = Items.AddNew<contactview />();

            parentWorkspace.Show(m_contactView, m_smartPart);



            this.Activate();

        }



        protected override void OnActivated()

        {

            base.OnActivated();

        }



        protected override void OnDeactivated()

        {

            base.OnDeactivated();

        }

        

        protected override void OnTerminated()

        {

            base.OnTerminated();

        }

    }

}    


我们的公共Show方法创建一个视图,并添加到MDI工作区的工作。它实例化一个WindowSmartPartInfo对象,管理智能的部分属性,增添了新(使用泛型)创建ContactView父工作。在这种情况下,它的MDI工作区的SimpleMDIShellForm创建。
显示的方法是所谓SimpleMDIShellForm OnFileNew FileNewContact命令菜单按钮被点击时触发的事件处理程序。要注意的几点:OnActivate和OnDeactivate WorkItem的得到或失去焦点时调用的CAB overridables。OnTerminated(在这种情况下)时调用的应用程序关闭。这取决于你如何管理的WorkItems的使用寿命。静点成员,使新的看法不只是隐藏以前创建的。使用MVC模式,但驾驶室不执行此。事实上,当使用的SCSF,这种方法是最有价值球员。
您现在应该能够建立并运行这一激动人心的应用程序(!)。请记住,这只是一个起点,以了解在一个CAB应用程序组件的结构和组织??在这种情况下,使用一个MDIWorkspace。它不仅触及政制事务局提供的能力,但是一个非常有用的学习锻炼。示例代码所附的示例应用程序是在这篇文章添加了一些代码几乎相同。其中主要使用的配置文件,设置壳牌形式菜单。有四个助手类:ShellItemsSection.csUIElementBuilder.csMenuItemElement.csMenuItemElementCollection.cs
这些都是用于构建从App.config中的菜单,加载服务和模块。
此外,还有更新状态条上的联系人姓名,ContactWorkItem是积极的代码。跳转到结束雏菊
本文已挖成的机制和组件的CAB,以及他们如何在MDI的GUI应用程序可能会使用。希望这有助于理解它是如何可能的松散耦合的GUI组件使用的开发团队和结构化的方法来构建复杂的图形用户界面的智能客户端。一些有用的链接和引用。政制事务局{A}泛型反思依赖注入SCSF GAT / GAX MS模式放大器;实践{A7}AOP {A8}|大卫中号布鲁克斯

回答

评论会员:游客 时间:2011/12/07
感谢伟大的文章!你提到的有关工作项清理/生命周期短暂。我需要学习如何"重置"一个WorkItem的状态,它启动后,在右侧;清理项目中,等我试过手动删除Items集合中的项目,但只是导致问题,所以我"米思想必须有一个CAB的方式来处理清理,我不知道。我搜罗谷歌,但无法找到任何有关此。你知道我在哪里可以看一下,或者你有任何快速提示和如何处理工作项life-cycle/cleanup例子:​​|?米格尔巴罗斯
的文章必须有用。

米格尔巴罗斯 - 开发
{A9}
评论会员:somagunasekaran 时间:2011/12/07
您好,

我使用菜单编辑器运行时的SmartClient厂壳牌形式... ...如果我一次单击文件菜单编辑器的子菜单是新合同Screen.and,如果我点击一个新的合同屏幕..然后显示在标签控制的新合同屏幕... 。但只有一次..

但我想只有在Tab控件一旦打开..如果新合同屏幕子菜单点击AGIN ..但sholud不会再来... ...所以,请该怎么办...请帮我.......{ S2}

关于
Somasundaram G

我要加入的网站
评论会员:rilov 时间:2011/12/07
辉煌职位...很简单..感谢书面方式这样一个很好的文章。

"我没有失败。我只是
发现万的方式,将无法正常工作。"
托马斯爱迪生
评论会员:mathewrajiv 时间:2011/12/07
一个美丽的文章,并解释很漂亮。
所有学分。我想知道,如果你有"上SCSF WPF"一些演示。
评论会员:游客 时间:2011/12/07
kk_upadhyay:如何更改子窗体的MDIFormStatusStrip文字?。
迈克尔同步
评论会员:游客 时间:2011/12/07
如何处理CAB用户的身份验证?我知道有认证服务,包括驾驶室,但我不知道如何使用,以符合我的要求。假设:有两种类型的用户在我的系统调用("normaluser"和"adminuser")。有5个不同的系统模块。adminuser是允许访问每一个模块,normaluser是能够访问只有3个模块。问题是时normaluser登录到系统后注销的adminuser,不得由normaluser访问模块仍然呈现。如果我们停止和重新启动应用程序,那么它的工作原理。我想我可能需要卸载模块,当一个用户登录系统。我想知道如何做到这一点。预先感谢。感谢和问候,迈克尔同步(博客:{A10})如果你想感谢我的帮助我,请投我的消息,点击旁边的数字之一,"此消息"。为什么要投票?PLZ阅读{A11}这里。谢谢。{S3}
玛祖卡舞
评论会员:游客 时间:2011/12/07
我试图按照你的例子,但它似乎对MdiWorkspace代码SimpleMDIShellForm失踪。我到年底findout这个重要的部分是丢失。
大卫布鲁克斯中号
评论会员:游客 时间:2011/12/07
刚检查了这一点,一切似乎都在压缩SRC。我刚下载了一个不同的电脑上,构建并运行得很好。也许被损坏的zip文件下载。如果您仍然有问题,让我知道,我会向您发送电子邮件的zip戴夫
Dominic_roberts1
评论会员:游客 时间:2011/12/07
如何创建一个shell右侧MDI窗口,点击左侧的外壳不同导航菜单。
jbe8224
评论会员:游客 时间:2011/12/07
如果你想有一个左侧导航(也许类似Outlook栏),并在右侧的文件,然后再考虑使用的SDI。SDI允许你更多的控制如何以及在何处的窗口应该显示。像VisualStudio的用户界面与SCSF/CAB的例子可以在这里找到:{A12}
CCESONG
评论会员:游客 时间:2011/12/07
如果我想在不同的模块ContactView,怎么可能壳模块传递MDI的工作区,以Contactview显示。Dockworkspace,Zoneworkspace,Tabworkspace控制可添加到workitem.workspaces。MdiWorkspace不能因为它不是一个控制。
mAreValo
评论会员:游客 时间:2011/12/07
我有同样的问题。这个实现的唯一途径是壳以前知道的工作项目,并在本地启动。但同样,如果工作项目是一个单独的模块,如何将模块知道在其中会显示工作区?{S4}的请原谅我的英语{五}
RTate
评论会员:游客 时间:2011/12/07
缺少源代码附件,以及部分的例子是在"代码"块包裹,所以它看起来很丑陋,是不可读的。这篇文章是一个很好的开始,但尚未东西,我会投赞成票。
大卫Broooks
评论会员:游客 时间:2011/12/07
这是检查和附加SimpleMDIApp_src.zip完成。这可能是你下载被损坏。此外,请记住这是FPORVS2005的。至于代码块。文章的一点是要看到和理解的代码,而不是隐藏它;O)
robinw77
评论会员:游客 时间:2011/12/07
尼斯"间隔"的引用!哦,文章还不错。