Visio插件开发:根据形状选择颜色

在Visio中,根据用户选择的形状自动应用颜色似乎是一个简单的任务,但实际上它涉及到几个关键的技术点。本文将介绍如何使用Visual Studio 2017创建一个Visio插件,实现这个功能。主要的技术挑战包括:

  • 连接SelectionChanged事件
  • 在Ribbon中保持和访问状态(用于默认颜色)
  • 设置选中形状的颜色

首先,需要在Visual Studio 2017中安装“Office/SharePoint开发”工作负载。从Visual Studio 2017开始,安装程序允许模块化安装,所以只需要添加这个工作负载到安装中。

启动Visual Studio Installer(开始 -> 输入“Visual Studio Installer”)。在安装程序窗口中,选择“更多 > 修改”:

稍等片刻后,将进入工作负载选择屏幕。选择Office/SharePoint开发,然后点击“修改”。

当再次启动Visual Studio时,会发现有一组新的项目模板。

创建Visio插件

在VS中,创建一个新项目(文件 > 新建 > 项目...),如下所示:

如所见,有新的项目模板用于“Office/SharePoint”。选择了Visio插件项目,并给它一个合适的名称“ActOnShapeSelection”。

结果是一个包含一个C#文件的项目(ThisAddIn.cs)。这是将初始化事件的地方。作为一个测试,在启动插件时显示一个消息框,关闭它时再显示一个:

public partial class ThisAddIn { private void ThisAddIn_Startup(object sender, System.EventArgs e) { MessageBox.Show("启动ActOnShapeSelection"); } private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { MessageBox.Show("关闭ActOnShapeSelection"); } }

注意:默认情况下,System.Windows.Forms命名空间不包含在using列表中,所以需要添加它。一个简单的方法是点击下划线的消息框,然后输入ctrl+;(控制+分号)。现在可以选择如何解决“using问题”。

启动应用程序(F5)现在将启动Visio,第一个消息框确实显示出来了。关闭Visio会显示第二个消息框。到目前为止,没有什么复杂的,但这证明了插件已正确加载到Visio中。

说服Visio在形状被选中时做一些事情只是稍微困难一些。

连接Selected事件

public partial class ThisAddIn { private void ThisAddIn_Startup(object sender, System.EventArgs e) { Application.SelectionChanged += Application_SelectionChanged; } private void Application_SelectionChanged(Visio.Window Window) { MessageBox.Show("SelectionChanged ActOnShapeSelection"); } }

SelectionChanged事件必须在启动事件中连接。稍后,将为ShapeAdded事件做同样的事情。一旦知道了这个“技巧”,事情就变得容易了。

运行这段代码时,每次在Visio中选择一些东西,就会看到消息框。所以事件连接工作。现在希望能够只在形状被选中时执行代码。让调查一下能否在“Window”参数中找到关于选定对象的一些信息:

正如预期的那样,这是一个动态对象。Visio通过COM访问。幸运的是,调试器允许展开动态视图成员。查看这个对象的成员,发现一个属性“Selection”。这看起来很有希望!再进一步,“Selection”是IVSelection接口的实现。这个接口继承自IEnumerable。

所以Selection实际上是一个可枚举的集合,包含了所有选定的项目,因此可以使用标准的foreach()来处理。让试试这个:

private void Application_SelectionChanged(Visio.Window Window) { Visio.Selection selection = Window.Selection; foreach (dynamic item in selection) { Visio.Shape shp = item as Visio.Shape; if (shp != null) { shp.Characters.Text = "selected"; } } }

再次运行插件(F5),并在页面上添加2个形状。当选择形状时,它们会得到文本“selected”。所以现在能够知道哪些形状被选中,并对它们做一些有用的事情。让添加一个新的Ribbon,以便在形状上执行操作。毕竟,这就是这个练习的目的。

添加Ribbon

