I suggest you use this implementation
The above library uses a VBA implementation of what @lbo suggested. It's essentially a way of creating 'fake events' from existing events which already capture the functionality you desire. In this case we use CommandBars_OnUpdate event (which appears to trigger whenever shapes are changed / deleted / selected / deselected / created. Then we filter down the on the current state of the excel workbook to try to understand what actually occurred. By detecting the selected object is or was a shape, we can adequately determine if this event is occurring on a shape or not.
Public WithEvents bars As commandBars
Public old_selection As Object
Private Sub InitialiseEvents()
Set bars = Application.commandBars
End Sub
Private Sub bars_OnUpdate()
'This will call on each user action, here we can check our shapes:
If DetectShape Then
'Shape selected and changed event:
If GetName(old_selection) = GetName(Selection) Then
Debug.Print "Shape Changed"
Else
Debug.Print "Shape Selected"
End If
End If
Set old_selection = Selection
End Sub
Private Function GetName(ByVal obj As Object) As String
On Error Resume Next
GetName = obj.Name
End Function
Private Function DetectShape() As Boolean
On Error GoTo endDetect
DetectShape = Selection.ShapeRange.Count > 0
endDetect:
End Function
Running InitialiseEvents() will print "Shape Selected" whenever a shape is selected and "Shape Changed" whenever a shape might have changed. Note I leave detecting whether the shape has indeed changed to you.