OberonPlace.com Forums  

Go Back   OberonPlace.com Forums > Developer Forums > VBA > CorelDRAW/Corel DESIGNER VBA

Thread Tools Search this Thread Display Modes
Old 27-10-2004, 11:07
Posts: n/a
Default activeselection cloning

I would like to clone a base shape a few times to get several texts centered on copies of this base shape and each text grouped with its copy of the base shape. The following code used to work on CorelDraw 11:

Sub SelectionClone()
Dim cdr As CorelDRAW.Application
Dim rectdoc As CorelDRAW.Document
Dim t As CorelDRAW.Shape
Dim t_x As Double, t_y As Double, t_w As Double, t_h As Double
Dim r_x As Double, r_y As Double, r_w As Double, r_h As Double
Dim shPrice As CorelDRAW.Shape

Set cdr = CreateObject("CorelDRAW.Application.12")
cdr.ActiveDocument.ReferencePoint = cdrTopLeft
cdr.ActiveDocument.Unit = cdrPixel
cdr.Visible = True

Dim shrect As CorelDRAW.Shape, shrectclone As CorelDRAW.Shape

' open base shape file
Set rectdoc = cdr.OpenDocument("C:\rectangle.cdr")
Set shrect = ActiveSelection.Clone

Set t = cdr.ActiveLayer.CreateArtisticText(0, 0, "9.99")

' does conversions to get the bounding box around a (white) text
t.Fill.UniformColor.CMYKAssign 0, 0, 0, 0

' get bounding box around text
t.GetBoundingBox t_x, t_y, t_w, t_h

' clone the base shape
Set shrectclone = shrect.Clone
' get bounding box around base shape
shrectclone.GetBoundingBox r_x, r_y, r_w, r_h

' move base shape to center it on the text
shrectclone.PositionX = t_x + (t_w - r_w) / 2
shrectclone.PositionY = t_y + 2 * t_h + (t_h - r_h) / 2

' group text and base shape
Set shPrice = cdr.ActiveSelection.Group

' move group
cdr.ActiveSelection.PositionX = 0
cdr.ActiveSelection.PositionY = 0

End Sub

Now that I have updated CorelDraw to version 12, it doesn't work anymore. When it gets to line

Set t = cdr.ActiveLayer.CreateArtisticText(0, 0, "9.99")

the shrect variable (holding the first clone of the base shape) is suddenly reassigned so that to point to the text object (t), so the next cloning command does clone text t instead of the base shape.

Does anyone know of any changes in VBA so that now this code couldn't work anymore? Hopefully this could be just a problem of bad coding that used to work in the previous version but that has been fixed in the new release. In this case I would like to know where my mistake is and how I could get the same (old) result with a correct coding.

I attached a copy of the cdr file that contains the base shape.

Attached Files
File Type: cdr rectangle.cdr (14.9 KB, 970 views)
Reply With Quote
Old 29-10-2004, 15:49
Alex's Avatar
Alex Alex is offline
Join Date: Nov 2002
Posts: 1,940
Blog Entries: 4
Default Re: activeselection cloning

This is because in CorelDRAW 12, if Clone (or Duplicate) is run on a selection shape, the returned shape is the selection too (but now the cloned/duplicated objects are selected). Because Selection shape has very unique behavior in a sense that there is only one shape of this type per document and it always points to the currently selected shape(s).

Here is an example:

Sub TestSelection()
    Dim s1 As Shape
    Dim s2 As Shape
    ActiveLayer.CreateRectangle 0, 0, 2, 2
    Set s1 = ActiveSelection
    ActiveLayer.CreateEllipse 2, 2, 8, 4
    Set s2 = ActiveSelection
    s1.Rotate 10
    s2.Rotate 10
End Sub
At a glance you might think that the above code will create a rectangle and an ellipse and then rotate each by 10 degrees. But in fact, it's the ellipse which will be rotated by 20° instead. The reason being that both s1 and s2 point to the current selection. In order to fix this, you need to actually get a reference to the actual shape which is selected. You can get to it through the selection shape's Shapes collection:

ActiveSelection.Shapes(1) will give you the first selected shape. In case when there is only one shape in the selection you can use ActiveShape property which is a shortcut to ActiveSelection.Shapes(1):

Sub TestSelection2()
    Dim s1 As Shape
    Dim s2 As Shape
    ActiveLayer.CreateRectangle 0, 0, 2, 2
    Set s1 = ActiveShape
    ActiveLayer.CreateEllipse 2, 2, 8, 4
    Set s2 = ActiveShape
    s1.Rotate 10
    s2.Rotate 10
End Sub
Now this code will create the shapes and both of them will be rotated by 10°. Obviously, you should try not to rely on selections in your own code at all. It's always better to use the return values of functions and other ways of referencing shapes and leave the selection to communicate with the human user...

Here is how you can simplify the above code:

Sub TestSelection3()
    Dim s1 As Shape
    Dim s2 As Shape
    Set s1 = ActiveLayer.CreateRectangle(0, 0, 2, 2)
    Set s2 = ActiveLayer.CreateEllipse(2, 2, 8, 4)
    s1.Rotate 10
    s2.Rotate 10
End Sub
It is simpler and much more correct.

However, if the selection contains more than one shape in it, using ActiveShape is not the correct solution, because it will return just one object (that would be the last object added to the selection).

In this case you should use shape ranges. Basically, you can get a range from any shape collection:

Dim sr As ShapeRange
Set sr = ActiveSelection.Shapes.All
sr.Rotate 10
This way you create a static list of shapes that were in the selection at the time the code was executed. After shape range is created, it points to the same shapes even if the selection actually changes.

You can use ActiveSelectionRange method as a shortcut to ActiveSelection.Shapes.All:

Dim sr As ShapeRange
Set sr = ActiveSelectionRange
sr.Rotate 10
Now, to get back to your original problem with Clone method. To resolve the issue, you have two options:

1. If you know for sure that the selection contains only one shape in it, call Clone on the actual shape, not the selection shape:

Dim sClone As Shape
Set sClone = ActiveShape.Clone
2. If there might be more than one shape in the selection, you should use
CloneAsRange method which will return the list of cloned shapes as a range:

Dim sr As ShapeRange
Set sr = ActiveSelection.CloneAsRange
You can then work on the shapes in the range as if it was a single shape, or iterate through them, etc.

Oh, and one more thing, instead of cloning shapes and then moving the clones, use the optional parameters of Clone/CloneAsRange to specify the offset.

ActiveShape.Clone 0, 0
will clone the selected shape and place the clone exactly on top of the original... This works at least in CorelDRAW 12...
Reply With Quote
Old 05-11-2004, 09:59
Posts: n/a

Thanks Alex for your really complete (as always) answer.

Reply With Quote

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

All times are GMT -5. The time now is 07:52.

Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
Copyright © 2011, Oberonplace.com