生成自定义工具栏

前序

相信我们在用VBA编写Coreldraw插件时,都经常这样用,写好功能代码后,在Coreldraw工作界面,手动创建一条工具栏,然后在工具栏上新建按钮,让按钮指向VBA代码块,方便快捷的调用操作。比如下图:
在这里插入图片描述

来到C#,如何做呢,WinForm的操作挺方便,但很难植入Coreldraw,除非你用监控的方式,但也有点复杂;用Visual Studio Tools for Applications写宏代码也没有问题,但目前还不是很完善,好像还没有办法让自定义工具栏上的图标指向宏代码的方法。

其实Corel很早就提出用C++编写cpg插件或用C#编写addon插件的方式植入插件。这里我们研究一下用C#编写addon插件生成自定义工具栏(CommandBar)的方法。

先看一下addon插件存放目录和文件。addon插件存放在Coreldraw安装目录的“\Programs64\Addons\”下,新建一个与你所生成的DLL标题一样的目录,在把文件拷进去。里面主要有4个文件,AppUI.xslt、UserUI.xslt、CorelDrw.addon、和一个程序集文件dll文件,CorelDrw.addon可以是空文件。比如下图:
在这里插入图片描述

安装C# Coreldraw插件开发模板

在Visual Studio有Coreldraw为用户提供的制作控件、使用工具和泊物窗、菜单的C#扩展模板程序,利用这个模板我们可以更方便的调试。我们就利用这个模板生成和调试工具栏。本教程用Visual Studio 2019社区版+Coreldraw 2018调试和讲解。
首先打开Visual Studio,在菜单命令上选择打开“管理扩展”,如下图:
在这里插入图片描述

搜索安装CorelDraw Addons Templates,至于CorelDraw Addons Packer可以选择安装也可以不安装。如下图:
在这里插入图片描述

关闭Visual Studio,等扩展应用安装完成,再启动Visual Studio,创建新项目,搜索“corel”,有4个模板供我们使用,我们就选控件模板吧,然后下一步。如下图:
在这里插入图片描述

项目名称最好先想好,要不以后改有点麻烦;指定项目存放目录,创建。如下图:
在这里插入图片描述

选择对应自己电脑上的Coreldraw版本,创建项目。如下图:

在这里插入图片描述

出现了如下界面:
在这里插入图片描述

“AppUI.xslt”和“UserUI.xslt”
先看“AppUI.xslt”和“UserUI.xslt”,这两个文件是由Coreldraw应用程序读取解释,主要是决定程序和用户界面的表现形式。“AppUI.xslt”和“UserUI.xslt”里面充满了GUID,据说GUID是微软是这些数字,让全世界的电脑的终端都不会有相同的ID出现。Coreldraw里面菜单栏、工具栏、泊物窗等都指定了不同的GUID,利用GUID查找Coreldraw的元素很都不会有重复。对单机电脑来说,从别处电脑复制来的GUID基本上也不可能有冲突。猜想一下,用户控件嵌入Coreldraw的界面后还可能另外指定了GUID,所以这两个表的GUID可以复制过来应该问题也不大。复制后有3个地方要改一下,如下图:
在这里插入图片描述

用户界面设计(xaml)

这个模板做成的项目应该是WPF应用,输出类型是类库。在解决方案资源管理器下找到ControlUl.xaml文档,双击打开。如下图:
在这里插入图片描述

可以看到这个窗体控件设计分为两块,上面是绘画窗体控件块,下面是代码块。这和WinForm不同,WinForm主要靠拖拉控件组件完成界面设计(当然也有窗体配置代码块),而WPF基本上是靠自己绘画。代码块则是类似于网页设计的代码结构(仿佛又想到为不同浏览器写兼容的HTML的抓狂),试过后,原来和HTML代码的编写很相像,应该不难掌握吧。对比一下,C#代码主要是大括号闭合代码块,而xaml是用尖括号闭合定义代码块,和HTML代码块相似。如下图:
在这里插入图片描述

