How to add UI to Publisher for your macro code


In this post I wanted to cover something simple that might come up handy when trying to add custom controls to Publisher’s UI that can serve as entry points for your macro subroutines. For that, I created a simple macro that adds a new button to the “Objects” toolbar. Then it creates a new toolbar and adds a button there too. The button uses a custom icon and whenever you click it, it runs a macro subroutine that will insert a custom shape.  To be able to do that, we have to code a sub that will modify our UI and create the UI entry points for our functionality, then ensure that this sub runs whenever we open our document:


Sub AddMyEntryPoint()


    Dim objectsCommandBar As commanBar


    Dim myCommandBar As commandBar


    Dim myButton1 As CommandBarButton


    Dim myButton2 As CommandBarButton


    Dim app As Application


    Dim picPicture As IPictureDisp


    Dim picMask As IPictureDisp


       


    ‘Find the Objects toolbar


    Set app = Application


    Set objectsCommandBar = app.CommandBars(“Objects”)


    ‘Create a new toolbar and dock it to the top


    Set myCommandBar = app.CommandBars.Add(“Insert Shape”, MsoBarPosition.msoBarTop, False, True)


    ‘Add a button to the objects command bar


    Set myButton1 = objectsCommandBar.Controls.Add(MsoControlType.msoControlButton, , , , True)


    ‘Add a buttom to my custom toolbar


    Set myButton2 = myCommandBar.Controls.Add(MsoControlType.msoControlButton, , , , True)


 


    ‘Load the pictures we’ll use for our button


    Set picPicture = stdole.StdFunctions.LoadPicture(“c:\funkyimage.bmp”)


    Set picMask = stdole.StdFunctions.LoadPicture(“c:\funkymask.bmp”)


   


    myButton1.Picture = picPicture


    myButton1.Mask = picMask


    myButton2.Picture = picPicture


    myButton2.Mask = picMask


    myButton1.OnAction = “DrawMyFunkyShape”


    myButton2.OnAction = “DrawMyFunkyShape”


    myCommandBar.Visible = True


End Sub


 


The first thing we need to do is to find the toolbar where we want to put our entry point in.  In this case, since I’m inserting a shape, I’ll add my entry point to the “Objects” toolbar:


Set objectsCommandBar = app.CommandBars(“Objects”)


I also want to add a toolbar of my own to add the button there as well.  We want to name our toolbar “Insert Shape”, dock it to the top,  make it not a menu bar and make it so that it removes itself when the document is closed (by forcing it to be temporary)


    Set myCommandBar = app.CommandBars.Add (“Insert Shape”, MsoBarPosition.msoBarTop, False, True)


 


The next step is to actually add the buttons that we’ll link to our sub. For that we’ll use the default values for most of the parameters except for temporary, which we’ll set to True so that the buttons are removed when we close the file.


 


    Set myButton1 = objectsCommandBar.Controls.Add(MsoControlType.msoControlButton, , , , True)


    Set myButton2 = myCommandBar.Controls.Add (MsoControlType.msoControlButton, , , , True)


 


 


Once we have our buttons, now we need to give them an icon and an action:


For the icons, you want to create 2 bitmaps, each 16 pixels by 16 pixels in size. One of the bitmaps represents the main icon the other one the mask. (So that we can make some of the pixels transparent). In my code I hardcode the paths to the images to my “c:” drive just for sample purposes.


 


    Set picPicture = stdole.StdFunctions.LoadPicture(“c:\funkyimage.bmp”)


    Set picMask = stdole.StdFunctions.LoadPicture(“c:\funkymask.bmp”)


   


    myButton1.Picture = picPicture


    myButton1.Mask = picMask


    myButton2.Picture = picPicture


    myButton2.Mask = picMask


 


The OnAction property on the button contains the name of the sub that will be run when the button is clicked.


 


    myButton1.OnAction = “DrawMyFunkyShape”


    myButton2.OnAction = “DrawMyFunkyShape”


    myCommandBar.Visible = True


 


Now, we need to ensure that this method runs whenever we open the file. For that, we need to use the Open event in the document.


Private Sub Document_Open()


    AddMyEntryPoint


End Sub


 


Finally, we need to implement the method that will execute our action. In our example, the method that we are using will insert a custom shape in the middle of the page. The shape is composed of a polyline and some ovals that get grouped to create the final shape. Since the focus of this example is not the actual sub that gets called, but the creation of the UI entry points, I’m not going to go into detail for this subroutine. Here is the code:


 


