zoukankan      html  css  js  c++  java
  • C#进行Visio二次开发

    工作总想偷懒,偷懒的前提就是要勤奋,那才有偷懒的资本

    ---------------------------------------------------------------------------------------------

       

    Visio的编程对象模型

       

      Visio二次开发中,对于其对象模型的了解,就写我们吃饭用筷子一样重要,否则不熟悉筷子的使用场景和方法,是吃不到东西的。

       

      其中主要的是下面几个对象: 

       

      Application

       

      Window (Application.ActiveWindow)

       

      Document (Application.ActiveDocument)

       

      Master、Shape、Cell

       

      一个程序中,就只有一个Application对象,类似进程的概念;打开的Visio文件有很多窗口,有一个ActiveWindow的主窗口,选区窗口、形状窗口等;模具文件打开后也是一个Document、打开的Visio文件也是一个Document、ActvieDocument是指当前 Visio窗口对应的文档,每个Visio的Document有一个或者多个Page,如系统中有两个Page、一个为绘图Page,一个为背景 Page。

       

      模具文件里面有很多Master,Master类似于模板的概念,一个Master代表一个设备类型、Shape是定义一个图形的信息,模具里面的 Master有且只有一个Shape,每个Shape又有很多Cell,代表一个ShapeSheet里面的一个格子,每个格子都有一个唯一的引用名称的。

       

      Visio文档里面,和模具文件不同,里面一个大千世界,有很多Master,也很多Shape和Cell,但是由于我们看到图纸可能一个模具的设备会有拷贝多个,因此它们公用一个Master,也就是一个Master有多个Shape引用,我们分析文件,就知道里面有一个MasterID,有点像数据库里面的外键一样。

    在VisioSDK中,大量提及使用Cell,CellsSRC等等方式进行操作,但却基本没有提及Visio的形状大小、颜色等等。Cell,Row,Column,比如最开始设置一个形状数据,为啥是取自CellsSRC(VisSectionProperty,0,0)第0行第0列?

    把Visio保存成为XML后,发现每一个形状都是使用XML进行描述的。这很重要,也就是说,Cell代表了XML中的一个叶子节点。比如形状数据中的值等等。根据保存的值,一个形状数据有很多属性,一个"CUSTID1"就有这么多内容:

    <Prop NameU='Row_1' ID='1'>

    <Value Unit='STR'>CUSTID1</Value>

    <Prompt F='No Formula'/>

    <Label>ID</Label>

    <Format F='No Formula'/>

    <SortKey F='No Formula'/>

    <Type>0</Type>

    <Invisible F='No Formula'>0</Invisible>

    <Verify F='No Formula'>0</Verify>

    <LangID>1033</LangID>

    <Calendar F='No Formula'>0</Calendar>

    </Prop>

    我们取得的Value这个Cell来定位Shape的。我们还可以取这个CUSTID1的Prompt,只需要用CellsSRC(VisSectionProperty,0, visCustPropsPrompt),注意,其实VisCustPropsPrompt的值是1,visCustPropsLabel的值是2。这暗示了一件事,也就是说,Column,列,意味着在XML中的位置,比如我们看到Value 是Prop中的第一行,哪么,它对应的Column就是0,我们数到Type是第6行,对应的Column就是5,这是真的吗?当然,不信去查visCustPropsType,它就是5。

    哪么Row又是怎么回事呢?Row,在这里就是第几个Prop的意思。一个形状可以定义多个形状数据,哪么第一个形状数据就是Row 0,第二个就是Row1。这个可以用来枚举的。

    哪么第一个参数Section是啥意思呢?因为我们是取形状数据,也就是CustProperty,因此第一个参数我们用的是visSectionProp。

    XML里边一个Shape可以有好多好多类的Section,Prop只是其中之一而已。

       

    言归正传,我们要设置Shape的位置,我们根据保存的XML可以很容易看出,Shape的位置信息似乎是在XForm这个Section里边的。

    <XForm>

    <PinX>1.771653543307088</PinX>

    <PinY>10.23622047244095</PinY>

    <Width>0.78740157480315</Width>

    <Height>0.78740157480315</Height>

    <LocPinX F='Inh'>0.393700787401575</LocPinX>

    <LocPinY F='Inh'>0.393700787401575</LocPinY>

    <Angle F='Inh'>0</Angle>

    <FlipX F='Inh'>0</FlipX>

    <FlipY F='Inh'>0</FlipY>

    <ResizeMode F='Inh'>0</ResizeMode>

    </XForm>

    按照我们一般的思想,Shape总归有一个左上角的坐标,其实我没找到。PinX、PinY,是旋转的中心点。LocPinX和LocPinY是这个Shape自身的中心点。后来我想啊想啊的就想明白了,Shape(形状)可能是不规则的,虽然可以获得包容Shape的最小矩形框,但是毕竟不是规则的,也就是说,可能没有左上角的含义。所谓Shape中心点,也就是以左上角定义的中心点。(真的是左上角坐标系吗?呵呵)

    实际上,Visio采用的坐标系是左下角坐标系,也就是说,以页面左下角为0,0,页面左上端为0,MaxY,页面右上端是MaxX,MaxY。

       

    Ok,移动一个Shape,也就是设置<XForm>的<PinX>和<PinY>就可以了。根据上边我们对Cell的理解,也就是设置PinX,PinY这两个Cell就可以了。

    get_CellsSRC的三个参数怎么填写呢?首先是Section节,Visio没有对XForm定义单独的Section,它把它归在了VisSectionIndices.visSectionObject中,也就是说Section是Object,它需要使用Row来确定是取XForm节,我猜了一下,是(short)VisRowIndices.visRowXFormOut节。其实还有一个,叫visRowXFormIn。visRowXFormOut、visRowXFormIn这两个参数定义都是0,为啥呢?因为<XForm>是<Shape>的第一个定义,按照Visio的Cell、Row、Column的参数定义,第一个就是0嘛。

    第三个参数Column就很简单,取PinX就填写0,取PinY就填写1,实际上VisioSDK的参数中也是这样定义的,visXFormPinX = 0visXFormPinY = 1

    看起来似乎一切正常。我们取得了表示位置中心的PinX和PinY Cell,只需要动动小手指,改一下这两个Cell的值,就可以搞定移动了。根据我们前边的知识,只需要设置Formula(汗死…)就可以了。

    实际上我第一次也这样干的,傻呗。正确的做法是使用set_Result,get_Result,如下所示:

    m_Cell = sp.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowXFormOut,

    (short)VisCellIndices.visXFormPinX);

    m_Cell.set_Result(VisUnitCodes.visCentimeters, m_Cell.get_Result(VisUnitCodes.visCentimeters) + DeltaX);

    m_Cell = sp.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowXFormOut,

    (short)VisCellIndices.visXFormPinY);

    m_Cell.set_Result(VisUnitCodes.visCentimeters, m_Cell.get_Result(VisUnitCodes.visCentimeters) + DeltaY);

  • 相关阅读:
    ✨Synchronized底层实现---偏向锁
    🌞LCP 13. 寻宝
    ✨Synchronized底层实现---概述
    ⛅104. 二叉树的最大深度
    c++多线程之顺序调用类成员函数
    C++ STL实现总结
    C#小知识
    C#中HashTable和Dictionary的区别
    WPF的静态资源(StaticResource)和动态资源(DynamicResource)
    WPF之再谈MVVM
  • 原文地址:https://www.cnblogs.com/ningth/p/2681144.html
Copyright © 2011-2022 走看看