PDA

View Full Version : Images in custom Menu control



Roderick
08-01-2013, 02:37 PM
I'm using Word 2007 and Windows 7.

I've created a custom menu button which shows six items for a user to choose one. Selecting one of the menu items sets the number of Table of Contents (TOC) levels to display in the active document. The default number is six.

So if a user selects, say, the item which reads "3 levels"from the menu control then the appropriate onAction callback changes a CustomDocumentProperty to "3" and the TOC updates to three visible levels.

So far, so good . . .

Now comes the bit where I get stuck: I want to have a check mark appear next to the level selected on the control menu so that the user can see how many levels they have selected whilst all the others in the menu list do not have any graphic showing.

I'm using a general "getImage" attribute for the six buttons in the menu.

This can be shown by posting the relevant XML code below


<!--Sets TOC Levels-->
<menu id="mnuTOCLevels"
imageMso="TableOfContentsGallery"
label="Set TOC Levels"
size="large"
keytip="L"
itemSize="normal">

<menuSeparator id="SepLevels"
title="Select number of levels" />

<button id="SixLevels"
label="6 Levels (Default)"
screentip="Sets the TOC levels"
supertip="Displays six levels in this document's Table of Contents.

This is the default setting for the document."
getImage="mnuTOCLevels_GetImage"
onAction="mnuTOCLevels_OnAction" />

<button id="FiveLevels"
label="5 Levels"
screentip="Sets the TOC levels"
supertip="Displays five levels in this document's Table of Contents."
getImage="mnuTOCLevels_GetImage"
onAction="mnuTOCLevels_OnAction" />

<button id="FourLevels"
label="4 Levels"
screentip="Sets the TOC levels"
supertip="Displays four levels in this document's Table of Contents."
getImage="mnuTOCLevels_GetImage"
onAction="mnuTOCLevels_OnAction" />

<button id="ThreeLevels"
label="3 Levels"
screentip="Sets the TOC levels"
supertip="Displays three levels in this document's Table of Contents."
getImage="mnuTOCLevels_GetImage"
onAction="mnuTOCLevels_OnAction" />

<button id="TwoLevels"
label="2 Levels"
screentip="Sets the TOC levels"
supertip="Displays two levels in this document's Table of Contents."
getImage="mnuTOCLevels_GetImage"
onAction="mnuTOCLevels_OnAction" />

<button id="OneLevels"
label="1 Level"
screentip="Sets the TOC levels"
supertip="Displays one level in this document's Table of Contents."
getImage="mnuTOCLevels_GetImage"
onAction="mnuTOCLevels_OnAction" />

</menu>

Below is the callback routine to set the TOC levels and update the fields in the document. This is working well and with no problems.


'Callback for SixLevels onAction
Sub mnuTOCLevels_OnAction(control As IRibbonControl)
Select Case control.id
'sets the appropriate document property and then updates the fields in the document
Case Is = "SixLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 6
Call UpdateFields
Case Is = "FiveLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 5
Call UpdateFields
Case Is = "FourLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 4
Call UpdateFields
Case Is = "ThreeLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 3
Call UpdateFields
Case Is = "TwoLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 2
Call UpdateFields
Case Is = "OneLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 1
Call UpdateFields
End Select
End Sub

Following is the code for the getImage callback which is giving me the trouble. I want just one check mark to appear next to to the one which matches the saved document property. At the moment I get one checkmark against every item on the menu!

I know what is going wrong but I cannot think of a way to achieve the correct process.


'Callback for SixLevels getImage
Sub mnuTOCLevels_GetImage(control As IRibbonControl, ByRef returnedVal)
Dim oTOCLevels As Integer
'gets the value of TOC Levels custom property
oTOCLevels = ActiveDocument.CustomDocumentProperties("TOC Levels")
Select Case oTOCLevels
Case Is = 6
returnedVal = "AcceptInvitation"
Case Is = 5
returnedVal = "AcceptInvitation"
Case Is = 4
returnedVal = "AcceptInvitation"
Case Is = 3
returnedVal = "AcceptInvitation"
Case Is = 2
returnedVal = "AcceptInvitation"
Case Is = 1
returnedVal = "AcceptInvitation"
End Select
End Sub

I've kicked the code about in the above procedure but without any luck.

Can anyone offer ideas how I can get just one check mark on the correct level and leave all the others blank. please?

Thanks for any help

Roderick

Paul_Hossler
08-01-2013, 03:23 PM
quick guess --

1. You need a onLoad call back to capture your ribbon object
2. Invalidate the control after each time you select a different TOC level
3. In each of the 6 TOC cases, you probably need to clear the other 5 levels that are not selected

