最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c# 基于wpf,開發(fā)OFD電子文檔閱讀器

 更新時間:2021年03月08日 10:16:55   作者:源之緣  
這篇文章主要介紹了c# 如何基于wpf,開發(fā)OFD電子文檔閱讀器,幫助大家更好的理解和學(xué)習(xí)使用c#的wpf技術(shù),感興趣的朋友可以了解下

前言 

OFD是國家標(biāo)準(zhǔn)版式文檔格式,于2016年生效。OFD文檔國家標(biāo)準(zhǔn)參見《電子文件存儲與交換格式版式文檔》。既然是國家標(biāo)準(zhǔn),OFD隨后肯定會首先在政務(wù)系統(tǒng)使用,并逐步推向社會各個方面。OFD是在研究當(dāng)下各類文件格式后,推出的標(biāo)準(zhǔn),有如下優(yōu)點:

1 產(chǎn)權(quán)屬于自主產(chǎn)權(quán)

2 具有便攜性:文件小,可壓縮比率大。測試顯示生成的文件體量比PDF還要小。

3 具有開放性:易于入門,對于使用者來說更具開放性。

4 具有擴(kuò)展性:預(yù)留了可擴(kuò)展入口和自定義標(biāo)引,設(shè)置了非接觸式引用機(jī)制,為特性化提供支持。

5 呈現(xiàn)效果與設(shè)備無關(guān),在各種設(shè)備上閱讀、打印或印刷時,版面固定、不跑版。

6 應(yīng)用廣泛:無論是電子商務(wù)、電子公務(wù),還是信息發(fā)布、文件交換,檔案管理等都需要版式文檔的技術(shù)支持。

  關(guān)于標(biāo)準(zhǔn),我也要吐槽一下。OFD標(biāo)準(zhǔn)是國內(nèi)幾家專業(yè)的電子文檔處理公司參與起草的;標(biāo)準(zhǔn)文檔(注:以下用”標(biāo)準(zhǔn)”特指OFD標(biāo)準(zhǔn))只有126頁,在我看來,標(biāo)準(zhǔn)對技術(shù)細(xì)節(jié)的描述過于簡單,沒有一定的技術(shù)背景很難看懂。與此形成鮮明對比的是pdf標(biāo)準(zhǔn),有1000多頁。我在網(wǎng)上也沒找到文字版的標(biāo)準(zhǔn),特別不利于閱讀和參考。

ofd閱讀器程序(已集成了轉(zhuǎn)圖、轉(zhuǎn)PDF功能)下載。

  我最近一直研究ofd標(biāo)準(zhǔn),試圖寫一款閱讀器,已初有成果。具有ofd轉(zhuǎn)換為pdf、轉(zhuǎn)為圖片等特色功能。界面如下:

 本文就把我開發(fā)的過程做簡單介紹。

OFD標(biāo)準(zhǔn)簡介

  簡而言之,OFD存儲是采用壓縮技術(shù),描述采用XML格式。這一點與微軟的word文檔(docx)格式很類似。標(biāo)準(zhǔn)可能參考了微軟的處理方式;在技術(shù)上也要實事求是,國標(biāo)這種格式不是獨創(chuàng)和領(lǐng)先的。將OFD格式文件解壓后,會看到如下目錄和文件:

文件中會包括資源文件(圖片、字體庫等)。XML會對資源存放,圖元(文字、圖像等)顯示做描述,閱讀軟件會根據(jù)這些描述呈現(xiàn)出一致的顯示效果。

開發(fā)OFD閱讀軟件步驟

  國內(nèi)流行的ofd閱讀軟件應(yīng)該是福昕和數(shù)科開發(fā)的,這兩款我都用過。我還要吐槽一下:

  1)福昕閱讀器幫助文檔是ofd格式,但是無法用數(shù)科的閱讀器打開。

  2)有些ofd文檔中xml標(biāo)記,在標(biāo)準(zhǔn)中找不到,是某些公司獨創(chuàng)的?

  這些軟件都是用C++開發(fā)的,用到了QT。同樣情況下,相比于C#,C++開發(fā)軟件難度肯定會大增。在windows平臺開發(fā)界面,WPF應(yīng)該是最好的庫了。WPF雖然出現(xiàn)十幾年了,大家好像對此還很陌生。主要現(xiàn)在是BS的天下;不是WPF不夠好,是生不逢時。

