您的位置:首页 > 编程语言 > C#

学习C#操纵Visio之一:定位Shape

2010-04-17 16:49 323 查看
写在本文前边:

程序员讲究因果关系,直接就说我想学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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: