仅使用VSTA在Corel Draw X6中创建自定义控件

Create a custom control in Corel Draw X6 using only VSTA
2021-02-23
  •  译文(汉语)
  •  原文(英语)

我正在使用VSTA(适用于Visual Studio的应用程序)CorelDraw X6创建插件(或插件)的过程,因为我喜欢C#.NET库.我想在CorelDraw工具栏上有一个按钮,因此当用户单击此按钮时,会发生一些动作,例如,显示一个表单.为此,我使用预定义的解决方案VSTAGlobal,当我启动CorelDraw时就可以使用它.不幸的是,NO官方文档(WTF !!!!!)为VSTACorelDraw中,我们反而有VBA(Visual Basic应用程序)文件和 CorelDraw对象模型.我在Google上搜索了很多,并找到了一些链接:一些论坛帖子YouTube视频教程.问题是,那里的两个人都创建了他们的CustomControl(例如,一个按钮),并简单地将其构建为* .dll,然后使用VBA脚本将CustomControl添加到CorelDraw工具栏中,如下所示

Sub addLineWidthControl()
    Call FrameWork.CommandBars("Standard").Controls. '
         AddCustomControl("MyNameSpace.MyCustomControlClass", '
                          "MyCustomControlAssembly.dll")
End Sub

所以,我的问题是:有什么方法可以仅使用VSTA来做到这一点?

附加信息:

例如,在默认解决方案VSTAGlobal中,存在具有[CgsAddInModule]属性的Main类:

[CgsAddInModule]
public partial class Main
{
    private Corel.Interop.VGCore.Application app;

    // some other code here...
}

此类具有构造函数(请注意,默认值由CorelDraw提供):

[CgsAddInConstructor]
public Main(object _app)
// this constructor probably gets an instance
// of CorelDraw application object.
{
    app = _app as Corel.Interop.VGCore.Application;
    // will it work if I add some code here?
}

也许这是我应该添加以下内容的地方:

app.FrameWork.CommandBars["Standard"]
    .Controls.AddCustomControl("MyCustomControlClass");

我对这最后一行代码做了一些实验.我知道控件数量在增加,但是MyCustomControl仍未显示在工具栏中.

速聊1:
无论如何,您如何加载VSTA插件?我不能让它工作.我将生成的DLL文件复制到CorelDRAW \ Addins文件夹中,但无法运行!
解决过程1

有一种方法可以仅使用C#(我在Corel X8中对此进行了测试,但是它可以在具有VSTA的任何版本中使用).这是一个两部分的过程.首先,您需要在Corel中打开Macro Manager并编辑VSTAGlobal解决方案.例如,如果要添加按钮和滑块,请添加以下方法:

[CgsAddInMacro]
        public void Add()
        {
            string controlAssembly = @"C:\VSTS\ScratchProjects\CoreDrawPoC\CoreDrawPoC\bin\Debug\CoreDrawPoC.dll";
            var mySlider = app.FrameWork.CommandBars["Standard"].Controls.AddCustomControl("CoreDrawPoC.MySlider", controlAssembly);
            mySlider.Caption = "Border Sizing Slider Caption";
            mySlider.ToolTipText = "Border Sizing Slider Tooltip";

            var myButton = app.FrameWork.CommandBars["Standard"].Controls.AddCustomControl("CoreDrawPoC.ButtonSample", controlAssembly);
            myButton.Caption = "Rectanlge Selector";
            mySlider.ToolTipText = "Rectanlge Selector Tooltip";

        }

添加此代码后,将需要为上面列出的文件夹添加.dll作为解决方案.打开Visual Studio 2015并创建一个新项目(我的项目名为CoreDrawPoC).它必须是WPF用户控件库项目.创建2个.xaml文件.首先将是滑块:

<UserControl x:Class="CoreDrawPoC.MySlider"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CoreDrawPoC"
             mc:Ignorable="d" >
    <Slider x:Name="mySlider" Width="100" Minimum=".5" Maximum="10" TickFrequency=".5" IsSnapToTickEnabled="True" ValueChanged="mySlider_ValueChanged"/>
</UserControl>

后面的代码是:

using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CoreDrawPoC
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class MySlider : UserControl
    {
        Corel.Interop.VGCore.Application appDraw = null;
        public MySlider()
        {
            InitializeComponent();
        }

        public MySlider(object app)
        {
            InitializeComponent();
            appDraw = (Corel.Interop.VGCore.Application)app;
        }

        private void mySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (appDraw != null && appDraw.ActiveDocument != null && appDraw.ActiveShape != null)
            {
                double width = appDraw.ConvertUnits((double)e.NewValue, Corel.Interop.VGCore.cdrUnit.cdrPoint, Corel.Interop.VGCore.cdrUnit.cdrInch);
                appDraw.ActiveSelectionRange.SetOutlineProperties(width);
            }
        }
    }
}

然后创建按钮:

