Creating Custom Tools in CorelDRAW and Corel DESIGNER

New to CorelDRAW X7 Update 1 and Corel DESIGNER X7 is the ability to create your own tools in VBA, C# or C++. This is done using the new tool interface called ToolState and a set of many new functions and classes that are specifically geared towards creating tools.

While new tools can be implemented in any language that supports COM, this article will focus on C#.

Prerequisites

Microsoft Visual Studio 2012 or higher is required. Visual Studio Community (free version) is available from Microsoft here.

The "CorelDRAW and Corel DESIGNER Tool Addon" extension for Visual Studio is demonstrated in this article. To install the extension run Visual Studio, select the Tools->Extensions and Updates menu item, expand the Online tab and search for "CorelDRAW". Select "CorelDRAW and Corel DESIGNER Tool Addon" extension and install it.

Creating a New Project

Once the "CorelDRAW and Corel DESIGNER Tool Addon" extension is installed in Visual Studio, it will be available through the File->New Project list. Go to File->New Project andnavigate to Installed->Templates->Other Languages->C#, and select "CorelDRAW and Corel DESIGNER Tool Addon" from the list. Choose a name for the tool (e.g. "MyTool") and press OK to create the project.

Next the Addon Settings dialog is displayed from which the startup application can be selected. This choice can be changed later through the project's properties dialog (Start external program). Note: The application choices are only enabled if the template detects that the application is installed on the computer.

Compile and Run

To compile the addon, select Build->Build Solution (or press F7). Press F5 and it will launch the application (CorelDRAW or Corel DESIGNER) that was selected earlier and the new tool will be added to the toolbox.

This sample tool allows the user to create 2-point lines and demonstrates how easy it is to create a custom tool. It has on screen preview UI, snapping, constraints, a property bar, and everything else one would expect for a tool.

The Code

The project has two .cs files. Addon.cs contains the entry point. This class will be instantiated by the host application (CorelDRAW or Corel DESIGNER) when the application is started. This is where the new tool is registered, any other data sources or other tasks that need to be performed on application startup.

///<summary>
/// Constructor for the Addon. This is called by CorelDRAW or Corel DESIGNER when it is discovered.
///</summary>
public Addon(Application Application)
{
// Create and register our tool
ToolState toolState = new CGS.MyTool(Application);
Application.RegisterToolState("b17f7ca0-0062-4dd8-adf6-1ea2192a3d35", "MyTool", toolState);
}

The function RegisterToolState tells that application that the GUID (Globally Unique IDentifier) "b17f7ca0-0062-4dd8-adf6-1ea2192a3d35" identifies the MyTool addon. This GUID must be different for every tool and the Visual Studio extension will generates a new one for every project. Multiple tools can be created within the project and all registered at this place. Each tool will need a unique GUID. This can be created using Tools->Create GUID in Visual Studio or an equivalent GUID generator that are available on the web.

The MyTool.cs file contains the code for the tool. This sample tool is less than 200 lines long, but could be extended to do whatever custom logic is required. The MyTool class inherits from the ToolState interface. The host application, when using the tool, will call into the various functions that are implemented. For example, when the tool starts, the OnStartState() function will be called, allowing the tool to be set for use. When you move the mouse across the view, the OnMouseMove() function will be called. This function can be used to update the UI or collect mouse positions for curve creation.

The code for the sample tool is documented well, please take a few moments to read through the code and the comments to gain a basic understanding of the functions. The pseudo code for the line tool is as follows:

OnLButtonDownLeaveGrace save the left mouse button down position

OnMouseMove if the left mouse is down update the xor'd on screen UI with a line from the saved location to the current position

OnLButtonUp Create a line from the saved position to the current position

The UI

In the project there are two XSLT files: AppUI.xslt and UserUI.xslt. XSLT is an XML transformation file. It's purpose is to update the user's workspace to include the new tool. This sample will just add the new tool button to the end of the Toolbox. More complex changes to the workspace are possible using other XSLT transformations. If you're attempting to create any complicated UI, you may want to read up on XSLT to better understand it.