这可以通过右键单击项目,新建项目项来轻松完成。然后选择Office/SharePoint > Ribbon(Visual Designer)。

将这个Ribbon命名为“ActionsRibbon”。

打开Ribbon,现在可以使用视觉设计器。确保工具箱窗口是可见的(视图 > 工具箱)。

现在在设计表面上添加3个ToggleButton,命名为btnRed、btnGreen和btnBlue。对于每个按钮,通过双击按钮来添加Click事件。使用GroupView Tasks,还添加了一个DialogBoxLauncher。这将打开一个ColorDialog用于选择自定义颜色。

双击该组以实现“DialogLauncherClick”事件,这将处理这个事件。

ActionsRibbon将包含它自己的数据,即3个颜色组件(Red、Green、Blue):

public byte Red { get; private set; } public byte Green { get; private set; } public byte Blue { get; private set; }

每个切换按钮将切换自己的颜色组件:

private void btnRed_Click(object sender, RibbonControlEventArgs e) { Red = (byte)(255 - Red); } private void btnGreen_Click(object sender, RibbonControlEventArgs e) { Green = (byte)(255 - Green); } private void btnBlue_Click(object sender, RibbonControlEventArgs e) { Blue = (byte)(255 - Blue); }

注意:如果不可能选择自定义颜色,这段代码工作得很好。当选择自定义颜色时,值将变成0或255以外的其他值,不再与UI相对应。把它留给读者作为一个练习来实现更好的实现。

选择自定义颜色:

private void group1_DialogLauncherClick(object sender, RibbonControlEventArgs e) { ColorDialog dlg = new ColorDialog { Color = Color.FromArgb(Red, Green, Blue) }; if (dlg.ShowDialog() == DialogResult.OK) { Red = dlg.Color.R; Green = dlg.Color.G; Blue = dlg.Color.B; } }

在AddIn类的SelectionChanged事件中,现在需要引用Ribbon中的RGB值。以下是事件处理程序的完整代码:

private void Application_SelectionChanged(Visio.Window Window) { ActionsRibbon rib = Globals.Ribbons.ActionsRibbon; Visio.Selection selection = Window.Selection; foreach (dynamic item in selection) { Visio.Shape shp = item as Visio.Shape; if (shp != null) { shp.Characters.Text = "selected"; shp.CellsSRC[(short)Visio.VisSectionIndices.visSectionObject, 3, 0].FormulaU = "THEMEGUARD(RGB(" + rib.Red + ", " + rib.Green + ", " + rib.Blue + "))"; } } }

有一些Visio-fu来设置颜色。把它看作是一个食谱。当这样做时,会得到预期的结果。Visio并不总是那么直接的。

现在有一个工作的Visio插件,它做了被要求的事情。但是当添加一个新形状时,它会自动接收所选的颜色。为了解决这个问题,添加了另一个事件处理程序:

Application.ShapeAdded += Application_ShapeAdded;

还添加了一个布尔值,指示否正在添加一个形状。

bool _isAddingAShape = false;

在ShapeAdded事件中,将它的值设置为true:

private void Application_ShapeAdded(Visio.Shape Shape) { _isAddingAShape = true; }

修改SelectionChanged事件,使其在形状被添加时不做任何事情。这个事件会在形状被选中时被调用,也会在形状被添加时被调用(这确实选择了它)。代码如下:

private void Application_SelectionChanged(Visio.Window Window) { if (!_isAddingAShape) { ActionsRibbon rib = Globals.Ribbons.ActionsRibbon; Visio.Selection selection = Window.Selection; foreach (dynamic item in selection) { Visio.Shape shp = item as Visio.Shape; if (shp != null) { shp.Characters.Text = "selected"; shp.CellsSRC[(short)Visio.VisSectionIndices.visSectionObject, 3, 0].FormulaU = "THEMEGUARD(RGB(" + rib.Red + ", " + rib.Green + ", " + rib.Blue + "))"; } } } _isAddingAShape = false; }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485