<UserControl x:Class="CoreDrawPoC.ButtonSample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CoreDrawPoC"
             mc:Ignorable="d">
    <Button x:Name="buttonSample" Click="buttonSample_Click" Width="24" Height="24" >
        <Button.Template>
            <ControlTemplate>
                <Image Source="C:\CorelIcons\Two.bmp"/>
            </ControlTemplate>
        </Button.Template>
    </Button>

</UserControl>

后面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CoreDrawPoC
{
/// <summary>
/// Interaction logic for ButtonSample.xaml
/// </summary>
public partial class ButtonSample : UserControl
{
    Corel.Interop.VGCore.Application appDraw = null;
    public ButtonSample()
    {
        InitializeComponent();
    }
    public ButtonSample(object app)
    {
        InitializeComponent();
        appDraw = (Corel.Interop.VGCore.Application)app;
    }

    private void buttonSample_Click(object sender, RoutedEventArgs e)
    {
        SelectOfType("rectangle");
    }

    private void SelectOfType(string strType)
    {
        string strQuery = null;
        Corel.Interop.VGCore.ShapeRange srGroup = default(Corel.Interop.VGCore.ShapeRange);
        Corel.Interop.VGCore.ShapeRange srTopOnly = default(Corel.Interop.VGCore.ShapeRange);

        strQuery = "@type='" + strType + "'";
        srGroup = appDraw.ActivePage.Shapes.FindShapes("", 0, true, strQuery);
        srTopOnly = appDraw.ActivePage.Shapes.FindShapes("", 0, false, strQuery);
        srTopOnly.CreateSelection();
        appDraw.ActivePage.Shapes.FindShapes("", 0, false, strQuery).CreateSelection();

        //if (srTopOnly.Count == srGroup.Count)
        //{
        //    lblWarning.Visibility = System.Windows.Visibility.Hidden;
        //}
        //else
        //{
        //    lblWarning.Visibility = System.Windows.Visibility.Visible;
        //}
    }

}

}

完成后,您将需要编译代码.另外,您将要创建映像C:\ CorelIcons \ Two.bmp.它只是一个看起来像是24x24的位图,但是您希望它看起来像.然后编译项目.您将需要关闭CorelDraw.

成功编译后,您将需要运行VSTA宏以添加按钮和滑块.该宏只需要运行1次!之后,它将直接连接到您dll中的代码.如果您更改了dll中的任何内容并在Corel关闭时对其进行了更新,它将对其进行更改.这包括图像.

最后,我从2篇博文中学习了如何执行此操作,并且只对其进行了更改,以在"标准"命令栏中添加按钮并仅使用C#.这些职位是:

速聊1:
非常感谢@ ben-hoffman!几年前,我问了这个问题,从那时起,我对该项目一无所获.我无法确认该解决方案是否有效,但是我还是给它一个"是"和"+",因为它对您有用,因为它非常详细,因为问题和主题很少,并且您提供了链接重要资源.再次感谢!

I am in the process of creating a plugin (or addin) for CorelDraw X6 using VSTA (Visual Studio for Applications) because I like C# and .NET library. I would like to have a button in CorelDraw toolbar, so when a user clicks this button some action happens, for example, a form is showed. For that I use predefined solution VSTAGlobal, that is there for me when I start CorelDraw. Unfortunately, there is NO official documentation (WTF!!!!!) for VSTA in CorelDraw, instead we have VBA (Visual Basic for Applications) documentation and CorelDraw Object Model. I googled a lot and found a few links: some forum post and YouTube video tutorial. The problem is, both guys there create their CustomControl (a buton for example) and simply build it as *.dll and then use VBA script to add the CustomControl to CorelDraw toolbar like this

Sub addLineWidthControl()
    Call FrameWork.CommandBars("Standard").Controls. '
         AddCustomControl("MyNameSpace.MyCustomControlClass", '
                          "MyCustomControlAssembly.dll")
End Sub

So, my question is: is there any way to do this using only VSTA?

Additional info:

For example, in the default solution VSTAGlobal there is a Main class with [CgsAddInModule] attribute:

[CgsAddInModule]
public partial class Main
{
    private Corel.Interop.VGCore.Application app;

    // some other code here...
}

This class has a constructor (note, default and provided by CorelDraw):

[CgsAddInConstructor]
public Main(object _app)
// this constructor probably gets an instance
// of CorelDraw application object.
{
    app = _app as Corel.Interop.VGCore.Application;
    // will it work if I add some code here?
}

Maybe this is the place where I should add something like this:

app.FrameWork.CommandBars["Standard"]
    .Controls.AddCustomControl("MyCustomControlClass");

I did some experiments with this last line of code. I obtained that the Count of Controls is increasing, but still MyCustomControl does not show up in the toolbar.

Talk1:
How did you load the VSTA addin anyway? I can't get that to work. I copy the built DLL file to the CorelDRAW\Addins folder but it doesn't run!
Solutions1

There is a way to use only C# (I tested this in Corel X8 but it should work in any version that has VSTA). It is a 2 part process though. First you will need to open Macro Manager in Corel and edit the VSTAGlobal solution. For example, if you want to add a button and a slider, add this method:

