Custom add-ons and dockers in CorelDRAW

Update: For differences in X5 please see this

Introduction

As you know, CorelDRAW is a very extensible and customizable application.  With X4 a new feature was added that makes it even more so—the "Addons" folder.  In this tutorial, we'll discuss creating an addon, customizing UI and creating custom HTML dockers.  For example, a table preset docker (link to the addon and source found at the bottom of the article). 

This tutorial will be technical.  We'll be using XML, XSLT, VBA, HTML and JavaScript.  While I tried to write this tutorial so that you could tweak the examples without a full understanding of the languages, some knowledge of them will be helpful.  There are plenty of online resources for any of these items.  You'll also need a GUID generator.  I use the one that comes with Visual Studio, but there are online generators as well.  http://www.guidgenerator.com/ for example.

The last thing you'll need is CorelDRAW X4 with SP2 installed.

The "Addons" folder

If you look in your X4 install, you'll find the addons folder at: "C:\Program Files\Corel\CorelDRAW Graphics Suite X4\Programs\Addons".  This folder was added to give CorelDRAW developers a method to create features which weren't tied to core code.  Another benefit: it gives you and other 3rd party addon developers a way to create and deliver new features for CorelDRAW X4.  Under the addons folder you'll find "\Common" and "\Draw".  Addons which are shared between Draw and Photopaint are placed in "\Common", while CorelDRAW-only addons are stored in "\Draw""\PhotoPaint" is for Photopaint addons; you'll need to create this folder if you intend to create a PhotoPaint-only addon.

Customizing UI via an XSLT

To start with something simple, we'll create an addon which adds a menu item to the 'Text' menu.  The new menu item will run the 'Calendar Wizard' macro which comes with CorelDRAW. 

  • Add a new folder under "\Addons\Draw"Name it "\MyAddon". 