The AppUI.xslt file is responsible for defining new items (e.g. buttons) and adding new dockers or dialogs. Anything that isn't customizable can be defined here. In the sample line tool, it adds one new item.

A GUID is used to identify the tool button ("b17f7ca0-0062-4dd8-adf6-1ea2192a3d35"). This GUID is set for both the item and the grouped radio identifier. This is also the same GUID that was registered as MyTool with the application. This is important as it causes MyTool activate when the button is clicked.

UserUI.xslt is for modifying any UI that is customizable, for example, adding buttons to existing toolbars or menus, or creating new toolbars for the tools, etc.

<!--Add tool item to the Toolbox--><xsl:templatematch="//commandBarData[@guid='7c905e2a-cb64-4ba1-aff0-c306f392680c']/toolbar"><xsl:apply-templatesmode="insert-item" select="."><xsl:with-paramname="content"><xsl:iftest="not(./item[@guidRef='6b5b83bb-e7b8-4f9d-8dfd-36f59bf545cf'])"><!--Only insert if its not already there--><itemguidRef="6b5b83bb-e7b8-4f9d-8dfd-36f59bf545cf"/></xsl:if></xsl:with-param></xsl:apply-templates></xsl:template>

The first section adds the new tool button to the end of the Toolbox. It makes use of template the helper insert-item also defined in the XSLT. The second section defines a new property bar mode for the tool. The guid "fd9a53f7-05cc-4cdc-b2ad-0fd6a7ea3480" is unique for this tool as well, and in MyTool::StartAtState(), you'll find the following line:

This tells the host application that we want to use this property bar when the tool is selected. The items on this sample property bar mode come from the application, mostly from the real line tool. Custom items can be created and included here as well.

The Resources

The three types of resources that can be defined are icons, cursors and strings. The config.xml ties a GUID for an item to a particular resource. In this case we tie "b17f7ca0-0062-4dd8-adf6-1ea2192a3d35" to string "10223" and icon "104. These resources can be found in the project by double-clicking on resources.rct.

Note: It may be easier to create icons using an external editor instead of using the built-in editor and then use "Add Resource", "Icon", Import.

The APIs

Below is a list of all of the new functions added to the CorelDRAW X7.1 and Corel DESIGNER X7 object model:

Class

API(s)

Description

Application

ActiveToolStateGuid [get,set]

This is a replacement for ActiveTool. It uses a GUID to identify the tool. Unlike ActiveTool, it can be used to get or set any state.

RegisterToolState, UnregisterToolState

This allows third parties to register or unregister custom tools with CorelDRAW. UnregisterToolState does not need to be called before shutdown. RegisterToolState can be called multiple times with the same tool (e.g. if the code has been updated)

CreateOnScreenCurve, CreateOnScreenHandle, CreateOnScreenText

Helper function to create an on screen curve, handle or text that is xor'd onto the view

Math

Object that provides math utility functions

RegisterUserApplicationPreference

This allows third parties to register custom application preferences. Application preferences persist after shutdown and are stored with the workspace. They can be access via the AppPrefMgr datasource. They can also be bound to UI within the application. They support most basic types (int, string, double, bool) and Color

GetApplicationPreferenceValue, SetApplicationPreferenceValue

Get or set any application preference

Document

CreateCurveFitToPoints, CreateCurveFitToPointsAndCusps

This function creates a Curve that is fit to a Points array.

SampleColorAtPoint, SampleColorInArea

This function retrieves a color at a given point (or area) in the document

Curve

AppendSubpathFitToPoints, AppendSubpathFitToPointsAndCusps

This appends a new curve subpath that is fit to a Points array

ApplyTransformMatrix

This method transforms the curve by a TransformMatrix

AppendSubpathFromPoints

Creates line segments from the points array

CreateCurveMappedToStroke

Creates a curve that is this curve mapped to a stroke, similar to artistic media

