学习C#操纵Visio之一:定位Shape
来源:互联网 发布:郑杭生 知乎 编辑:程序博客网 时间:2024/09/21 08:50
写在本文前边:
程序员讲究因果关系,直接就说我想学C#想用C#操作Visio显然很突兀。恩,我就讲下为啥想起来要用C#操作Visio。恩,我有一个IPHONE,上边有很多有趣的程序,恩..表达能力非常强,比以前写的传统对话框、按钮、输入行等等能力强多了。那么现在的UI库通常都是商用的,而且,重要的是似乎并不是以图形表达为重点的,比如我想界面上有一个报警灯,一会儿亮一会儿灭,实现起来就挺烦人。要是界面上都是这样的东西,恐怕得自己写一套什么。Visio、PPT什么的表达能力很强,但是,它的被操作能力如何?能不能按照我的想法表达我的思想?这就是学C#操作Visio的本意。
为啥用C#?因为我懒,厌倦了用C/C++写一大堆东西。
OK,现在开始吧。
操纵形状(哭脸变笑脸)
我这个人比较直接,用C#控制visio就想看看效果。比如实现一个动画?哭脸变笑脸? 当然我脑海中这很简单,无非就是做一个visio图,把哭脸和笑脸摆在一起,重叠放置,然后一会儿把哭脸放在前边,一会儿把笑脸放在前边。
这个很简单吧?至少听起来很简单。这里有两件事情需要搞清楚。第一,我们知道visio里的东西都是Shape,就是形状了,似乎印象中Shape是一个对象,Shape. BringToFront();就是放置在前边。这个解决Shape放置很容易了。第二,既然Shape是一个对象,那我们怎么知道哭脸是哪个对象,笑脸是哪个对象呢?这就存在一个Visio中的查找形状的问题。说实话这个问题真是讨厌,按照我的想法,因为Visio中每一个Shape都可以定义自己的形状数据(就是形状上按右键à数据à形状数据定义的东西),我只需要为哭脸定义一个形状数据,为笑脸定义一个形状数据,然后查找包含指定形状数据的形状,这样就可以确定了。
简单说来就是这样的:
foreach(每一个形状)
{
如果形状.形状数据 = 指定的形状数据(例如哭脸或笑脸)
{
形状.BringToFront()
Break;
}
}
怎么打开visio文件?
恩,说了这么多,第一件事就是打开visio文件。C#操作visio需要Reference中引用Microsoft.Office.Interop.Visio; 然后在CS文件中:
using Microsoft.Office.Interop.Visio;
第一件事情就是初始化一个app:
ApplicationClass app = new ApplicationClass();
第二件事情就是打开文档:
Document doc;
doc = app.Documents.OpenEx("E://csharp//tstvisio001//test.vsd", (short)Microsoft.Office.Interop.Visio.VisOpenSaveArgs.visOpenCopy);
Okay,我们初始化了app,也打开了这个test.vsd,然后呢?我把整个visio进行全屏:
app.DoCmd((short)VisUICmds.visCmdFullScreenMode);
为了让visio关闭的时候别提示要保存,咱们让visio以为已经保存了:
doc.Saved = true;
好了,事已至此,差不多算打开了visio文件。
关闭文件请:
doc.Close();
app.Quit();
怎么枚举页面中每一个形状
简单说来,枚举页面中每一个形状可以使用Document.Pages[x].Shapes来枚举。页面上的所有形状都是Shape,放在该Page对象的Shapes里边。
for(i=1;i<=doc.Pages[1].Shapes.Count;i++)
{
Shape sp = doc.Pages[1].Shapes[i];
…
}
注意Shape的下标是从1开始的。
怎么寻找定义的形状数据。
这个比较搞,花了一点时间才弄明白。首先是要搞明白Visio的结构。显然形状数据从属于形状。也就是说我期望Shape里有一个专门的形状数据属性,然后直接取出来就可以。后来发现Shape的属性中没有这个东西,找来找去都是什么GetRowCount,GetCellsSRC之类的东西。
貌似保存的形状数据也是在Row、Cell里。注意了,神秘的Row、Cell是Visio的基础。Row是一个框,什么都往里装。我看例子和帮助里都是用CellsSRC之类的东西取的Prop。CellsSRC的参数有三个:short Section, short Row, short Column
Section:帮助里语焉不详的说什么visSectionProp是形状数据。
Row: 许多里直接写的就是0
Column: 许多里也直接写的0
实际上我们在笑脸中定义了形状数据后,直接用Shape. get_CellsSRC((short)VisSectionIndices.visSectionProp,(short)0,(short)0); 可以直接取得刚才定义的形状数据Cell。
看到这里我迷惑了。一开始看到参数中又是行又是列,脑海中赫然一张二维表,恩恩,有道理,可能形状数据可以定义很多吧,但后来一看,md难道每次定义的都是在第0行第0列?这不是sb了么?
恩恩,这个问题直到后来研究改颜色的时候才明白过味来。我一开始写的程序,就直接用的Shape. get_CellsSRC((short)VisSectionIndices.visSectionProp, (short)0, (short)0); 。这里可以给大家一个小提示,VisRowIndices.visRowProp 的定义就是0,VisCellIndices.visUserValue的定义也是0 ,也就是说,get_CellsSRC((short)VisSectionIndices.visSectionProp, VisRowIndices.visRowProp, VisCellIndices.visUserValue); 和0,0是等价的。
废话不多说,直接上程序:
public Shape findshapebyid(string sid) { Shape sp; int i; Cell ce; short iCellExits; for (i = 1; i <= m_Doc.Pages[1].Shapes.Count; i++) { sp = m_Doc.Pages[1].Shapes[i]; iCellExits = sp.get_CellsSRCExists((short)VisSectionIndices.visSectionProp, (short)VisRowIndices.visRowProp, (short)VisCellIndices.visUserValue,(short)1); if (iCellExits == 0) continue; ce = sp.get_CellsSRC((short)VisSectionIndices.visSectionProp, (short)VisRowIndices.visRowProp, (short)VisCellIndices.visUserValue); if (ce.Formula == sid) return sp; } return null; }
这个要注意一下,因为我们用的Cells.Formula,因此如果定义的是CUSTID1,那么对应的Formula的值就是带了前后引号的”CUSTID1”,因此,传入参数应当是”/”CUSTID1/””。
程序及文件
做了一个Visio文件,里边两个Shape ,重叠在一起,分别定义形状数据CUSTID1,CUSTID2,然后不断拿到前边,这样形成哭脸变笑脸的动画。
程序包: http://download.csdn.net/source/2251471
- 学习C#操纵Visio之一:定位Shape
- 学习C#操纵Visio之三:移动Shape位置
- 学习C#操纵Visio之四:设置Shape颜色
- 学习C#操纵Visio之二:响应鼠标事件
- 学习C#操纵Visio之六:Visio版本俄罗斯方块源码下载
- 学习C#操纵Visio之五:做了个俄罗斯方块的游戏
- delphi操纵Excel之一
- C#学习笔记之一
- 基础学习 C#之一
- C# 学习教程之一
- Visio学习
- IOS学习 IOS8对应之一---------定位问
- selenium技术学习-定位方法之一
- C#多线程学习(二) 如何操纵一个线程
- C#多线程学习(二) 如何操纵一个线程
- C#多线程学习(二) 如何操纵一个线程
- [C#] C#多线程学习(二) 如何操纵一个线程
- C#多线程学习(二) 如何操纵一个线程
- ACE中TCP通信
- 尤菲·如月 与你有约 ぐりぐりキュートユフィ汉化补丁
- ACE中UDP通信
- Lucene
- 学习博客
- 学习C#操纵Visio之一:定位Shape
- Java Applet读写客户端串口——终极篇
- java谜题-2
- 求质数的文章
- 这句代码什么意思?img, div, input { behavior: url("iepngfix.htc") }
- c# 字符串的反转
- 在DELPHI中实现无标题窗体的移动最简单的方法
- JavaScript 循环
- 小民扯淡