Sub DrawMyFunkyShape()


   


    ‘Insert our funky shape on the middle of the page


    Dim app As Application


    Dim centerX As Single


    Dim centerY As Single


    Dim shapeHeight As Single


    Dim shapeWidth As Single


    Dim body As shape


    Dim rightEye As shape


    Dim leftEye As shape


    Dim rightEar As shape


    Dim leftEar As shape


    Dim initialX As Single


    Dim initialY As Single


    Dim shapePoints(1 To 11, 1 To 2) As Single


    Dim eyeWidth As Single


    Dim eyeHeight As Single


    Dim earWidth As Single


    Dim earHeight As Single


    eyeWidth = 10


    eyeHeight = 5


    earWidth = 18


    earHeight = 9


    shapeHeight = 100


    shapeWidth = 100


    Set app = Application


    centerX = app.ActiveDocument.ActiveView.ActivePage.Width / 2


    centerY = app.ActiveDocument.ActiveView.ActivePage.Height / 2


    initialX = centerX – shapeWidth / 2


    initialY = centerY – shapeHeight / 2


   


    ‘Our funky shape will be a polyline grouped with 4 ovals: 2 for the eyes and 2 for the ears


    shapePoints(1, 1) = initialX


    shapePoints(1, 2) = initialY


    shapePoints(2, 1) = initialX + shapeWidth


    shapePoints(2, 2) = initialY


    shapePoints(3, 1) = initialX + ((shapeWidth / 3) * 2)


    shapePoints(3, 2) = initialY – ((shapeHeight / 3) * 2)


    shapePoints(4, 1) = initialX + shapeWidth


    shapePoints(4, 2) = initialY – (((shapeHeight / 3) * 2) + (shapeHeight / 12))


    shapePoints(5, 1) = initialX + shapeWidth


    shapePoints(5, 2) = initialY – (((shapeHeight / 3) * 2) + ((shapeHeight / 12) * 2))


    shapePoints(6, 1) = initialX + ((shapeWidth / 4) * 3)


    shapePoints(6, 2) = initialY – shapeHeight


    shapePoints(7, 1) = initialX + (shapeWidth / 4)


    shapePoints(7, 2) = initialY – shapeHeight


    shapePoints(8, 1) = initialX


    shapePoints(8, 2) = initialY – (((shapeHeight / 3) * 2) + ((shapeHeight / 12) * 2))


    shapePoints(9, 1) = initialX


    shapePoints(9, 2) = initialY – (((shapeHeight / 3) * 2) + (shapeHeight / 12))


    shapePoints(10, 1) = initialX + (shapeWidth / 3)


    shapePoints(10, 2) = initialY – ((shapeHeight / 3) * 2)


    shapePoints(11, 1) = initialX


    shapePoints(11, 2) = initialY


    ‘Add the body


    Set body = app.ActiveDocument.ActiveView.ActivePage.Shapes.AddPolyline(shapePoints)


    ‘Add the eyes and ears


    Set rightEye = app.ActiveDocument.ActiveView.ActivePage.Shapes.AddShape(msoShapeOval, initialX + ((shapeWidth / 3) * 2), initialY – ((shapeHeight / 12) * 10), eyeWidth, eyeHeight)


    Set leftEye = app.ActiveDocument.ActiveView.ActivePage.Shapes.AddShape(msoShapeOval, initialX + (shapeWidth / 3) – eyeWidth, initialY – ((shapeHeight / 12) * 10), eyeWidth, eyeHeight)


    Set rightEar = app.ActiveDocument.ActiveView.ActivePage.Shapes.AddShape(msoShapeOval, initialX + ((shapeWidth / 4) * 3), (initialY – shapeHeight) – (earHeight / 2), earWidth, earHeight)


    Set leftEar = app.ActiveDocument.ActiveView.ActivePage.Shapes.AddShape(msoShapeOval, initialX + (shapeWidth / 4) – earWidth, (initialY – shapeHeight) – (earHeight / 2), earWidth, earHeight)


 


    ‘Fills


    ‘Blue Fill


    body.Fill.ForeColor.RGB = RGB(0, 0, 255)


    rightEar.Fill.ForeColor.RGB = RGB(0, 0, 255)


    leftEar.Fill.ForeColor.RGB = RGB(0, 0, 255)


    ‘White Fill


    rightEye.Fill.ForeColor.RGB = RGB(255, 255, 255)


    leftEye.Fill.ForeColor.RGB = RGB(255, 255, 255)


    ‘Select all and group


    body.Select (True)


    rightEar.Select (False)


    leftEar.Select (False)


    rightEye.Select (False)


    leftEye.Select (False)


    app.Selection.ShapeRange.Group


   


End Sub


 


Here is a screenshot of what the final results looks like:


View of custon UI


 


Then, after you click on the button, we call the sub and our custom shape gets inserted into the document


Funky shape on the page


 


Hopefully you’ll find this useful when working with macros in Publisher. You can find the publication with the macro and the icons that I’m using from this location.


 


About the contributor: Miguel Gonzalez-Gongora  is a Software Design Engineer in Test and has worked for Microsoft for 4  years, all of them in the Publisher Test Team. Besides writing macros using Publisher, he is the resident expert in tequila in all its permutations.

Comments (0)