define hotkey

Started by perry59, February 07, 2024, 06:53:42 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

perry59

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
what, me worry?

Nikolay

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

perry59

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 !
what, me worry?

Nikolay

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 :(

perry59

#4
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!

what, me worry?

Nikolay

#5
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..

perry59

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!
what, me worry?

perry59

#7
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
what, me worry?