Outlook: Reset ToggleButton to default

Add-in Express™ Support Service
That's what is more important than anything else

Outlook: Reset ToggleButton to default
 
André Gerards




Posts: 10
Joined: 2017-11-15
Hello everybody,

I try to develop an Outlook 2010-Com-Add-In with VS2017 (VB.net).

The request:
A user has to decide whether his mail has to be encrypted or not. So I integrated (Inspector: Outlook.MailItem) on TabNewMailMessage a group with three togglebuttons - for the possible states: not, only this time, always encrypted). If one togglebutton is pressed, the other ones get unpressed ... so far, so good.
The default value is defined by his department an I got this information from the AD - so for example it always has to be 'always encrypted'. The user is able to override this default with each mail.
(If you think about why there are three different states ... for just one mail there are only two states - encrypt or not, please don't think about, for there are some more internal settings that depends on.)

So, everythings fine for the first mail.
But with the next mail or opening a second mail-window the default button has to reset again. And that's the problem. Outlook seems to cache the last state of the togglebuttons and restores it with each new window.
I can't reload the ribbon using _NewInspector-procedure. This 'event' is only once fired.

I'm getting desperate and frustrated for I'm not able to catch the event that gives me the oportunity to reload the ribbons defaults.

Please, can you help me? Have you any ideas how to handle this problem?

Thanks very much form Germany
André
Posted 16 Nov, 2017 11:37:47 Top
Andrei Smolin


Add-in Express team


Posts: 14582
Joined: 2006-05-11
Hello André,

You should start with checking sections Updating ribbon controls at run time and Determining a ribbon control's context at https://www.add-in-express.com/docs/net-ribbon-components.php. The first of them describes the mechanism that you need to use in your case; please refer to the PropertyChange event. The second section describes how you can use the information that the Ribbon API provides to identify the context in which your Ribbon control is displayed/clicked.

Also, you should be sure that that your code releases every COM object it creates. Actually, every call returning an object of the type declared on the Outlook object model (any Office model!) creates a COM object. And you need to release all of them! See also Releasing COM objects

Finally, there are what we call "cached inspectors" in Outlook. When Outlook takes such an inspector from the cache, it doesn't call PropertyChanging for the Ribbon controls of that inspector. To bypass this issue, try to call ADXRibbonTab.Invalidate e.g. in the InspectorActivate event.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 17 Nov, 2017 06:54:38 Top
André Gerards




Posts: 10
Joined: 2017-11-15
Hello Andrei,

thanks sofar for this input. I'll try to implement it on weekend. I suppose, you will hear from me again :)
Regards, André
Posted 17 Nov, 2017 08:19:36 Top
Andrei Smolin


Add-in Express team


Posts: 14582
Joined: 2006-05-11
You are welcome!

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 17 Nov, 2017 08:28:22 Top
André Gerards




Posts: 10
Joined: 2017-11-15
Hello Andrei,

last week I asked for some help for (re-)setting togglebuttons in a Outlook.MailItem-inspector.
You give me a lot of hints, but, sorry, I don't understand at all.

I understood that I have to use PropertyChanging-Event to control the setting, in this case the value or pressed-state of the toggle-button. I also need the OnClick-Event to set the other toggle-buttos (in a group of three buttons), when one of them is clicked - for the buttons represents a typical OptionButton-Group - only one of them is possible.
My problem, I don't know, how to determine or release them when closing the inspector.
At least (and in my opinion of course) the Invalidate-Event of the ribbon doesn't fire.

I will send you a absolutly reduced project. Can you please show me, what I have to do? I don't see a way for a solution.
Thanks very much,
André
Posted 27 Nov, 2017 04:15:54 Top
Andrei Smolin


Add-in Express team


Posts: 14582
Joined: 2006-05-11
Hello André,

There's no such thing as the Invalidate event. You call the Invalidate() method) to inform Office that it should redraw the specified Ribbon control.

To display a Ribbon control, Office sends your add-in a bunch of requests looking for every little detail: caption, tooltip, visible, enabled, screentip, everything. When handling such a request, an Add-in Express component raises the PropertyChanging event on the corresponding Ribbon component. The event handler provides a) the request type, b) the default value. This is how the simple schema mentioned in Updating ribbon controls at run time works: behind the scenes, Office issues requests and Add-in Express returns values; the values are taken from the Ribbon component's settings (you specified the settings at the design time and modified them at the run time).

To get the full control over what Office is supplied with, you handle the PropertyChanging event. The method below is taken from that page :
Private Sub AdxRibbonButton1_PropertyChanging(sender As System.Object, _
    e As AddinExpress.MSO.ADXRibbonPropertyChangingEventArgs) _
    Handles AdxRibbonButton1.PropertyChanging
    Select Case e.PropertyType
        Case ADXRibbonControlPropertyType.Caption
            If condition Then
                e.Value = "Some caption"
            Else
                e.Value = "Some other caption"
            End If
        Case ADXRibbonControlPropertyType.Enabled
            If condition Then
                e.Value = True
            Else
                e.Value = False
            End If
    End Select
End Sub


This method only handles the Office requests for the values of the Caption and Enabled properties; for every other property, Add-in Express returns the value stored in the component.

In your case, the key point is the condition to use: you need to identify the email in which you've modified the state of the Ribbon controls. There are two ways.

1. You can retrieve the item's EntryId and use it to identify the email. Note that MailItem.EntryId is an empty string on a newly created email; it is set to a real value when you save the item. That is, you can save the item in your code.