CreateCurveMappedToStrokeAndReferenceLine

Creates a curve that is this curve mapped to a stroke and reference line, similar to artistic media

AutoReduceNodes

Reduces the number of nodes in a curve based on a tolerance value

JoinTouchingSubpaths

Connects any subpaths that touch

AppendSubpathCircle

Creates a circle subpath

AppendSubpathRectangle

Creates a rectangle subpath

AppendSubpathThreePointArc

Creates a 3-point arc subpath

SelfWeldClosedSubpaths

Self welds any closed subpaths

Window

ScreenDistanceToDocumentDistance

Converts a screen distance in pixels to document unit distance. This used to be in Math.

DocumentDistanceToScreenDistance

Converts document unit distance to a screen distance in pixels

Node

GetPoint, SetPoint

Get or set a position of a node using a Point

Segment

GetPerpendicularVectorAt

Get a perpendicular vector at a position on the segment

GetTangentVectorAt

Get a tangent vector at a position on the segment

GetPointAt

Get a point from a position on the segment

Subpath

EqualDivide

Divide the subpath into equal length subpaths

GetEvenlySpacedPoints

Get a PointRange of points evenly spaced along the subpath

GetPerpendicularVectorAt

Get a perpendicular vector at a position on the subpath

GetTangentVectorAt

Get a tangent vector at a position on the subpath

GetPointAt

Get a point from a position on the subpath

Shape

TransformationMatrix [get, set]

Gets or sets the transformation applied to the shape. This is a replacement for GetMatrix, SetMatrix which do not package up the matrix in an object.

ApplyTransformMatrix

This method transforms the shape by a TransformMatrix

Color

IsColorStyle

Determines if the color is a color style.

ColorStyleName

Returns the name of the color style if the color is a color style, otherwise empty.

ModifyColorStyleColor

If this color is a color style, this function modifies the underlying color style (i.e. all colors in the document referencing the color style will change). If changeWholeHarmony is true, all colors in the same harmony will change similar to the wheel in the color styles docker. If the color is a rule-based harmony, the whole harmony always changes, but the saturation only changes if changeWholeHarmony is true.

StyleSheet

AllColorStyles

Gets an array of all color styles in the document

CreateColorStyle

Creates a new color style

DeleteAllColorStyles

Deletes all color styles in the document

DeleteColorStyle

Deletes a specific color style in the document

RenameColorStyle

Renames a color style in the document

OnScreenCurve - This object represents an xor'd curve that is drawn within the view

Show, Hide

Show/Hide the curve.

SetPen, SetNoPen

Set the width and color of the curve

SetBrush, SetNoBrush

Set the fill of the curve

SetCurve, SetLine, SetRectangle, SetCircle, SetPoints

Set the curve

OnScreenHandle - This object represents an xor'd handle glyph that is drawn within the view

Show, Hide

Show/Hide the handle.

SetHandleColor

Sets the color of the handle

SetPosition

Sets the position of the handle

UpdateHotTracking

The handle can be draw larger when the mouse is over it, this function allows for this.

IsHotTracked

Determines if the handle is hottracking

IsOnHandle

Determines is a given point is over the handle

OnScreenText - This object represents an xor'd text that is drawn within the view

Show, Hide

Show/Hide the text.

SetTextColor

Set the text color

SetTextAndPosition

Set the text and position of the text

SetText

Set only the text

SetPixelOffset

Set the the amount in pixels to offset the text by

UpdatePosition

Update only the position of the text

ToolStateAttributes - This object provides several attributes and helper functions for custom tools

PropertyBarGuid

Get/Set the guid for the tool's property bar

ContextMenuGuid [get, set]

Get/Set the guid for the tool's context menu

UseTabletPressure [get, set]

Determines if the tools should be collecting pressure data

AllowTempPickState [get, set]

Determines if the tool can resize objects using the resize handles

AllowAutopan [get, set]

Determines if the tool allows autopan while dragging

AllowContextMenu [get, set]