由于模板目标是生成插入到属性工具栏的1个按钮,所以我们要改一下,我们把Grid里面的Button块去掉如下图:
在这里插入图片描述

由于我们要制作工具栏,所以先确定他的尺寸。我们把Hight这一块改为以下代码:

Height="40" Width="200" Padding="0 8 0 8"  Loaded="UserControl_Loaded">

如下图:
在这里插入图片描述

UserControl的Height(高度)和Width(宽度)不是很重要,以后嵌入Coreldraw界面后会自动调整;代码元素的尺寸都是以像素为单位的;这些属性之间是空格隔开,那个先后都没有关系,完全取决你的习惯。Padding和Maggin是网页控制的常用属性,Padding是容器里面要留出的空间;Maggin是对象与对象之间或对象与它的容器之间的空间,两对象的Maggin空间可以重叠。Padding和Maggin在这里是按左、上、右、下的方位来设置,如果4个值都相同,就写1个就可以了,否则就要写完4个值,和HTML都相似。
你可以调整试图的显示比例,以方便你的观察和操作。如下图:
在这里插入图片描述

在“”闭合块中加入以下代码:

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="29" />
            <ColumnDefinition Width="29" />
            <ColumnDefinition Width="29" />
            <ColumnDefinition Width="29" />
            <ColumnDefinition Width="29" />
        </Grid.ColumnDefinitions>

Grid.ColumnDefinitions是指将Grid(网格)格按列来分块,宽度属性为29。点击单词Grid上,可以看到如下图:
在这里插入图片描述

从左侧工具箱中拉一个Rectangle控件到设计视图,可以看见代码中自动生成了一行Rectangle元素定义的代码。如下图:
在这里插入图片描述

Rectangle作为将来工具栏上的图标鼠标经过时底部的效果,其宽度和高度都为24像素,Stroke是指边线,现在颜色是黑色。点击代码中Rectangle单词,在右边的属性打开“外观”选项,看见它的边框厚度为1像素。
在这里插入图片描述

我们的目标是把这个工具栏,做成在电脑上创建自定义工具栏时的工具栏的表现形式。我们把Rectangle的Grid.ColumnSpan(跨过几栏网格)的属性去掉,如果有的话。并调整一下属性的先后次序以便我们更好的阅读。
HorizontalAlignment有点像网页HTML中的position-left。如下图:
在这里插入图片描述

再加上一个属性Grid.Column=“0”,指将Rectangle置于第一个网格中(从0开始);再改它的Marggin属性值。代码如下:
<Rectangle Grid.Column="0" Width="24" Height="24" Margin="3,0,0,0" HorizontalAlignment=“Left” Fill=“#FFE0F0FF” Stroke=“#FF00ADF4” VerticalAlignment=“Top”/>
效果如下图:
在这里插入图片描述

可以看到Rectangle矩形基本居中于第一个网格的中央,当然你可以手动移动它的位置到你想要的地方,下面的代码也会自动随之改变。
我们复制Rectangle闭合块的代码3次到下面,然后依次改变它的Grid.Column属性值,可以看见4个矩形框出现在4个Grid网格的中央。如下图:
在这里插入图片描述

我们准备在上面放4个图片图标,当然你也可以自己在这里画出来。这4个图标像素都是16X16的,由于比较小,所以用ICO图标,并且是按每像素来制作的。用过的像素画图工具Pixel Editor,好像可以无限试用,但经常弹出注册提示框。你也可以用PNG或JPG图片,但可能图片像素要大点才够清晰。我们现在从电脑上导入图标到项目中。我们打开项目属性,定位到资源选项卡,添加文件。如下图:
在这里插入图片描述

打开电脑上的ICO图标目录,选择4个图标加进来。图标文件名要符合它的要求,不能有特殊符号,并且最好文件名格式都一致,文件类型也一样,以便以后以后的操作。导入后要全选,在右边的属性栏Persistence(存续期)属性改为嵌入(好像保持默认的Source也可以)。比如下图:
在这里插入图片描述

