I know this is not specific to visio, but I'm not fond of most of the other programming forums, maybe someone here can help.
I want to set up a hotkey to toggle a setting in my visio addin. Just about every example I've found does so within the context of a form but I want to have the hotkey handled when no form is visible. While working on my events class I did discover a built in handler which is declared thus:
AddHandler ThisAddIn.Application.KeyDown, AddressOf KeyDownHandler
I then created this function:
Private Sub KeyDownHandler(KeyCode As Integer, KeyButtonState As Integer, ByRef CancelDefault As Boolean)
MsgBox("keycode is " & KeyCode.ToString & ", Keybuttonstate is " & KeyButtonState & ", Canceldefault is " & CancelDefault.ToString)
End Sub
this does work, regardless of any form shown, but it only captures regular keys, i.e. A-Z. It doesn't seem to work with modifiers (i.e. CTL-W or ALT-W) which is what I want. I obviously don't want this thing firing every time a user types something. Also, it seems the last two parameters never change in my debug message.
does anyone know how I can do this?
Thanks
Well actually this may be specific to Visio :)
They have a specific event halder for add-ins, OnKeystrokeMessageForAddon
https://learn.microsoft.com/en-us/office/vba/api/visio.window.onkeystrokemessageforaddon
I have sort of example here, but it's a bit overcomplicated.
Actually you just need to subscribe to that message and check the params for your keys in the handler
https://github.com/nbelyh/VisioHtmlSidebar/blob/2e99e9319c5d4ca05380fb343c3ec18745274cac/Addin/ThisAddIn.cs#L163
https://github.com/nbelyh/VisioHtmlSidebar/blob/2e99e9319c5d4ca05380fb343c3ec18745274cac/Addin/ShortcutManager.cs
Quote from: Nikolay on February 07, 2024, 07:26:31 PM
Well actually this may be specific to Visio :)
They have a specific event halder for add-ins, OnKeystrokeMessageForAddon
https://learn.microsoft.com/en-us/office/vba/api/visio.window.onkeystrokemessageforaddon
I have sort of example here, but it's a bit overcomplicated.
Actually you just need to subscribe to that message and check the params for your keys in the handler
https://github.com/nbelyh/VisioHtmlSidebar/blob/2e99e9319c5d4ca05380fb343c3ec18745274cac/Addin/ThisAddIn.cs#L163
https://github.com/nbelyh/VisioHtmlSidebar/blob/2e99e9319c5d4ca05380fb343c3ec18745274cac/Addin/ShortcutManager.cs
Thanks Nikolay!
I was unaware of that visio event handler, and it needs to be implemented a bit differently than my other event handlers.
It looks a bit more complicated than what I was expecting maybe I can get it to work, right now I don't know what Imports I need to get "ControlShortcutKeys" and "Win32" to be recognized.
Your example helps a lot though, I'll keep at it !
You don't really need that "Win32" thing (it's that application-specific).
Basically you need to write just the handler for this event.
All information aboutthe pressed key is passed in the parameters.
But yes, this is messy :(
My bad on the "ControlShortcutKeys" comment, it was defined in your example, I guess the "win32" thing is from a dll import?
anyway if its not necessary I can do without. I copied from your example into my addin and commented out part of the handler and omitted the two functions "KeysFromString" and "ControlShortcutKeys" to keep it as simple as possible. For some reason though the handler is never entered regardless of what key I press so I'm not sure what's going on there. Here is what I have (both defined in "ThisAddin.vb"):
Private Sub ThisAddIn_Startup() Handles Me.Startup
_panelManager = New PanelManager(Me)
'these handlers DO load at startup, "selectionchanged" works as expected
'"keymessage" never executes
AddHandler Application.SelectionChanged, AddressOf Application_SelectionChanged
AddHandler Application.OnKeystrokeMessageForAddon, AddressOf KeyMessage
_visEvents = New VisEvents(Me)
End Sub
and the handler:
Public Function KeyMessage(msgwrap As Visio.MSGWrap) As Boolean
Dim keys__1 = CType(msgwrap.wParam, Keys)
If (Control.ModifierKeys And Keys.Control) <> 0 Then
keys__1 = keys__1 Or Keys.Control
End If
If (Control.ModifierKeys And Keys.Shift) <> 0 Then
keys__1 = keys__1 Or Keys.Shift
End If
Dim control__2 = TryCast(Control.FromChildHandle(CType(msgwrap.hwnd, IntPtr)), WebBrowser)
If control__2 Is Nothing Then
Return False
End If
Return False
End Function
by the way, it probably would have been better to leave in the two functions I removed but "keysfromstring", when the compiler reached this line
Dim result = New HashSet(Of Keys)(keys.Split(","c).[Select](Function(s) s.Trim()).[Select](kc.ConvertFromString).Cast(Of Keys)().ToList())
gave the following errors:
'Error BC30518 Overload resolution failed because no accessible '[Select]' can be called with these arguments:
'Extension method 'Public Function [Select](Of TResult)(selector As Func(Of String, TResult)) As IEnumerable(Of TResult)' defined in 'Enumerable': Type parameter 'TResult' cannot be inferred.
'Extension method 'Public Function [Select](Of TResult)(selector As Func(Of String, Integer, TResult)) As IEnumerable(Of TResult)' defined in 'Enumerable': Type parameter 'TResult' cannot be inferred.
'Error BC30516 Overload resolution failed because no accessible 'ConvertFromString' accepts this number of arguments.
possibly a bad translation from C# to VB
Thanks for all your help Nikolay!
The form is specific for that specific project, I was thinkgin just key handling i.e.
Private Sub ThisAddIn_Startup() Handles Me.Startup
AddHandler Application.OnKeystrokeMessageForAddon, AddressOf KeyMessage
End Sub
Public Function KeyMessage(msgwrap As Visio.MSGWrap) As Boolean
' check if you get the keypress here, it should come as msgwrap, and do what is needed. Do you get the call here?
End Function
Now I remember that this "keystroke for addon" may be only called when user is in a custom (addon's) form actually :(
I.e. it may not be global, and I already forgot that..
Yes, while debugging I set a breakpoint at the first line of the handler "Keymessage" but it never gets there.
But I also need a hotkey to work when there is no form visible, I'll keep plugging away at it.
Thanks Nikolay!
I finally just settled on this:
AddHandler ThisAddIn.Application.KeyDown, AddressOf KeyDownHandler
Private Sub KeyDownHandler(KeyCode As Integer, KeyButtonState As Integer, ByRef CancelDefault As Boolean)
If KeyCode = 36 Then 'F11
Commands.ToggleAutowire()
End If
End Sub
unfortunatly KeyDown doesn't handle modifiers which i would have preferred so I just chose a seldom used function key.
very simple and it works