• 从DWG到XAML (III) – .NET中的 XPS Packaging类库及一个DWFx Packaging类库的实现 (源码)


    导读

    DocumentViewer

          其实复杂的事情原本可以很简单. 你想要的那个轮子, 也许别人早就为你造好了. 在这里也是如此. 比如全部你想要的, 就是在你的系统前端可以直接查看DWG文件, 那么全部需要做的, 仅仅是简单的从DWG导出为DWFx文件, 然后使用WPF的DocumentViewer控件打开这个文件就可以了. 这个示例程序可以从这里获取.

    XAML
    1.  <DocumentViewer Name="docViewer" />
    Code-Behind : Load DWFx
    1.  XpsDocument xpsDocument = null;
    2.  
    3.  if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    4. {
    5.      // If there's an existing document open, close it.
    6.      if (xpsDocument != null)
    7.          xpsDocument.Close();
    8.  
    9.      // Create an XpsDocument for the file specified by the user.
    10.      try
    11.     {
    12.          xpsDocument = new
    13.              XpsDocument(dlg.FileName, System.IO.FileAccess.Read);
    14.     }
    15.     catch (UnauthorizedAccessException)
    16.     {
    17.         System.Windows.MessageBox.Show(
    18.             String.Format("Unable to access {0}", dlg.FileName ) );
    19.         return;
    20.     }
    21.  
    22.     // For optimal performance the XPS document should be remain
    23.     // open while its FixedDocumentSequence is active in the
    24.     // DocumentViewer control.  When the XPS document is opened
    25.     // with the XpsDocument constructor ("new XpsDocument" above) a
    26.     // reference to it is automatically added to the PackageStore.
    27.     // The PackStore is a static application collection that contains
    28.     // a reference to each open package along the package's URI as
    29.     // a key.  Adding a reference of the XPS package to the
    30.     // PackageStore keeps the package open and avoids repeated opens
    31.     // and closes while the document content is being accessed by
    32.     // DocumentViewer control.  The XpsDocument.Dispose() method
    33.     // automatically removes the package from the PackageStore after
    34.     // the document is removed from the DocumentViewer control and
    35.     // is no longer in use.
    36.     docViewer.Document = xpsDocument.GetFixedDocumentSequence();

          DocumentViewer是WPF专为呈现XPS文件内容准备的控件. 它所呈现的内容叫做FixedDocument, 这完全符合XPS的标准. 我们的DWFx格式文件是与XPS兼容的, 所以也可以被DocumentViewer直接载入和显示.我们用DocumentViewer直接打开一个DWFx文件并仔细对比, 你会发现它所呈现出来的内容和在AutoCAD中精确地相同.

    Captu3re      这一特点, 取决于DWG文件导出到DWFx文件的过程中所采取的处理方式. 在转化的过程中, 所有的图形地理信息, 包括直接描述和图块信息引用, 都被原地还原被进行相应的变换(比如旋转, 缩放), 然后将最终的图形信息全部写入到FixedPage文件中. 采取这样的行为, 保证了转换前后的呈现精确问题, 并且这种精确性的实现不依赖于转换后容器的特性.

          凡事有一利必有一弊. 这里面有个问题.  我们知道, 如果我们手里有图形的原信息, 有变换公式, 那么我们很容易就能得到变换后的图形. 反之, 如果我们有变换后的图形和变换公式, 虽然可能麻烦一些, 但是大多数情况下我们能得到图形的源信息. 但是, 如果我们有图形的源信息和变换后的图形, 那么在大多数情况下猜测变换公式是极其困难的; 如果我们仅有变换后的图形, 那么还愿图块的图形信息引用, 是根本不可能的. 现在我们得到的DWFx这个包, 就让我们处在了这个比较囧的处境中 - 我们有变换后的图形信息(都在FixedPage中), 除此之外, 关于图形的一切其他细节, 比如它是经过什么变换来的, 它和另外一个图块是不是同一类图形等这些信息, 什么都没有了.

    好吧, 这实在是够麻烦的. 不过我们可以有一些折中的办法, 比如, 在设计时, 相同的图块, 我们给它定义一些自定义属性,来标记这些图块原本指代了同一类实体, 比如都指代了电脑. 我们有这些自定义属性就够了. 自定义的属性是可以被获得的, 这些属性都保存在DWFx包中的Object definition file文件中.

    自定义属性才是这个系统能够自动化的关键!

          比如我们要建设一个网吧自动管理系统. 我们的DWG文件就是包括电脑摆放位置在内的网吧布局设计. 我们的期待能交互的实体是DWG文件中摆放的一台台电脑. 我们期待这个管理系统能自动读入DWG/DWFx文件来表示网吧电脑的陈列位置, 然后我能在这些电脑上点击选择操作, 比如杀毒, 比如下载设置文件等. 要达到这个目的, 我们依赖自定义属性就可以了. 我们可以要求设计厂商在DWG文件中对每一台电脑加上一个电脑编号. 到我们的系统中, 我们可以读出这个自定义属性, 从而实现自动化. DWG/DWFx文件标示了实体的位置, 自定义属性标示了实体的唯一标记并实现系统的互动.

          上一篇文章已经详细分析了DWFx包内各个文件的含义. 所以读取这些文件的内容是相对容易的. 不过看起来, 我们首先需要一个标尺类库, 来标示我们应该如何去读取,怎么读.

    XPS Packaging类库

          .NET Framework在System.Windows.Xps.Packaging命名空间下, 提供了一系列的类型和方法来帮助我们显示和操作XPS文档. 虽然我们的DWFx文件格式上兼容XPS, 但是显然XPS Packaging这个类库是Generic的, 是为所有的XPS文件设计的, 所以不太可能使用这个类库来直接操作我们的DWFx文件内容(从上文的文件内部组织形式也能体现这种差异). 不过作为微软提供的类库, 它应该是我们想要实现的DWFx类库的最好的标杆.

          您可以从这个链接来查看和学习XPS Packaging类库: http://msdn.microsoft.com/en-us/library/system.windows.xps.packaging.aspx. 可以注意的几个类是XPSDocument, xxxSequenceReader/Writer, xxxDocumentReader/Writer, xxxPageReader/Writer. 聪明的你一定注意到了, 这几个类的名字几乎正好对应了上文分析的XPS文档的组织形式. 所以如果我们来写DWFx Packaging Library, 也要清楚的显示出DWFx文件内部的层次形式.

    DWFx Packaging & Converting Library的实现

          废话不多说了, 点击这里下载笔者创建的一个DWFx Packaging & Converting 类库的实现. 这个类库一共包含了4个项目:

    Captur23e JeffreySun.Dwfx : 基础项目, 包含了一些DWFx的基本信息, 以及错误处理等;

    JeffreySun.Dwfx.Packing : Packaging类库, 实现读取DWFx文件包内容的功能;

    JeffreySun.Dwfx.Converting : Converting类库, 将读取的DWFx文件包内容链接并转化为XAML + 自定义属性

    JeffreySun.DWFX2XAMLConverter : 一个简单的示例程序.

     

          您一定要注意这段重要声明! 这一类库仅以学习目的发布, 你可以在你的项目中直接使用, 但是作者不保证该类库的完整性, 也不保证该类库中没有问题, 并且不提供任何技术支持. 作者强烈建议您在研究DWFx格式规范后实现自己的DWFx类库.

    至少, 您得改一下类库的名字吧...不然老板会踢你的屁股的 :)

    作者:Jeffrey Sun
    出处:http://sun.cnblogs.com/
    本文以“现状”提供且没有任何担保,同时也没有授予任何权利。本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    解决软件卸载时Abstract: "Invalid serial number" xe4
    Delphi 数据类型列表
    delphi self.Update 什么作用
    delphi之完美Splash方案(在TfrmMain.FormCreate里不断调用TfrmSplash显示加载进度文字,并且及时Update显示)
    H5单页面架构:自定义路由 + requirejs + zepto + underscore
    H5单页面架构:backbone + requirejs + zepto + underscore
    H5单页面架构:requirejs + angular + angular-route
    基于angularJS和requireJS的前端架构
    单页面应用SPA架构
    自动化前端项目构建
  • 原文地址:https://www.cnblogs.com/sun/p/1656340.html
Copyright © 2020-2023  润新知