1 對OFD文件解壓縮

  OFD文件其實就是壓縮文件,解壓后的文件也有目錄結(jié)構(gòu)。該模塊的功能是獲取每個文件的路徑和數(shù)據(jù)。

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;

namespace WpfOfdReader.OfdFileType
{
  class OfdFileReader
  {
    ZipArchive _zipArchive;
    public void ReadZipFile(string fileName)
    {
      _zipArchive = ZipFile.OpenRead(fileName);
    }

    public void Close()
    {
      if (_zipArchive != null)
        _zipArchive.Dispose();
    }

    public List<OfdFileItemInfo> AllFileItem
    {
      get
      {
        return _zipArchive.Entries.Select(o => new OfdFileItemInfo(o)).ToList();
      }
    }

    private ZipArchiveEntry GetArchiveEntry(ZipFilePath path)
    {
      foreach (ZipArchiveEntry entry in _zipArchive.Entries)
      {
        if (entry.FullName == path.FulleName)
        {
          return entry;
        }
      }
      return null;
    }

    public static byte[] GetFileBuffer(ZipArchiveEntry entry)
    {
      List<byte[]> listBuffer = new List<byte[]>();
      using (Stream s = entry.Open())
      {
        while (true)
        {
          byte[] buffer = new byte[10];
          int n = s.Read(buffer, 0, buffer.Length);
          if (n <= 0)
            break;

          if (n == buffer.Length)
          {
            listBuffer.Add(buffer);
          }
          else
          {
            Array.Resize(ref buffer, n);
            listBuffer.Add(buffer);
            break;
          }
        }
      }

      int totalLen = 0;
      listBuffer.ForEach(o => totalLen += o.Length);
      byte[] result = new byte[totalLen];
      int index = 0;
      foreach (byte[] buffer in listBuffer)
      {
        Buffer.BlockCopy(buffer, 0, result, index, buffer.Length);
        index += buffer.Length;
      }
      return result;
    }
  }
}

2 找到需要展示的page

  順著路線 OFD.xml --> Document.xml --> Pages,找到最終需要展示的page頁。Page頁包含三類節(jié)點:PathObject、ImageObject,暨對應(yīng)標(biāo)準(zhǔn)中的三類圖元。需要對這三類節(jié)點建模。這三個類共同繼承父類PageObject。所有的圖元都有繪制區(qū)域、坐標(biāo)變換、裁剪等共性,所有這些由PageObject類處理。

  public class PageObject
  {
    public string ID { get; set; }
    public PageLayer ParentLayer { get; set; }
    public string PageFileLoc => ParentLayer.ParentPage.PageFileLoc;

    XmlNode _xmlNode;

    public string Boundary { get; set; }
    public string CTM { get; set; }

    public OfdClipsGroup ClipsGroup { get; set; }

    public void SetPageObject(PageLayer layer, XmlNode xmlNode)
    {
      _xmlNode = xmlNode;

      ID = XmlHelper.GetXmlAttributeValue(xmlNode, "ID");
      ParentLayer = layer;

      Boundary = XmlHelper.GetXmlAttributeValue(xmlNode, "Boundary");
      CTM = XmlHelper.GetXmlAttributeValue(xmlNode, "CTM");

      foreach (XmlNode childNode in xmlNode.ChildNodes)
      {
        if (childNode.Name == OfdClipsGroup.XML_Name)
        {
          ClipsGroup = OfdClipsGroup.FromXml(childNode);
          break;
        }
      }

    }

    public string GetAttributeValue(string name)
    {
      string result = XmlHelper.GetXmlAttributeValue(_xmlNode, name);
      return result;
    }

  }

3 創(chuàng)建WPF顯示模型