Determines if the tool should pop up a context menu with the right mouse click

CanUpdateSelectionOnMouseClick [get, set]

Determines if the tool can select different objects when a click happens

DeselectOnLButtonDown [get, set]

Determines if the tool should de-select the current shape when the left mouse is clicked

EnterGraceStateOnLButtonDown [get, set]

Determines if the tool should enter a grace state when the left mouse button is clicked. This is useful to determine if a click or click+drag is happening.

StatusInfo

Sets the status bar tool string

SetCursor

Sets the current cursor

SetCursorGuid

Sets the current cursor using a resource GUID (which can be exposed via the config.xml file of an addon)

StartTimer

Starts a timer that calls into the tool

StopTimer

Stops a timer

SnapMouse

Snaps a mouse position using current snapping settings

AnchoredSnapMouse

Snaps a mouse position using current snapping settings, and allows for more advanced snapping (such as snapping a line to a perpendicular)

ConstrainMouse

Uses the current constrain settings to constrain to an angle

IsKeyDown

Determines if a given key is held

CurrentPressure

Returns the current pen pressure between 0 and 1.

ToolState - This is an object that must be implemented and registered to create custom tools

OnStartState

Callback when the tool is activated

OnExitState

Callback when the tool is deactivated

OnMouseMove

Callback when the mouse is moved

OnLButtonDown

Callback when the left mouse button is pressed

OnLButtonDownLeaveGrace

Callback when the left mouse button is pressed and a small amount of time has passed or the mouse has been moved a short distance

OnLButtonUp

Callback when the left mouse button is released

OnLButtonDblClick

Callback when the left mouse button is double clicked

OnClick

Callback when the mouse has been clicked. New parameter, no longer returns boolean.

OnRButtonDown

Callback when the right mouse button has been pressed

OnRButtonUp

Callback when the right mouse button has been released

OnKeyDown

Callback when a key is pressed

OnKeyUp

Callback when a key is released

OnDelete

Callback when the Delete key is pressed and released

OnAbort

Callback when the ESC key is pressed and released

OnCommit

Callback when IsDrawing is true and the user presses enter or space

OnSnapMouse

Callback to handle snapping

OnTimer

Callback when a registered timer event is invoked

IsDrawing

Callback to tell the tool that we're drawing. Several small behaviour changes happen when we are drawing, for example, autopan will activate when the user moves the mouse close to the edge of the view.

Point - object to wrap a simple x and y position

x, y [get, set]

The coordinate

Add, Subtract

Shift the x and y by a vector offset

DistanceTo

Get the distance to another point

GetCopy

Get a copy of the point

PointRange - object that hold multiple points

Item [get, set]

Get or set a point within the array

First, Last

Get the first or last point within the array

Count

Get the number of points within the array

AddPoint, AddPointXY

Add a point to the end of the array

InsertPoint, AddPoints, InsertPoints

Add and insert points into the array

Remove

Remove a point from the array

RemoveRange

Remove several points in the array

RemoveAll

Clear the array

RemoveAdjacentDuplicates

Removes a point where the next point is the same

Reverse

Reverses the order of the points

Smoothen

Run a smoothing operation of the points. Renamed

GetCopy

Get a copy of the PointRange

Vector - object to wrap a simple x and y vector

x, y [get, set]

The vector's x and y offset

Length [get, set]

Get or set the length of the vector

Angle [get, set]

Get or set the angle of the vector

GetOffsettedPoint

Given a point and a distance, creates a new point which is offsetted perpendicualr to the vector

Add, Subtract

Add or subtract vectors

MultiplyBy

Scale the vector

Negate

Negate the vector

Normalize

Set the vector's length to 1.0

AngleBetween

Gets the angle in degrees between the vector and another in counter clockwise direction

SmallAngleBetween

Gets the small angle in degrees between the vector and another

DotProduct

Computes the dot product between this vector and another

CrossProduct

Computes the cross product between this vector and another

SetFromPoints

Creates a vector from point A to B

ProjectOnto