[CgsAddInMacro]
        public void Add()
        {
            string controlAssembly = @"C:\VSTS\ScratchProjects\CoreDrawPoC\CoreDrawPoC\bin\Debug\CoreDrawPoC.dll";
            var mySlider = app.FrameWork.CommandBars["Standard"].Controls.AddCustomControl("CoreDrawPoC.MySlider", controlAssembly);
            mySlider.Caption = "Border Sizing Slider Caption";
            mySlider.ToolTipText = "Border Sizing Slider Tooltip";

            var myButton = app.FrameWork.CommandBars["Standard"].Controls.AddCustomControl("CoreDrawPoC.ButtonSample", controlAssembly);
            myButton.Caption = "Rectanlge Selector";
            mySlider.ToolTipText = "Rectanlge Selector Tooltip";

        }

Once you add this code, you will need to add a .dll for a solution to the folder listed above. Open Visual Studio 2015 and create a new project (mine was named CoreDrawPoC). It needs to be a WPF User Control Library project. Create 2 .xaml files with. First will be the slider:

<UserControl x:Class="CoreDrawPoC.MySlider"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CoreDrawPoC"
             mc:Ignorable="d" >
    <Slider x:Name="mySlider" Width="100" Minimum=".5" Maximum="10" TickFrequency=".5" IsSnapToTickEnabled="True" ValueChanged="mySlider_ValueChanged"/>
</UserControl>

Code behind is:

using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CoreDrawPoC
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class MySlider : UserControl
    {
        Corel.Interop.VGCore.Application appDraw = null;
        public MySlider()
        {
            InitializeComponent();
        }

        public MySlider(object app)
        {
            InitializeComponent();
            appDraw = (Corel.Interop.VGCore.Application)app;
        }

        private void mySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (appDraw != null && appDraw.ActiveDocument != null && appDraw.ActiveShape != null)
            {
                double width = appDraw.ConvertUnits((double)e.NewValue, Corel.Interop.VGCore.cdrUnit.cdrPoint, Corel.Interop.VGCore.cdrUnit.cdrInch);
                appDraw.ActiveSelectionRange.SetOutlineProperties(width);
            }
        }
    }
}

Then create the button:

<UserControl x:Class="CoreDrawPoC.ButtonSample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CoreDrawPoC"
             mc:Ignorable="d">
    <Button x:Name="buttonSample" Click="buttonSample_Click" Width="24" Height="24" >
        <Button.Template>
            <ControlTemplate>
                <Image Source="C:\CorelIcons\Two.bmp"/>
            </ControlTemplate>
        </Button.Template>
    </Button>

</UserControl>

Code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CoreDrawPoC
{
/// <summary>
/// Interaction logic for ButtonSample.xaml
/// </summary>
public partial class ButtonSample : UserControl
{
    Corel.Interop.VGCore.Application appDraw = null;
    public ButtonSample()
    {
        InitializeComponent();
    }
    public ButtonSample(object app)
    {
        InitializeComponent();
        appDraw = (Corel.Interop.VGCore.Application)app;
    }

    private void buttonSample_Click(object sender, RoutedEventArgs e)
    {
        SelectOfType("rectangle");
    }

    private void SelectOfType(string strType)
    {
        string strQuery = null;
        Corel.Interop.VGCore.ShapeRange srGroup = default(Corel.Interop.VGCore.ShapeRange);
        Corel.Interop.VGCore.ShapeRange srTopOnly = default(Corel.Interop.VGCore.ShapeRange);

        strQuery = "@type='" + strType + "'";
        srGroup = appDraw.ActivePage.Shapes.FindShapes("", 0, true, strQuery);
        srTopOnly = appDraw.ActivePage.Shapes.FindShapes("", 0, false, strQuery);
        srTopOnly.CreateSelection();
        appDraw.ActivePage.Shapes.FindShapes("", 0, false, strQuery).CreateSelection();

        //if (srTopOnly.Count == srGroup.Count)
        //{
        //    lblWarning.Visibility = System.Windows.Visibility.Hidden;
        //}
        //else
        //{
        //    lblWarning.Visibility = System.Windows.Visibility.Visible;
        //}
    }

}

}

Once that is done, you will want to compile the code. Also, you will want to create the image C:\CorelIcons\Two.bmp. It is just a 24x24 bitmap that looks however you want it to look. Then compile the project. You will need to this will CorelDraw closed.

Once it compiles successfully, you will want to go and run your VSTA macro to add the button and slider. This macro will only need to be run 1 time! After than, it will connect directly to the code in your dll. If you change anything in the dll and update it while Corel is closed, it changes it. This includes the images.

Finally, I learned how to do this from 2 blog posts and I only changed it to add a button to the Standard command bar and to use purely C#. Those posts are:

Talk1:
Thank you so much, @ben-hoffman! I asked this question years ago, and haven't done anything about this project since then. I cannot confirm that this solution works, but I'll still give it a "yes" and a "+" because it worked for you, because it's very detailed, because the question and the subject are very rare, and because you provide links to important resources. Thanks again!
转载于:https://stackoverflow.com/questions/23733516/create-a-custom-control-in-corel-draw-x6-using-only-vsta

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入