圖像精確定位需要用到Canvas控件作為容器。繪制大量圖形需要用到輕量級繪制模型DrawingVisual。在此基礎(chǔ)上,派生了繪制基礎(chǔ)模型OfdVisual,此模型對應(yīng)PageObject。 

  public class OfdVisual : DrawingVisual
  {
    public OfdVisual()
    {
    }

    protected DrawingCanvas _drawingCanvas;
    public DrawingCanvas DrawingCanvas
    {
      get
      {
        return _drawingCanvas;
      }
    }

    public bool IsAddToCanvas
    {
      get
      {
        return _drawingCanvas != null;
      }
    }


    internal void AddToCanvas(DrawingCanvas drawingCanvas)
    {
      if (_drawingCanvas == drawingCanvas)
        return;
      _drawingCanvas = drawingCanvas;
      _drawingCanvas.AddVisual(this);
    }

    public void ReomveFromCanvas()
    {
      if (_drawingCanvas != null)
      {
        _drawingCanvas.DeleteVisual(this);
      }
    }

    public virtual void Show(bool visiable, bool even = false)
    {

    }

    public Point BoundaryLocation { get; set; }
    public Size BoundarySize { get; set; }

    public MatrixTransform ObjectTransform { get; protected set; }

    public VisualClipsGroup ObjectClipsGroup { get; protected set; }
    public void SetPageObject(PageObject pageObject)
    {
      OfdHelper.ParseBoundary(pageObject.Boundary, out Point location, out Size size);
      BoundaryLocation = location;
      BoundarySize = size;

      if (!string.IsNullOrEmpty(pageObject.CTM))
      {
        ObjectTransform = OfdHelper.OfdTextToTransform(pageObject.CTM);
      }

      if (pageObject.ClipsGroup != null)
      {
        ObjectClipsGroup = new VisualClipsGroup() { ClipsGroup = pageObject.ClipsGroup };
      }
    }

    protected Rect ClipRect
    {
      get
      {
        return new Rect(0, 0, BoundarySize.Width, BoundarySize.Height);
      }
    }

    protected RectangleGeometry ClipGeometry
    {
      get
      {
        RectangleGeometry geometry = new RectangleGeometry(ClipRect);
        return geometry;
      }
    }


    protected void PutBoundary(DrawingContext dc)
    {
      TranslateTransform translateBoundary = new TranslateTransform(BoundaryLocation.X, BoundaryLocation.Y);
      dc.PushTransform(translateBoundary);
      dc.PushClip(ClipGeometry);
    }

    protected void PopBoundary(DrawingContext dc)
    {
      dc.Pop();
      dc.Pop();
    }

    protected void PutTransform(DrawingContext dc)
    {
      if (ObjectTransform != null)
      {
        dc.PushTransform(ObjectTransform);
      }
    }

    protected void PopTransform(DrawingContext dc)
    {
      if (ObjectTransform != null)
      {
        dc.Pop();
      }
    }
  }

有三種類型繪制對象OfdVisualText、OfdVisualPath、OfdVisualImage,派生自O(shè)fdVisual。分別處理三種圖元數(shù)據(jù)。所有的繪制操作在函數(shù)

public override void Show(bool visiable, bool even = false);

對應(yīng)文本,繪制函數(shù)如下:

 void DrawText()
    {
      using (DrawingContext dc = RenderOpen())
      {
        if (ObjectClipsGroup == null)
        {
          PutBoundary(dc);
          PutTransform(dc);

          DrawTextInner(dc);

          PopTransform(dc);
          PopBoundary(dc);
        }
        else
        {
          foreach (VisulClip visulClip in ObjectClipsGroup)
          {
            PutBoundary(dc);
            visulClip.PutClip(dc);
            PutTransform(dc);

            DrawTextInner(dc);

            PopTransform(dc);
            visulClip.PopClip(dc);
            PopBoundary(dc);
          }
        }
      }
    }

    private void DrawTextInner(DrawingContext dc)
    {
      int i = -1;
      double deltaXTotal = 0;
      double deltaYTotal = 0;
      Point pt = new Point();

      foreach (FormattedText formattedText in FormattedTextCollection)
      {
        i++;
        if (i != 0)
        {
          if (DeltaCollectionX != null)
          {
            double deltaX = DeltaCollectionX.GetValue(i - 1);
            deltaXTotal += deltaX;
          }

          if (DeltaCollectionY != null)
          {
            double deltaY = DeltaCollectionY.GetValue(i - 1);
            deltaYTotal += deltaY;
          }
        }

        pt.X = TextLocation.X + deltaXTotal;
        pt.Y = TextLocation.Y + deltaYTotal - FormattedTextCollection.FontBaseLine;
        dc.DrawText(formattedText, pt);
      }
    }

 繪制前,需要對當(dāng)前坐標(biāo)做變換、旋轉(zhuǎn)、剪切等操作。

最近又對程序完善了,增加縮略圖和公文索引:

后記

編寫閱讀器類軟件的關(guān)鍵是建模。首先讀懂標(biāo)準(zhǔn),對標(biāo)準(zhǔn)中描述的圖元做歸類分析,并建立起相應(yīng)的顯示模型。本人做WPF開發(fā)很多年了,感覺用WPF開發(fā)這類軟件并不是非常的難。相比于QT,采用wpf開發(fā)有很多優(yōu)勢。如果要完整實現(xiàn)OFD標(biāo)準(zhǔn),還需要大量的開發(fā),我會逐步完善該軟件的功能。