All of the UI within CorelDRAW is stored within an XML file.  We add custom UI to it by creating two XSLT files.  An XSLT is a file which transforms an XML file.  For our purpose, the XSLT simply copies all of the existing UI and inserts our new UI into CorelDRAW's main XML UI file.  AppUI.xslt defines new buttons, menu items, menu flyouts and dockers.  Lets take a look at it:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:frmwrk="Corel Framework Data">
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
  <!-- Use these elements for the framework to move the container from the app config file to the user config file -->
  <frmwrk:uiconfig>
    <!-- The Application Info should always be the topmost frmwrk element -->
    <frmwrk:applicationInfo userConfiguration="true" />
  </frmwrk:uiconfig>
 
  <!-- Copy everything -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
 
  <!-- Add the custom UI items -->
  <xsl:template match="uiConfig/items">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
      <itemData guid="886e8a11-c69c-30be-4d7f-f33a704645e9"
                       dynamicCommand="CalendarWizard.Wizard.CreateCalendar"
                       dynamicCategory="2cc24a3e-fe24-4708-9a74-9c75406eebcd"
                       bmpCol="0" bmpRow="0" userCaption="Create Calendar"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Near the end of the file you'll see the new button (or item) that we've defined.  It has the GUID "886e8a11-c69c-30be-4d7f-f33a704645e9".  I generated this GUID using GuidGen.exe (see http://www.guidgenerator.com/ for an online generator).  It is a unique identifier.  When you create a new addon, you should generate your own GUIDs so that your addon doesn't conflict with other addons.  For the purposes of this tutorial you can use the GUIDs I give you. 

dynamicCommand="CalendarWizard.Wizard.CreateCalendartells the item what VBA function it runs. 

dynamicCategory="2cc24a3e-fe24-4708-9a74-9c75406eebcd" tells the item to add itself to customization, "2cc24a3e-fe24-4708-9a74-9c75406eebcd" refers to the VBA customization list. 

bmpCol="0" bmpRow="0" defines the icon to use.  bmpCol needs to be between 0 to 9, while bmpRow goes above a thousand.  You can define your own icons too, but this is out of the scope of this tutorial.  

  • Create a new text document in the MyAddon folder and name it AppUI.xslt. ***
  • Open it in a text editor (notepad will do, but an editor with XML syntax highlighting can be helpful). 
  • Copy and paste the above XSLT contents into it and save.

  *** As pointed out by a reader, Vista users may need to modify their folder permissions to create these files ***

Now the button is defined, but if you run the application, you won't find it in the UI.  To add the UI we use UserDraw.xslt.  We'll place it after the "Font list options" menu item in the main text menu.  

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:frmwrk="Corel Framework Data"> 
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
  
  <!-- Use these elements for the framework to move the container from the app config file to the user config file --> 
  <frmwrk:uiconfig> 
    <!-- The Application Info should always be the topmost frmwrk element --> 
    <frmwrk:applicationInfo name="CorelDRAW" framework="CorelDRAW" version="14" userConfiguration="true" /> 
    <frmwrk:compositeNode xPath="/uiConfig/commandBars/commandBarData[@guid='52433451-c803-47a2-9855-83a9f5e902c5']"/> 
    <frmwrk:compositeNode xPath="/uiConfig/frame"/> 
  </frmwrk:uiconfig> 
  
  <!-- Copy everything --> 
  <xsl:template match="node()|@*"> 
    <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
  </xsl:template> 
  
  <!-- Add the button to the text menu --> 
  <!--                &nbsp;                                                                                 * text menu guid *******************                                         * Font List Option Settings guid *******--> 
  <xsl:template match="uiConfig/commandBars/commandBarData[@guid='52433451-c803-47a2-9855-83a9f5e902c5']/container/item[@guidRef='87b76531-493d-4a9d-921d-ebcf0fad8fcf']"> 
    <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> <!-- copy Font List Option Settings --> 
    </xsl:copy> 
    <item guidRef="266435b4-6e53-460f-9fa7-f45be187d400"/> <!-- add a separator --> 
    <item guidRef="886e8a11-c69c-30be-4d7f-f33a704645e9"/> <!-- add the calendar wizard button --> 
  </xsl:template>
</xsl:stylesheet>

  • Create a new text document in the MyAddon folder and name it UserDraw.xslt
  • Open it in a text editor. 
  • Copy and paste the above XSLT contents and save.
  • Run CorelDRAW (For convenience, here is the test addon MyAddon.zip)

Now when you run CorelDRAW, you should find "Create Calendar" at the bottom of the text menu. 

Keep in mind, if you make more changes to UserDraw.xslt, you'll need to hold F8 when you launch CorelDRAW for your changes to take effect.  Unfortunately, this resets the workspace and you'll lose any customization. 

You may be wondering where I found the guids for the text menu and the font list options item.  If you look in "\Programs\UIConfig\CorelDRAW" in your install folder, you'll find DrawUI.xml.  This is the main UI xml.  All of the guids for existing menus, dockers, flyouts, ect. are stored here. 

Also, if you're having trouble finding stuff, you can customize a macro button into a toolbar, menu, or next to an item your looking for, then open "C:\Documents and Settings\<your windows user name>\Application Data\Corel\CorelDRAW Graphics Suite X4\User Workspace\CorelDRAW\_default\DRAWUIConfig.xml" and search for the macro name you've added.

Creating a custom html Docker

While it's possible to custom create dockers which use native CorelDRAW items (for example, see Jeff's Text Docker at MacroMonster.com), using HTML to define UI adds incredible flexibility.  It's also a format that many people know very well, so it shouldn't be too difficult to create some amazing addons.

To make this as easier, I've created a template webdocker to start with.   

  • Download and save TemplateWebDocker.zip
  • Unzip the contents into \Addons\Draw.
  • You should now have the folder \Addons\Draw\TemplateWebDocker.  Rename TemplateWebDocker to MyWebDocker.
  • Rename TemplateWebDocker.html and TemplateWebDocker.gms to MyWebDocker.html and MyWebDocker.gms respectively.
  • Generate 3 guids
  • Open AppUI.xslt and UserDraw.xlst, and find and replace
    • <<GUID A>> with the first GUID you generated
    • <<GUID B>> with the second GUID you generated
    • <<GUID C>> with the third GUID you generated
    • <<TemplateWebDocker>> with MyWebDocker
  • Run CorelDRAW

If everything was done right, CorelDRAW should have the new docker and menu item available.  If things do go wrong, no worries.  You can either shut down Draw, fix the error, and restart with F8, or delete the MyWebDocker folder completely and start over, remembering to hold F8 when you relaunch CorelDRAW.

You may have noticed that there's a GMS file in the MyWebDocker folder.  VBA will try to load any GMS files contained in the addon folder.  This makes it much easier to package your addons.