2. You can create a custom named property and use the property to identify the email and the state of the buttons in it.

As to other buttons, I suppose you don't need to set them directly. Instead, you can call ADXRibbonToggleButton.Invalidate(); this causes Office to raise a bunch of PropertyChanging events; you use the events to display a required state of the button.

In the above said, there's no place to get or release toggle buttons themselves: they only exists in the form of the events that you handle and values that you supply.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 27 Nov, 2017 08:49:50 Top
Andrei Smolin


Add-in Express team


Posts: 14582
Joined: 2006-05-11
Hello André,

Okay. I have created the example.

The sample add-in at http://temp.add-in-express.com/support/MyAddin236-ThreeToggleButtonsVB.zip creates a Ribbon tab showing three toggle buttons in an Outlook mail compose inspector. The idea is to use a UserProperty to store the state of the buttons as a string of boolean values such as "True;False;False" meaning the first button is pressed, the second and third buttons are not.

When the tab's visibility is requested by Office, the event handler of the AdxRibbonTab1.PropertyChanging event looks for the UserProperty; if it isn't found, the event handler creates and sets it to the default value. Whenever Office looks for the Pressed state of the buttons, the UserProperty value is retrieved, parsed, and the parsed value is used. When you click such a button, 1) the UserProperty is overwritten with a string reflecting the desired state of the buttons and 2) the buttons are invalidated right away. This causes Office to request a new value of the Pressed state of the buttons; this ends with parsing the UserProperty value and setting e.Value as specified (see above).

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 30 Nov, 2017 05:48:21 Top
André Gerards




Posts: 10
Joined: 2017-11-15
Hello Andrei,

first of all: Thank you very much!!!

I will have a look on it tomorrow. I hope, I'll understand everything :)

Kind regards,
André
Posted 30 Nov, 2017 10:02:34 Top
André Gerards




Posts: 10
Joined: 2017-11-15
Hello Andrei,

thanks a lot for your sample AddIn. It works, great idea!
I've just added the inspector-NewInspector-Event and there I invalidate each toggle-button.
For I have two groups of toggle-buttons (overall 5 buttons) and in each group always one button is pressed I have to add little code to your 'SaveButtonState'-procedure


Private Sub SaveButtonState(buttonId As Integer, control As IRibbonControl)

...

	'the inner If-clause
	If mail IsNot Nothing Then
		Dim ups As Outlook.UserProperties = mail.UserProperties
		Dim up As Outlook.UserProperty = ups.Item(C_UserPropertyName)
		If up Is Nothing Then
			up = ups.Add(C_UserPropertyName, Outlook.OlUserPropertyType.olText)
			up.Value = strUserPropertyDefaultValue
		End If
		
		'Array (five toggle-buttons)
		Dim strArr As String() = {"False", "False", "False", "False", "False"}
		strArr(buttonId - 1) = Boolean.TrueString
		Dim result As String = String.Join(C_SeparatorString, strArr)
		up.Value = result

		Marshal.ReleaseComObject(up) : up = Nothing
		Marshal.ReleaseComObject(ups) : ups = Nothing

		'two seperate groups of toggle-buttons
		'Group a = AdxRibBtn1, AdxRibBtn2, Group b = AdxRibBtn3, AdxRibBtn4, AdxRibBtn5
		Select Case buttonId
			Case 1
				'state schould be unchanged, if a button is clicked twice
				If AdxRibBtn1.Pressed = False Then AdxRibBtn1.Invalidate()
				'changes the other button
				AdxRibBtn2.Invalidate()
			Case 2
				AdxRibBtn1.Invalidate()
				If AdxRibBtn2.Pressed = False Then AdxRibBtn2.Invalidate()
			Case 3
				If AdxRibBtn3.Pressed = False Then AdxRibBtn3.Invalidate()
				AdxRibBtn4.Invalidate()
				AdxRibBtn5.Invalidate()
			Case 4
				AdxRibBtn3.Invalidate()
				If AdxRibBtn4.Pressed = False Then AdxRibBtn4.Invalidate()
				AdxRibBtn5.Invalidate()
			Case 5
				AdxRibBtn3.Invalidate()
				AdxRibBtn4.Invalidate()
				If AdxRibBtn5.Pressed = False Then AdxRibBtn5.Invalidate()
		End Select

	End If

...

End Sub


So, again, great support, thank you
André
Posted 04 Dec, 2017 08:37:30 Top
Andrei Smolin


Add-in Express team


Posts: 14582
Joined: 2006-05-11
Hello André,

I strongly suggest that you use a custom named property instead of a UserProperty; the latter is visible when you Print Preview the email.

I suggest that you study the following pages to learn how to create such a property:
- https://msdn.microsoft.com/EN-US/library/office/jj973068.aspx]Properties (Outlook)
- https://msdn.microsoft.com/en-us/library/office/ff863046.aspx]PropertyAccessor Object (Outlook)
- https://social.msdn.microsoft.com/Forums/vstudio/en-US/08ecce0a-be0a-4d42-9bbd-7d1691b8abde/using-propertyaccessor-to-set-and-get-properties-in-a-meeting-request?forum=vsto]Using PropertyAccessor to Set and Get properties in a meeting request

Also you can find some details at https://www.add-in-express.com/forum/read.php?FID=5&TID=14156 useful.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 04 Dec, 2017 08:50:59 Top