然后保存所有文档。全选刚嵌入的资源,拖放到ControlUl.xaml文档处停一会,出现设计窗体界面在那里释放。如下图:
在这里插入图片描述

效果如下图:
在这里插入图片描述

你可以把4个图片手动按你的顺序放到矩形框的中央,并设置它们的层次关系。前后层次关系是选择图形,鼠标右击,排序。置于顶层就是排在前面。如下图:
在这里插入图片描述

当然你可以改代码控制,推荐代码方式,以便于后台代码的书写。改为以下代码:

<Rectangle Grid.Column="0" Name="SetSelectionFullScreenRectangle" Fill="#FFE0F0FF" Width="24" Height="24" Stroke="#FF00ADF4" HorizontalAlignment="Left" VerticalAlignment="Top" StrokeThickness="1" Margin="3,0,0,0" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave" MouseDown="SetSelectionFullScreenImage_MouseDown"/>
    <Image Grid.Column="0" Name="SetSelectionFullScreenImage" Margin="4" Width="16" Height="16" Source="全屏显示_SetSelectionFullScreen_所选全屏显示.ico" Stretch="None" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave" MouseDown="SetSelectionFullScreenImage_MouseDown" ToolTip="55"/>
    <Rectangle Grid.Column="1" Name="Rotate90AngelRectangle" Fill="#FFE0F0FF" Width="24" Height="24" Stroke="#FF00ADF4" HorizontalAlignment="Left" VerticalAlignment="Top" StrokeThickness="1" Margin="3,0,0,0" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave"/>
    <Image Grid.Column="1" Name="Rotate90AngelImage" Width="16" Height="16" Margin="4,4,4,4" Source="旋转90_Rotate90Angel_所选旋转90度.ico" Stretch="None" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave"/>
    <Rectangle Grid.Column="2" Name="SizeHeightSameWidthScaleRectangle" Fill="#FFE0F0FF" Width="24" Height="24" Stroke="#FF00ADF4" HorizontalAlignment="Left" VerticalAlignment="Top" StrokeThickness="1" Margin="3,0,0,0" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave"/>
    <Image Grid.Column="2" Name="SizeHeightSameWidthScaleImage" Margin="4,4,4,4" Source="高同宽随_SizeHeightSameWidthScale_右图高同左图宽随比例.ico" Stretch="None" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave"/>
    <Rectangle Grid.Column="3" Name="MoreOperateRectangle" Fill="#FFE0F0FF" Width="24" Height="24" Stroke="#FF00ADF4" HorizontalAlignment="Left" VerticalAlignment="Top" StrokeThickness="1" Margin="3,0,0,0" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave"/>
    <Image Grid.Column="3" Name="MoreOperateImage" Width="16" Height="16"  Margin="4,4,4,4" Source="更多操作_MoreOperate_更多操作和功能.ico" Stretch="None" MouseEnter="QuickFunctionEnter" MouseLeave="QuickFunctionLeave"/>

这里都给它们添上了Name属性,并且在后面加上Rectangle或Image,用于区分便于后台代码操作,如同HTML一样。同时加上鼠标动作事件。MouseEnter和MouseLeave,鼠标进入和鼠标离开的事件名,在后台绑定,由于前台会传送鼠标点击对象给后台,所有元素的MouseEnter可以设计为共用一个事件,所有元素的MouseLeave也共用一个事件,在后台可以判断是哪一个对象被点击。MouseDown,鼠标点击事件,这里只演示一个元素对象的点击事件。
“UserControl.Resources></UserControl.Resources>”这一片的代码有待研究,我们先把它注释掉,也是用Ctrl+K+C组合键。

界面设计基本完成了,下面出现了错误,需要去更正。如下图:
在这里插入图片描述