The new "MyWebDocker" menu item under the dockers sub-menu won't do anything yet because the MyWebDocker.gms hasn't been set up yet.  

  • In CorelDRAW, open up VBA (Alt+F11)
  • In the project window find TemplateWebDocker(MyWebDocker.gms):
  • Rename TemplageWebDocker to MyWebdocker
  • Open MyWebDocker->Macros
  • Replace <<TemplateWebDocker>> with MyWebDocker
  • Replace <<GUID C>> with the same guid you generated for guid C in the XSLT file.

Now you have a working web docker with a menu item to open it.  Try it by clicking the menu item "MyWebDocker" found under "Windows->dockers".

Nothing too exciting yet.  Lets make the new docker do something. 

From here on, we don't need to restart CorelDRAW to try the changes.  After modifying MyWebDocker.html, you can right click on the docker and select "Refresh" from the context menu.  Again, to make the tutorial easier, I've provided a new html page to use.

  • Replace MyWebDocker.html with MyWebDocker.html found in MyWebDocker.zip
  • Right click on the docker and refresh

The docker should look like:

I think you'll agree, that is a more interesting docker.  I chose to create a simple selection docker because it demonstrates how to make UI, call CorelDRAW's object model and listen to events (In this case, selection change).  It may even be a useful addon for some.

Selection Docker HTML Code Dissection

Open up MyWebDocker.html and take a look at the HTML code.  This first thing to note is the meta tag.

<meta http-equiv="MSThemeCompatible" content="yes"/> 

This line tells the HTML control to theme buttons and other controls.  If we didn't do this, the controls would look as they do in Window2k and 95.  The next items of interest are these two lines:

window.external.RegisterEventListener( "SelectionChange", "OnSelectionChange()" );

and

window.external.UnregisterEventListener( "SelectionChange" );

These lines register and unregister an event listener respectively.  After calling RegisterEventListener, a selection change in CorelDRAW will result in the javascript function "OnSelectionChange" being called.  The unregister isn't really necessary for this docker since we always want to listen for the event while the docker is open.  The event listener is unregistered automatically when the docker is closed. 

The "SelectionChange" event will probably be the event most often used.  There are many other events that can be listened for too:

"ObjectTransformed"
"StateChange"
"TextSelectionChange"
"DocUnitChange"
"TextAttributeChange"
"SelectionChange"
"NewDocument"
"CloseDocument"
"ColourPaletteChange"
"ActiveViewChange"
"ZoomLevelChange"
"ActivePageChange"
"ViewMappingChange"
"ViewScroll"
"AppStarted"
"AppShuttingDown"
"DockerStateChanged"
"OutlineAttributeChange"
"FillAttributeChange"
"CurveEditedChange"
"MacroSetChange"
"PageTypeChange"
"NodeSelectionChanged"
"TableTool_CellSelectionChanged"
"TableCore_TableModified"

In most cases you should be able to guess what these events do by looking at the name.

The last thing you need to know is how to call a function in CorelDRAW's object model.

window.external.Application

This identifies the root of CorelDRAW's object model.  For example, in the selection docker you will find the line:

numSelected.value = window.external.Application.ActiveSelection.Shapes.Count;

If you're familier with VBA in CorelDRAW, part of this probably looks familiar.   In VBA, ActiveSelection.Shapes.Count is a property which returns the number of shapes in the active selection.  Any object model function available in VBA can be run in javascript by placing "window.external.Application" in front of it.  You can even run VBA functions you write yourself in javascript by calling GMSManager.RunMacro.  For example, if you wanted to call the function to show the docker:

window.external.Application.GMSManager.RunMacro( "MyWebDocker", "Macros.ShowMyWebDocker" ); 

