In an add-in I am writing, I have some ribbon controls which are designed to be activated when text has focus - and otherwise to be inactive. I use the WindowSelectionChange event to trigger reloading of the relevant controls. Unfortunately this does not work for all combinations of Office/Windows.
For Office 2016 on Windows 10, or Office 2010 on Windows 10, this works fine.
For Office 2016 or Office 2013 on Windows 7, I am not getting the WindowSelectionChange event when opening PowerPoint and creating a presentation. In fact, I don't get any event on a reference to an Application object defined with WithEvents after the NewPresentation event. My tests indicate that the relevant variable is still there - and hasn't been reset after the NewPresentation event - just that it no longer gets these events.
Note, if I open an existing presentation, then the events fire as expected, and also having opened an existing presentation and then creating a new presentation that also works as expected.
Any suggestions?
Below details of my tests:
MainModule:
Option Explicit
Public gb_oAppEvents As CApplicationEvents
Public gb_stTestVariable As String
Public gb_boolContextSet As Boolean
Public gb_oMyRibbon As IRibbonUI
Sub RibbonUI_onLoad(Ribbon As IRibbonUI)
MsgBox "RibbonUI_onLoad run"
If gb_oAppEvents Is Nothing Then
Set gb_oAppEvents = New CApplicationEvents
End If
Set gb_oAppEvents.App = Application
Set gb_oMyRibbon = Ribbon
' Check if variable retained:
' (We fined that it is always retained for all versions).
gb_stTestVariable = "Variable set on load"
' Set something on the gb_oAppEvents object for testing:
gb_oAppEvents.stVariableSet = "An Application Events variable was set when the ribbom loaded."
End Sub
Sub NormalControl()
Dim stAppEventsVar As String
stAppEventsVar = ""
' The global app events does not go away - this works after the ribbon has
' been loaded at any point:
If Not gb_oAppEvents Is Nothing Then
stAppEventsVar = vbCrLf & vbCrLf & "The value of the test " & _
"variable on the gb_oAppEvents object is: " & gb_oAppEvents.stVariableSet
End If
MsgBox "You clicked a normal control. The value of the test variable is: " & _
gb_stTestVariable & stAppEventsVar
End Sub
Sub ContextSensitiveControl()
MsgBox "You clicked a context sensitive control"
End Sub
Sub ContextSensitiveAlwaysTrue()
MsgBox "You clicked on the always true context sensitive control"
' We don't lose the object containing the ribbon reference - this
' never gets triggered:
If gb_oAppEvents Is Nothing Then
Set gb_oAppEvents = New CApplicationEvents
MsgBox "Oh dear - we would have lost the ribbon as well!"
End If
' The application object does not go away:
If gb_oAppEvents Is Nothing Then
MsgBox "The application object went away"
Else
MsgBox "The application object did not go away - reset it anyway!"
End If
' reset app property - but this doesn't help - the reference application
' object does not respond to events.
Set gb_oAppEvents.App = Application
End Sub
Sub GetEnabled(Control As IRibbonControl, ByRef returnedVal)
' On Windows 7 this doesn't work - because the App_WindowSelectionChange
' event never gets called - so gb_boolContextSet is never changed.
' It works fine in Windows 10 it seems.
' In all cases this is always called when the ribbon is invalidated.
If Control.Id = "idContextSensitiveControl" Then
returnedVal = gb_boolContextSet
End If
' This works fine:
If Control.Id = "idContextSensitiveAlwaysTrue" Then
returnedVal = True
End If
End Sub
CApplicationEvents Class:
Option Explicit
Private p_stVariableSet As String
Public WithEvents App As Application
Public Property Get stVariableSet() As String
stVariableSet = p_stVariableSet
End Property
Public Property Let stVariableSet(value As String)
p_stVariableSet = value
End Property
Public Sub App_WindowSelectionChange(ByVal Sel As Selection)
' For new presentations - where no existing document is open - this is not
' called on the Office 2016/Windows 7 install. However, if an existing document
' has been opened, before creating a new presentation, then it is called.
' For Office 2016 or 2010/Windows 10, this is called in all situations - i.e.
' for new presentations following opening of PowerPoint as well.
MsgBox "The selection changed."
' This activates/de-activates ribbon controls.
If Application.ActiveWindow.Selection.Type <> ppSelectionText Then
MainModule.gb_boolContextSet = False
Else
MainModule.gb_boolContextSet = True
End If
Dim oRibbon As IRibbonUI
Set oRibbon = MainModule.gb_oMyRibbon
oRibbon.InvalidateControl "idContextSensitiveControl"
End Sub
Private Sub App_NewPresentation(ByVal Pres As Presentation)
' This gets triggered on both Windows 7 and Windows 10 installs
MsgBox "New Presentation"
' This is the last event that seems to get triggered in Windows 7 on first opening
' of PowerPoint and creating a new presentation.
MainModule.gb_boolContextSet = True
If MainModule.gb_oMyRibbon Is Nothing Then
MsgBox "The ribbon isn't recorded."
Else
Dim oRibbon As IRibbonUI
Set oRibbon = MainModule.gb_oMyRibbon
oRibbon.InvalidateControl "idContextSensitiveControl"
End If
End Sub
Private Sub App_AfterNewPresentation(ByVal Pres As Presentation)
' This gets triggered on the Windows 10 install, but not the Windows 7 one.
MsgBox "After New Presentation"
If MainModule.gb_oMyRibbon Is Nothing Then
MsgBox "The ribbon isn't recorded."
Else
Dim oRibbon As IRibbonUI
Set oRibbon = MainModule.gb_oMyRibbon
oRibbon.InvalidateControl "idContextSensitiveControl"
End If
End Sub
This is the ribbon XML:
<customUI onLoad="RibbonUI_onLoad" xmlns="not-allowed-to-post-links">
<ribbon startFromScratch="false">
<tabs>
<tab idMso="TabHome">
<group id="idRibbonVarCheck" label="Ribbon Var Check">
<button id="idNormalControl"
label="Normal"
imageMso="ClipArtInsert"
size="normal"
onAction="NormalControl"/>
<button id="idContextSensitiveControl"
label="Context Sensitive"
imageMso="MailMergeGoToPreviousRecord"
size="normal"
onAction="ContextSensitiveControl"
getEnabled="GetEnabled"/>
<button id="idContextSensitiveAlwaysTrue"
label="Context True"
imageMso="MailMergeGoToPreviousRecord"
size="normal"
onAction="ContextSensitiveAlwaysTrue"
getEnabled="GetEnabled"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>