户控件后台控制代码(C#)

在控件设计窗体中出现了错误,双击错误处,找到错误的地方。如下图:
在这里插入图片描述

原来是我们改xaml文档时删掉了,我们把它注释掉。这句代码是事件函数的简写,可以写在其它函数中,称为行内函数。等同于以下代码:

private void btn_Command_Click (object sender, RoutedEventArgs e)
        {
            corelApp.MsgShow("Working"); 
        }

S相当于object sender,e相当于RoutedEventArgs e 。btn_Command是对象名,也许是出现了两个“-”符号,就写成这样,好理解一些。
把“UserControl_Loaded”事件中的代码也注释掉,可能这些只是对于创建命令控件时有效的,我们是要创建工具栏,不一样。不注释可能还会发生错误。如下图:
在这里插入图片描述

由于xaml前台代码中注册了QuickFunctionEnter、QuickFunctionLeave、SetSelectionFullScreenImage_MouseDown三个事件,在这里的C#代码中也写入3个被绑定的事件函数,如下代码:

private void QuickFunctionEnter(object sender, MouseEventArgs e)
{
}
private void QuickFunctionLeave(object sender, MouseEventArgs e)
{
}
private void SetSelectionFullScreenImage_MouseDown(object sender, MouseButtonEventArgs e)
{
}

代码一会儿再补上,现在我们按启动命令,按启动图标启动程序。如下图:
在这里插入图片描述

启动后Coreldraw会自动生成插件目录,并把5个文件拷进去。如下图:
在这里插入图片描述

Pdb文件不用管它。Coreldraw界面一般能出现下面的一条长条。
在这里插入图片描述
如果没发现,可能要到工具栏里面去找。如下图:

在这里插入图片描述

把生成的长条拖放到文档窗口上面停靠释放。如下图:
在这里插入图片描述

完成效果如下:
在这里插入图片描述

停止调试后才能重新见到窗体设计窗口。我们停止调试,如下图:
在这里插入图片描述

我们还要添加像Coreldraw命令图标那样的滑动效果。我们在窗体设计ControlUl.xaml的代码块把加上名称属性:

回到ControlUl.xaml.cs代码窗口。
我们把UserControl_Loaded的事件函数改为以下代码:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
List uIElementLis t = GridParent.Children.Cast().ToList();
Type type1 = GridParent.Children[0].GetType();
Type type2 = GridParent.Children[1].GetType();
Image image = null;
foreach (UIElement uIElement in uIElementList)
{
if (uIElement.GetType() == type1) uIElement.Visibility = Visibility.Hidden;
Rectangle rectangle = null;
if (uIElement.GetType() == type1)
{
int index = uIElementList.IndexOf(uIElement);
rectangle = uIElement as Rectangle;
image = uIElementList[index+1] as Image;

            }
            if (uIElement.GetType() == type2)
            {
                image = uIElement as Image;
            }
            string source = image.Source.ToString();
            if (source.Contains("/"))
            {
                string[] sourceArray1 = source.Split('/');
                source = sourceArray1.Last();
            }
            source = source.Split('.').First();
            string[] sourceArray2 = source.Split('_');
            if (rectangle!=null) rectangle.ToolTip = sourceArray2[0] + ":" + sourceArray2[2];
            else image.ToolTip = sourceArray2[0] + ":" + sourceArray2[2];
        }
        //stylesController.LoadThemeFromPreference();
    }

