tl;dr Can I repurpose Cut/Copy/Paste in Visio to transfer text only?
I have some Shapes in Visio that users have frequent repeated data on (Ex: blocks for Date/Time). It's intuitive to use standard copy/paste methods to fill these blocks, resulting in inadvertent shape duplication. In some cases, the Shape is protected and require an Undo to remove, which is frustrating. I'd like to be able to toggle the Ctrl + C/X/V (and preferably the UI elements as well) functionality to transfer Shape Text only to avoid this frustration.
I'm currently using the Window.KeyUp event to handle this. Here's a simplified version of the code:
Private Sub vsoWindow_KeyUp(ByVal KeyCode As Long, ByVal KeyButtonState As Long, CancelDefault As Boolean)
Dim shp as Visio.Shape: Set shp = ActiveWindow.Selection.PrimaryItem
If shp is Nothing Then Exit Sub 'Nothing is selected
If KeyButtonState <> visKeyControl Then Exit Sub 'Ctrl isn't held
Select Case KeyCode
Case vbKeyC: CopyShapeText shp
Case vbKeyX: CutShapeText shp 'Doesn't work, Shape Protection intercepts
Case vbKeyV: PasteShapeText shp
End Select
End Sub
With the workers in a module:
Private Declare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long
Private Declare PtrSafe Function EmptyClipboard Lib "User32" () As Long
Private Declare PtrSafe Function CloseClipboard Lib "User32" () As Long
Private shpText as String
Sub CopyShapeText(shp As Visio.Shape)
shpText = shp.Text
ClearClipboard
End Sub
Sub CutShapeText(shp as Visio.Shape)
shpText = shp.Text
shp.Text = ""
ClearClipboard
End Sub
Sub PasteShapeText(shp as Visio.Shape)
shp.Text = shpText
End Sub
Sub ClearClipboard()
DoEvents
OpenClipboard 0
EmptyClipboard
CloseClipboard
End Sub
Copy/Paste works but is rather clunky. Sometimes it doesn't fire, despite CTRL being held. Cut doesn't work because the Shape gets stored before the event is triggered.
I attempted to use the KeyDown event, but this fails to trigger at all (detects CTRL but not CTRL + C) and would probably fail to properly clear the clipboard. I also attempted to use Application.EnterScope but ran into the same problems and an inconsistent ScopeID when pasting.
The straightforward approach is to use new keyboard shortcuts to control the operations. This works, but users didn't like it.
Is there a way to do this?
UPDATE: After thinking about it, I decided to implement the straightforward solution and utilize CTRL+Shift+C/X/V shortcuts to give users flexibility. I've posted an answer below going into greater detail. My actual question about intercepting the operations remains unanswered.
A similar question was asked several years ago and I was a bit disappointed that it never received a proper answer. The OP ended up using a solution that avoided the problem by utilizing the
Document.ShapeAddedevent.In the same vein, I've decided to go with the straightforward solution and added keyboard shortcuts
CTRL+Shift+C/X/Vto trigger these features. While users didn't like the shortcut in testing, it seems more foolproof than having a toggle which will inevitably lead to mistakes. For the sake of an answer, here's the full code for the simplified test case presented:Although my problem is solved, my question isn't. For the sake of curiosity, I think it's worthwhile to know whether it's possible to intercept these operations.
Aside: I ended up using the
Developer > Macrosdialog to set the keyboard shortcuts. Can this be accomplished programmatically without theApplication.OnKeyevent? I ended up putting comments in the code to indicate the shortcuts, but it'd be nicer to have it directly in code.