If you're interested in how I'm selecting all shapes of a certain type in 1 line of code, check out Corel Query Language (also found in CorelDRAW's VBA help listed under "Performing queries").  It's a new and powerful way to find and performs actions on objects, added to X4.

Security

Someone will eventually want to do something that goes outside of javascript's capabilities, and because you have access to the CorelDRAW's object model, you can. 

It's important to be aware of the functions you expose via your GMS files.  For example, you may want to parse subfolders or write files (e.g. saving presets).  Via a Microsoft activeX control you can get a fileSystemObject in javascript, but this brings up a message box that says that the html isn't safe.  The wrong way around this message would be to write a function in your GMS to retrieve the fileSystemObject to use in javascript. 

You may know your docker is offline, and therefore safe to do whatever you want, but another docker may be online.  If a hacker manages to hack an online docker, and they assume your addon is also installed, they would have complete access to the computer file system.  That would be bad for everyone.

The right way is to do as much work as possible in VBA when doing stuff javascript doesn't support.  Avoid passing parameters to the function that would give access to locations that are not part of your addon.  For example, if you wanted to get a list of subfolders in your addon's folder, instead of using the fileSystemObject in javascript, write a function in your VBA macro which figures out what directory to parse, and does the parsing.

Check out the table presets docker as an example.

Conclusion

Using the HTML control with CorelDRAW gives you a lot of control.  Your content can be offline, online and dynamic, use flash, silverlight, vml, and more.  One clever beta tester creates activeX controls and hosts them on the page.  Your imagination is the limit.  I look forward to seeing what you guys come up with.  If you want to share your creations with us at Corel, you can either post a reply or PM me.

Here is the table presets docker that's mentioned in the beginning of the article: TablePresetDocker.zip

 

 

  • Thats truly amazing! Thats exactly the solution for my custom GUI problem! May God bless you, Hendrik!

  • Cool stuff! Hendrik, Hey now I feel i should know these programming language.

  • Hi Hendrik!

    It's a very helpful tutorial for start with this option of CorelDraw X3 &4!

    thanks

    I've made a simple docker to navigate on the specific web site... it's working, but wen the popup windows is launching from the the web page, the popup is opened, closed and directly transfered(loaded) in the docker... the popup using Java scrip to find informations of computer and other, But, the same pages and (or) popup run correctly in Internet Explorer!

    do you know the option to constrain the docker(web player !) to run like the Windows Internet Explorer?

  • Hi All!

    Some versions of XML parser can't cope with the (c) copyright symbol in the header of the sample xslt files.  Please delete this character from all xslt files when creating your own.

    Thanks Shelby for finding this problem.

  • Hi

    What's this about the (C) symbol? I can't see one to delete -- or maybe you've already deleted it from the example?

    I get to the bit "Now when you run CorelDRAW, you should find "Create Calendar" at the bottom of the text menu" but my text menu is unchanged.

    I've tried this on two machines, one with a fresh X4 installation and a fully windows-updated XP. But X4 is SP2, not SP1. Should that be a problem?

  • Hi Harry, I've updated the text to specify that SP2 is needed, thanks.  I've also attached a zipped sample of the xslt which adds the calendar wizard to the text menu.  Unfortunately the system is archiving the samples in tgz files now.

    The (c) symbol was in the other zipped samples.  I have updated these (again, unfortunately they are now archived in tgz files).

  • does someone knows how to use my own icons for a CommandBar, in the tutorial above it talks about the bmpCol bmpRow properties but it doesn't say anything about customising icon because it was out of scope of this tutorial.  Any ideas?

  • @biok: There is a way to do that. Woxxom has two cool macros for free, able to do this job. Look here: recentfiles.netfirms.com

    @ Hendrik:

    is it possible to start an addon (implement a html file) in a Commandbar (in an additional Status bar at the bottom for example) the same way you described it for a docker? Or, can a docker be customized to be able to dock it to the bottom??

  • Mo,

    You might be able to put a browser on a command bar, but I'm not going to try it.

    There is a way to dock to the top/bottom in X5 (X4 didn't have it).   In UserDraw.xslt, where you define the dockPage, add

    canDockTop="true" canDockBottom="true"

    There is also canDockLeft, canDockRight, which defaults to true, but you can change the default if you want to limit this to horizontal only.  This stuff is new, and probably not well tested, but it should work.  Only the connect tray is using it.

  • Thanks Hendrik, that helps a lot. I am currently experimenting with dSVG inside dockers... I do not understand why this Markup Language was dropped in the past, at least in the GUI development. The upcoming IE9 enables unbelieveable UI possibilities with its full SVG support.

  • Switched from dSVG to VML due to better support in Windows. Do not use SVG in Dockers or Maco GUIs! For those who want to try...

  • Hendrik, I did update your Table Preset docker to work in X6, Win 7 and Win 8. Hope I didn't hack it up too bad. It's included and installed with Foster's new eBook for X6. Not quite as simple to install because of Windows permission settings under Program Files.

  • Hi,

    I'm using Visual Studio 2012 to develop a WPF User control for CorelDRAW X6 (64bit) as outlined in this tutorial (forum.oberonplace.com/blog.php).

    The problem is that the button and combobox controls are not showing up in the docker in CorelDRAW.

    Please help.