这里是工具栏界面加载时执行的过程,这里用于对工具栏界面UI的改变,让控件初始化时矩形框不显示(if (uIElement.GetType() == type1) uIElement.Visibility = Visibility.Hidden;),并加入提示(ToolTip)。UIElement,UI元素,可以是Image、Rectangle等元素的任意一种,UIElement转换为具体元素用as关键词(rectangle = uIElement as Rectangle;)。这块代码判断点击元素如果是Rectangle就让它隐藏,并获取它的下一个兄弟元素Image元素的索引号(image = uIElementList[index+1] as Image;),获取Image元素的Source(如:Source=“全屏显示_SetSelectionFullScreen_所选全屏显示.ico”)属性值,提取里面的说明关键词和更详细说明,给提示元素ToolTip赋值;点击元素如果是Image就直接提取出说明给ToolTip赋值。
把QuickFunctionEnter、QuickFunctionLeave、SetSelectionFullScreenImage三个函数改为以下代码:
private bool visableOrNo = true;
private void QuickFunctionEnter(object sender, MouseEventArgs e)
{
Type type = sender.GetType();
Rectangle rectangle = null;
if (type ==SetSelectionFullScreenRectangle.GetType())
{
rectangle = sender as Rectangle;
}
if (type == SetSelectionFullScreenImage.GetType())
{
Image image = sender as Image;
string name = image.Name;
int lenth = name.Length;
name = name.Remove(lenth - 5, 5) + “Rectangle”;
rectangle = GridParent.FindName(name) as Rectangle;
}
if (visableOrNo) rectangle.Visibility = Visibility.Visible;
else rectangle.Visibility = Visibility.Hidden;
}

    private void QuickFunctionLeave(object sender, MouseEventArgs e)
    {
        visableOrNo = false;
        QuickFunctionEnter(sender, e);
        visableOrNo = true;
    }

    private void SetSelectionFullScreenImage_MouseDown(object sender, MouseButtonEventArgs e)
    {
        corelApp.ActiveWindow.ActiveView.ToFitSelection();
        corelApp.ActiveWindow.FullScreen = true;
    }

” private bool visableOrNo = true; “定义一个类内变量,让QuickFunctionLeave可以调用QuickFunctionEnter处理,而不必另外写基本相同的代码。
object sender:是前台窗体控件传来的对象,里面记录了鼠标点击的对象的信息。转换为Image或Rectangle中具体的类型,就可以给Visibility赋值。MouseEventArgs和MouseButtonEventArgs则传递过来鼠标动作和形态等的信息,这里暂没用到。SetSelectionFullScreenImage函数是则是具体测试点击“全屏显示“按钮时的执行是否正常。
再次启动程序,程序会自动把5个文件再次拷贝到插件目录并替换原来的。如果你有Coreldraw文件打开它就会新开一个文档不影响工作,但还是建议先保存文件。这点时比较方便的。
也许你发现工具栏图标没有实现相应的功能。这是因为没有打开Coreldraw文档,打开后就能起作用了。这点切勿忽略,要不你搞不清楚什么回事。
调试到这里就基本完成目标了。

将加入的资源放到同一个文件夹

加入资源后可能会在项目根目录下生成数个文件,比如像这样:
在这里插入图片描述

你也可以新建文件夹放进去,但在xaml控件设计代码中的Source属性要加入文件夹名。比如,新建文件夹BarIco:
在这里插入图片描述

把文件放进这个目录:
在这里插入图片描述

改变Source属性值,这里是相对目录引用:
在这里插入图片描述

重新启动调试。应该没什么问题。

结语

我们生成了和VBA时代几乎一样的常用的工具栏。用WPF也可以完成以后的插件开发,界面控件编写基本靠自己绘画,还有用代码去控制,代码结构像HTML,做过网站的应该可以很快入手。其它后台C#代码除了对控件代码的控制外,和WinForm基本相同,但目前来看用WPF是生成自定义工具栏的较好的办法。当然,你也可以在工具栏命令中调用WinForm程序,对Coreldraw进行操作,这也应该是比较高效的办法,下次会讨论。资源的加入是本次调试的难点之一,我们的目标是让图片资源嵌入到程序中去,不必去电脑文件目录去调用;如果测试不成功,可能还要删除资源再重新导入重新测试。
调试中随时可能会出现许多的问题,所以课件写得较为详细,尽量避免由于表达过于简单而产生理解困难。随教程奉上项目源代码,大家有兴趣可以。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值