特別說明

ofd閱讀器開發(fā)語言為c#,具有完全自主產(chǎn)權(quán),沒有使用第三方ofd開發(fā)包??梢愿鶕?jù)你的需求快速定制開發(fā)。本閱讀器還在開發(fā)完善階段,如有任何問題,可以聯(lián)系我QQ:13712486。

以上就是c# 基于wpf,開發(fā)OFD電子文檔閱讀器的詳細(xì)內(nèi)容,更多關(guān)于c# wpf開發(fā)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C# WinForm實現(xiàn)Win7 Aero透明效果代碼

    C# WinForm實現(xiàn)Win7 Aero透明效果代碼

    這篇文章主要介紹了C# WinForm實現(xiàn)Win7 Aero透明效果代碼,通過調(diào)用dwmapi.dll相關(guān)方法實現(xiàn),需要的朋友可以參考下
    2014-07-07
  • C# Form自定義光標(biāo)的簡單實現(xiàn)

    C# Form自定義光標(biāo)的簡單實現(xiàn)

    這篇文章主要介紹了C# Form自定義光標(biāo)的簡單實現(xiàn),有需要的朋友可以參考一下
    2014-01-01
  • Unity報錯InvalidOperationException: out of sync的解決

    Unity報錯InvalidOperationException: out of sync的解決

    今天在做個東西,發(fā)現(xiàn)報錯,特此來記錄一下,本文介紹了Unity報錯InvalidOperationException: out of sync的解決,感興趣的可以了解一下
    2021-05-05
  • 超炫酷的WPF實現(xiàn)Loading控件效果

    超炫酷的WPF實現(xiàn)Loading控件效果

    這篇文章主要介紹了超炫酷的WPF實現(xiàn)Loading控件效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-11-11
  • 利用C#編寫Linux守護(hù)進(jìn)程實例代碼

    利用C#編寫Linux守護(hù)進(jìn)程實例代碼

    如今的編程是一場程序員和上帝的競賽,程序員要開發(fā)出更大更好、傻瓜都會用到軟件,下面這篇文章主要給大家介紹了關(guān)于利用C#編寫Linux守護(hù)進(jìn)程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2018-01-01
  • C#使用itextsharp生成PDF文件的實現(xiàn)代碼

    C#使用itextsharp生成PDF文件的實現(xiàn)代碼

    以下是對在C#中使用itextsharp生成PDF文件的實現(xiàn)代碼進(jìn)行了詳細(xì)分析介紹,需要的朋友可以過來參考下
    2013-07-07
  • C# MVC 微信支付教程系列之公眾號支付代碼

    C# MVC 微信支付教程系列之公眾號支付代碼

    本篇文章主要介紹了C# MVC 微信支付教程系列之公眾號支付代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • 利用Distinct()內(nèi)置方法對List集合的去重問題詳解

    利用Distinct()內(nèi)置方法對List集合的去重問題詳解

    這篇文章主要給大家介紹了關(guān)于利用Distinct()內(nèi)置方法對List集合的去重問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • C# 索引器的使用教程

    C# 索引器的使用教程

    索引器允許類或者結(jié)構(gòu)的實例按照與數(shù)組相同的方式進(jìn)行索引。索引器類似于屬性,不同之處在于他們的訪問采用參數(shù)。本文講解了c#的具體使用方法,感興趣的朋友可以了解下
    2021-05-05
  • 基于WPF實現(xiàn)多選下拉控件的示例代碼

    基于WPF實現(xiàn)多選下拉控件的示例代碼

    這篇文章主要為大家詳細(xì)介紹了WPF實現(xiàn)簡單的多選下拉控件,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下
    2023-02-02

最新評論

闽清县| 垫江县| 乐昌市| 天水市| 贵南县| 龙江县| 吴川市| 仁怀市| 红桥区| 富顺县| 剑河县| 齐河县| 民权县| 常德市| 郁南县| 彭山县| 县级市| 桦南县| 和顺县| 大石桥市| 武穴市| 临澧县| 邹平县| 奉贤区| 抚顺县| 赞皇县| 鄂托克旗| 和龙市| 霍林郭勒市| 兴海县| 子长县| 剑阁县| 敦化市| 道孚县| 密山市| 绥江县| 衡东县| 河西区| 泽库县| 华安县| 晋江市|