Post your docm here (don't need any text) if you want us to look at it

Paul

Roderick
08-05-2013, 06:13 AM
Thanks Paul for your thoughts. Sorry I haven't been back sooner but circumstances forced me to concentrate on other things after I had written of my challenge.

Today, I've started to follow your thoughts: I do have an onLoad callback for my Ribbon object and that works OK as I have over twelve different custom controls and all are working fine. I'm also invalidating each control as I select TOC levels and that side of things also works OK. Each TOC level is getting recorded correctly (I'm using a message box to simulate the updating of the TOC fields - saves time).

I've been working on your thought about clearing the remaining TOC cases and getting completely muddled. I can set one TOC level not to have the picture of the check mark showing but I cannot get the other ones to follow suit seeing that a Case statement can only handle one control.id. Whatever permutation I try I seem to hit a brick wall.

I'm sure I'm missing something obvious but I cannot see what it is.

Here is the code for my Ribbon callback:

Dim myRevisions As Boolean
Public myRibbon As IRibbonUI
Sub rxIRibbonUI_onLoad(ByVal ribbon As Office.IRibbonUI)
Set myRibbon = ribbon
'now goes back to the top of the document
ActiveDocument.Bookmarks("\StartofDoc").Select
Selection.Collapse
End Sub

Here is the callback procedure for setting the TOC levels required:

'Callback for SixLevels onAction
Sub mnuTOCLevels_OnAction(control As IRibbonControl)
Select Case control.id
'sets the appropriate document property and then updates the fields in the document
Case Is = "SixLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 6
' Call UpdateFields
MsgBox "Your TOC is now set to display 6 levels"
Case Is = "FiveLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 5
MsgBox "Your TOC is now set to display 5 levels"
Case Is = "FourLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 4
MsgBox "Your TOC is now set to display 4 levels"
Case Is = "ThreeLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 3
MsgBox "Your TOC is now set to display 3 levels"
Case Is = "TwoLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 2
MsgBox "Your TOC is now set to display 2 levels"
Case Is = "OneLevels"
ActiveDocument.CustomDocumentProperties("TOC Levels") = 1
MsgBox "Your TOC is now set to display 1 level"
End Select
'now invalidate the control
myRibbon.InvalidateControl (control.id)
End Sub

... and here is my messed-about code trying to set the required picture for the level of TOC which has been selected. I think I've also overcooked it with control invalidation!


'Callback for SixLevels getImage
Sub mnuTOCLevels_GetImage(control As IRibbonControl, ByRef returnedVal)
Dim oTOCLevels As Integer
'gets the value of TOC Levels custom property
oTOCLevels = ActiveDocument.CustomDocumentProperties("TOC Levels")

Select Case control.id
Case Is = "SixLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FiveLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FourLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "ThreeLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "TwoLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "OneLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
End Select

Select Case oTOCLevels
Case Is = 6
Select Case control.id
Case Is = "SixLevels"
returnedVal = "AcceptInvitation"
myRibbon.InvalidateControl (control.id)
Case Is = "FiveLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FourLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "ThreeLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "TwoLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "OneLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
End Select
myRibbon.InvalidateControl (control.id)

Case Is = 5
Select Case control.id
Case Is = "SixLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FiveLevels"
returnedVal = "AcceptInvitation"
myRibbon.InvalidateControl (control.id)
Case Is = "FourLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "ThreeLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "TwoLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "OneLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
End Select
myRibbon.InvalidateControl (control.id)

Case Is = 4
Select Case control.id
Case Is = "SixLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FiveLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FourLevels"
returnedVal = "AcceptInvitation"
myRibbon.InvalidateControl (control.id)
Case Is = "ThreeLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "TwoLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "OneLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
End Select
myRibbon.InvalidateControl (control.id)

Case Is = 3
Select Case control.id
Case Is = "SixLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FiveLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FourLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "ThreeLevels"
returnedVal = "AcceptInvitation"
myRibbon.InvalidateControl (control.id)
Case Is = "TwoLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "OneLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
End Select
myRibbon.InvalidateControl (control.id)

Case Is = 2
Select Case control.id
Case Is = "SixLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FiveLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FourLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "ThreeLevels"
returnedVal = ""
Case Is = "TwoLevels"
returnedVal = "AcceptInvitation"
myRibbon.InvalidateControl (control.id)
Case Is = "OneLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
End Select
myRibbon.InvalidateControl (control.id)

Case Is = 1
Select Case control.id
Case Is = "SixLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FiveLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "FourLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "ThreeLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "TwoLevels"
returnedVal = ""
myRibbon.InvalidateControl (control.id)
Case Is = "OneLevels"
returnedVal = "AcceptInvitation"
myRibbon.InvalidateControl (control.id)
End Select
myRibbon.InvalidateControl (control.id)

End Select

End Sub

What I have been trying to achieve is to clear the other five levels of control.id's of pictures when one level is selected. And all in one Case statement.

Roderick

Paul_Hossler
08-07-2013, 06:47 AM
I think I've also overcooked it with control invalidation!

Looks well done to me


could you post a sample document with the XML and the callbacks?

this would make it easier to verify since I wouldn't have to make sure that I'm recreating your test correctly

Paul

Roderick
08-07-2013, 11:22 AM
Looks well done to me


could you post a sample document with the XML and the callbacks?

this would make it easier to verify since I wouldn't have to make sure that I'm recreating your test correctly

Paul

Thanks again Paul.

In the interim period I've been playing with IF...Then statements to clear the non-required check marks but with no effect and much frustration.

Using STOP commands in the code I've noticed that the onAction events in the XML get done just once depending on which button is selected on the menu. However, when it comes to the getImage event in the XML it insists on going to every one of those events regardless of what I try to do prevent it and sticks a check mark on every item.

I've attached a .docm document in the hope that it will make it easier to see where my thinking is going awry.

Roderick

10384

Paul_Hossler
08-07-2013, 08:16 PM
Try this and see how it works for you. I added / move some to the Doc Open event



Option Explicit
Dim myRevisions As Boolean
Public myRibbon As IRibbonUI
Public oTOCLevels As Integer
Sub rxIRibbonUI_onLoad(ByVal ribbon As Office.IRibbonUI)
Set myRibbon = ribbon
'now goes back to the top of the document ------ moved to Document_Open event, plus somemore
'ActiveDocument.Bookmarks("\StartofDoc").Select
'Selection.Collapse
Call myRibbon.Invalidate

End Sub

'Callback for SixLevels onAction
Sub mnuTOCLevels_OnAction(control As IRibbonControl)
Select Case control.ID
'sets the appropriate document property and then updates the fields in the document
Case Is = "SixLevels"
oTOCLevels = 6
MsgBox "Your TOC is now set to display 6 levels"
Case Is = "FiveLevels"
oTOCLevels = 5
MsgBox "Your TOC is now set to display 5 levels"
Case Is = "FourLevels"
oTOCLevels = 4
MsgBox "Your TOC is now set to display 4 levels"
Case Is = "ThreeLevels"
oTOCLevels = 3
MsgBox "Your TOC is now set to display 3 levels"
Case Is = "TwoLevels"
oTOCLevels = 2
MsgBox "Your TOC is now set to display 2 levels"
Case Is = "OneLevels"
oTOCLevels = 1
MsgBox "Your TOC is now set to display 1 level"
End Select

ActiveDocument.CustomDocumentProperties("TOC Levels") = oTOCLevels
'let Word know document is "dirty," so it will save the new Custom Document Property.
ActiveDocument.Saved = False

'now invalidate the control
Call myRibbon.InvalidateControl("SixLevels")
Call myRibbon.InvalidateControl("FiveLevels")
Call myRibbon.InvalidateControl("FourLevels")
Call myRibbon.InvalidateControl("ThreeLevels")
Call myRibbon.InvalidateControl("TwoLevels")
Call myRibbon.InvalidateControl("OneLevels")
End Sub

'Callback for SixLevels getImage
Sub mnuTOCLevels_GetImage(control As IRibbonControl, ByRef returnedVal)

returnedVal = False

Select Case control.ID
Case Is = "SixLevels"
If oTOCLevels = 6 Then returnedVal = "AcceptInvitation"
Case Is = "FiveLevels"
If oTOCLevels = 5 Then returnedVal = "AcceptInvitation"
Case Is = "FourLevels"
If oTOCLevels = 4 Then returnedVal = "AcceptInvitation"
Case Is = "ThreeLevels"
If oTOCLevels = 3 Then returnedVal = "AcceptInvitation"
Case Is = "TwoLevels"
If oTOCLevels = 2 Then returnedVal = "AcceptInvitation"
Case Is = "OneLevels"
If oTOCLevels = 1 Then returnedVal = "AcceptInvitation"
End Select
End Sub



Paul

Roderick
08-08-2013, 02:20 PM
It works! Thank you so much Paul for your guidance in the matter. I just made a couple of additions to the code to now actually change the TOC levels, added it to the template and it works a dream.

Thanks again.

Roderick