Projects this vector onto another

GetCopy

Get a copy of the vector

TransformMatrix - object that stores a linear transformation matrix

d11, d12, d21, d22 [get, set]

The raw data that stores the transmations - please prefer not to use these

TranslationX, TranslationY [get, set]

Gets or sets the translation of the matrix

BasisXAxis, BasisYAxis [get, set]

Gets or sets the basis vectors for the matrix

Translation [get, set]

Gets or sets the translation for the matrix

SetToIdentity

Set the matrix to the identity

Invert

Inverts the matrix

TranslateBy, TranslateByVector, SetTranslation

Translates the matrix

Rotate

Rotates the matrix around (0, 0)

RotateAround

Rotates the matrix around a given point

Scale

Scales a matrix around (0, 0)

ScaleAround

Scales a matrix around a given point

Transform

Transforms a matrix by another

TransformAround

Transforms a matrix by another around a given point

TransformPoint, UntransformPoint

Transforms a point

TransformPoints, UntransformPoints

Transforms an array of points

TransformVector, UntransformVector

Transforms a vector

IsIdentity

Determine if the matrix is the identity matrix

IsSkewedOrRotatedOrMirrored

Determine if the matrix is the skewed or rotated or mirrored

ContainsOnlyTranslation

Determines if the matrix is only translations

IsSkewedOrRotated

Determines if the matrix is skewed or rotated

IsScaledOrSkewedOrRotated

Determines if the matrix is scaled or skewed or rotated

IsOrthogonal

Determines if the matrix is orthagonal

IsOrthonormalAxisAligned

Determines if the matrix is ortho normal axis aligned

IsOrthonormal

Determines if the matrix is orthonormal

IsMirrored

Determines if the matrix is mirrored

IsScaled

Determines if the matrix is scaled

IsTranslated

Determines if the matrix is translated

GetCopy

Get a copy of the TransformMatrix

MathUtils - object provided by the application that provides several utility math functions

Interpolate

Creates a point that interpolates two given points

IntersectLineSegments

Gets the intersection point of two line segments - returns false if the lines don't intersect

DistanceToLineSegment

Gets the distance of a point to a line segment

ClosestPointToLineSegment

Gets the closest point to a line segment

IntersectInfiniteLines

Gets the intersection point of two lines - returns false if the lines are parallel

DistanceToInfiniteLine

Gets the distance of a point to a line

ClosestPointToInfiniteLine

Gets the closest point to a line

GetRandomReal

Gets a random double precision number

GetRandomInteger

Gets a random integer

FitLineToPoints

Fits a line to an array of points

MidPoint

Creates a point that bisects two given points

CreatePoint

Creates a point

CreateVector

Creates a vector

CreatePointRange

Creates a PointRange

CreateIdentityTransformMatrix

Creates an identity TransformMatrix

CreateRotationTransformMatrix

Creates a rotation TransformMatrix

CreateTranslationTransformMatrix

Creates a translation TransformMatrix

CreateScaleTransformMatrix

Creates a scale TransformMatrix

CreateLineSegmentTransformMatrix

Creates a TransformMatrix which when applied to the line (FromStart, FromEnd) will result in the line (ToStart, ToEnd)

Notes:

VBA tools will require delay load to be off, for this reason alone, it is recommended to use C# or C++. You can also write your tool as a VB dll if that's the language you're most comfortable in.

The UserUI.xslt is only loaded once to update the workspace. If while developing the tool, this file needs to be changed, you will need to reset the workspace by holding F8. It is therefore recommended to work in a temporary workspace while you develop your tool.

The AppUI.xslt file is loaded every time so any changes made will be seen immediately.

Users of CorelDRAW X7.1 or higher must be signed in with a valid CorelDRAW Standard or Premium membership to use a custom addon tool. Standard membership is free for all customers who have purchased the CorelDRAW Graphics Suite X7.

If both 32 and 64-bit versions of CorelDRAW installed, the Visual Studio project template will select the 64-bit version.