UnregisterHotkey failed

  • (2 Pages)
  • +
  • 1
  • 2

18 Replies - 919 Views - Last Post: 15 December 2019 - 04:24 PM Rate Topic: -----

#1 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

UnregisterHotkey failed

Posted 01 December 2019 - 12:27 PM

Good evening,
I have a problem with "UnregisterHotkey" in a extern process. In a windows form I registered any Hotkeys

    Public Sub RegisterHotkeys()
        RegisterHotKey(Me.Handle, 1, Key_SHIFT, Keys.F10)
        RegisterHotKey(Me.Handle, 2, 0, Keys.F9)
        RegisterHotKey(Me.Handle, 3, 0, Keys.F10)
        RegisterHotKey(Me.Handle, 4, 0, Keys.F11)
    End Sub


When the form is called the second time, the hotkeys should be deactivated in the first form. Otherwise, I can not register the hotkeys for the new form. But that does not work. The Function only delivers Null

    Dim proc() As Process = Process.GetProcessesByName("DiktatePlayer")
        If proc.Length > 0 Then
            For Each p As Process In proc
                If SetForegroundWindow(p.MainWindowHandle) Then
                        ShowWindow(p.MainWindowHandle, 9)
                    End If
                    UnregisterHotkeys(p.Handle)
                End If
            Next
        End If

    Public Sub UnregisterHotkeys(hWnd As IntPtr)
        Dim ii As Integer
        ii = UnregisterHotKey(hWnd, 1)
        MessageBox.Show(ii & " " & hWnd.ToString & "  u1")
        ii = UnregisterHotKey(hWnd, 2)
        MessageBox.Show(ii & " " & hWnd.ToString & "  u2")
        ii = UnregisterHotKey(hWnd, 3)
        MessageBox.Show(ii & " " & hWnd.ToString & "  u3")
        ii = UnregisterHotKey(hWnd, 4)
        MessageBox.Show(ii & " " & hWnd.ToString & "  u4")
    End Sub


Can you give me a tip?
Environment: VisualStudio 2017 / Vb.Net / Win 10

Is This A Good Question/Topic? 0
  • +

Replies To: UnregisterHotkey failed

#2 maceysoftware   User is offline

  • Member Title
  • member icon

Reputation: 394
  • View blog
  • Posts: 1,649
  • Joined: 07-September 13

Re: UnregisterHotkey failed

Posted 01 December 2019 - 02:02 PM

Can you re-post your second code snippet, but first section (the for loop), either including what you have taken out or fully removing it, as at current the code you have posted wouldn't compile. (you have a extra End If, that doesn't marry up to anything)

Other than that, is ShowWindow showing the second form? if that is the case and from the information you have given us so far, don't you want to call UnregisterHotkeys before you call ShowWindow?
Was This Post Helpful? 0
  • +
  • -

#3 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

Re: UnregisterHotkey failed

Posted 02 December 2019 - 05:36 AM

Thanks! At the first call of the program (this is a compiled exe)the hotkeys are set like that:
RegisterHotkey(Me.Handle,1, Key_SHIFT, Keys.F10)

where Me is the StartForm with embedded MediaPlayer.

When the program is started again (new process), all hotkeys of the already existing processes should be removed (Unregister). This is the code in the new process (actually in all "DiktatePlayer" processes), when the MainWindow ist active:

    Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click
        Dim proc() As Process = Process.GetProcessesByName("DiktatePlayer")

        If proc.Length > 0 Then
            For Each p As Process In proc
                If p.Handle <> IntPtr.Zero Then
                    If SetForegroundWindow(p.MainWindowHandle) Then
                        ShowWindow(p.MainWindowHandle, 9)
                    End If
                    UnregisterHotkeys(p.MainWindowHandle)
                End If
            Next
        End If
        Me.Activate()
        RegisterHotkeys()
        Label1.BackColor = Color.LightGreen
    End Sub


The code for UnregisterHotkeys can you see above.

Best regards
Norbert
Was This Post Helpful? 0
  • +
  • -

#4 maceysoftware   User is offline

  • Member Title
  • member icon

Reputation: 394
  • View blog
  • Posts: 1,649
  • Joined: 07-September 13

Re: UnregisterHotkey failed

Posted 02 December 2019 - 06:21 AM

Sorry can we just clear it this up a little bit more.

What do you mean by showing the form again? do you mean running the application a second time or running a second instance of the form within the same application?

Also, what does:

ShowWindow(p.MainWindowHandle, 9)

Do as in, what are you expecting it to do, why are you passing 9 to it?

Not saying it is wrong, just trying to figure out your user case before jumping it with solutions.
Was This Post Helpful? 0
  • +
  • -

#5 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

Re: UnregisterHotkey failed

Posted 02 December 2019 - 08:59 AM

Many thanks!
Because it does not work, I assumed the window should not be inactive or invisible. That's why I show it with the API Function "ShowWindow". The "9" means "Show the Window and activate it" (see Docu by API functions).

Quote

What do you mean by showing the form again?

Here is running the app a second time (new process of the executed Exe). I give the IntPtr's from the MainWindowHandle's of all Windows to the Sub UnregisterHotkeys.

How can I demonstrate a picture (PNG) here?
Was This Post Helpful? 0
  • +
  • -

#6 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15490
  • View blog
  • Posts: 62,037
  • Joined: 12-June 08

Re: UnregisterHotkey failed

Posted 02 December 2019 - 09:10 AM

Quote

How can I demonstrate a picture (PNG) here?


Drop it on a third party service like imgur. Uploads have been temporarily disabled by the site owner.
Was This Post Helpful? 0
  • +
  • -

#7 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

Re: UnregisterHotkey failed

Posted 02 December 2019 - 09:12 AM

???
Was This Post Helpful? 0
  • +
  • -

#8 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

Re: UnregisterHotkey failed

Posted 02 December 2019 - 09:24 AM

I can't register by imgur. I not received a verification code ...
Was This Post Helpful? 0
  • +
  • -

#9 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15490
  • View blog
  • Posts: 62,037
  • Joined: 12-June 08

Re: UnregisterHotkey failed

Posted 02 December 2019 - 09:52 AM

I do not understand your response.

Any third party image or file hosting should do.
Was This Post Helpful? 0
  • +
  • -

#10 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1538
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: UnregisterHotkey failed

Posted 10 December 2019 - 01:11 PM

@ strzata,
As far as I am aware, you can only Register and UnRegister a hotkey for the current process that is running the code. In other words, the second instance of your application being opened would not be able to call UnregisterHotKey to unregister the hotkey that the first instance of your application set for itself when it called RegisterHotKey. You would have to use some sort of interprocess communication to send a message from the second application to the first application to let it know it needs to unregister it's hotkey. This could get a bit messy but, could be done.

Is there any reason why you need to have more than one instance of your application running at one time? If not, you could make a single instance application which would eliminate the chance of a second instance being opened. If you need more than one Window open at a time, have you considered just using several Forms in just one application instead of starting new separate applications?
Was This Post Helpful? 0
  • +
  • -

#11 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

Re: UnregisterHotkey failed

Posted 11 December 2019 - 03:05 AM

Thank you! The answer testifies to high competence! The unregister should be executed if the first instance loses the focus (in Deactivate). The sub is also executed, but the unregister is unsuccessful. Which trick do you have in stock? We need multiple instances and a new single-instance programming is my last resort.
Private Sub Form1_Deactivate(sender As Object, e As EventArgs) Handles MyBase.Deactivate
        Dim proID As Integer
        GetWindowThreadProcessId(GetForegroundWindow, proID)
        If Process.GetProcessById(proID).MainWindowHandle <> Handle Then
            If Process.GetProcessById(proID).MainWindowTitle.Trim.StartsWith("Diktat") Then
                UnregisterHotkeys(Handle)
            End If
        End If
    End Sub

Was This Post Helpful? 0
  • +
  • -

#12 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

Re: UnregisterHotkey failed

Posted 11 December 2019 - 03:13 AM

Posted Image
Was This Post Helpful? 0
  • +
  • -

#13 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1538
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: UnregisterHotkey failed

Posted 11 December 2019 - 06:13 PM

So let me get this clear, you only want the instance of your application that is in the foreground and has focus to detect the hotkey(s)? If the application is not the active foreground window, it should not detect the hotkey(s)?

If that is true, then you can just add a MenuStrip to your Form and add as many MenuItems to it as you have "Hotkeys" which you want to work like I described above. Then you can go to the Properties tab of each MenuItem you added and set the "ShortcutKeys" Properties to the desired key combination(s). Last, set the MenuStrip's Visible property to False.

Now you will not see the MenuStrip and nobody will even know its there. However, the Shortcut Keys will raise the Click Event of whichever MenuItem corresponds with the detected Shortcut Key on whichever instance of your application that has the mouse/keyboard focus.

This method would not require you to use the native RegisterHotkey and UnRegisterHotkey functions, nor would it require any code at all to register, unregister, or detect any hotkeys. Just use the Click events of the MenuItems to run the code for the detected shortcut key.
Was This Post Helpful? 1
  • +
  • -

#14 strzata   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 01-December 19

Re: UnregisterHotkey failed

Posted 12 December 2019 - 02:45 AM

Thanks a lot! The hotkeys (play, stop, forward, backward) must work system-wide. You hear the dictate with the player and at the same time write the text in a different program (for example WORD). Mostly only one player is open, but sometimes there are also several players. By opening or by activate a player actually the hotkeys are to be re-registered. But this does not work because the hotkeys are still registered for the previous player.

Best regards
Norbert
Was This Post Helpful? 0
  • +
  • -

#15 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1538
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: UnregisterHotkey failed

Posted 12 December 2019 - 05:56 PM

Ok, I think I understand now. You just want the last instance of your application that was activated to keep the hotkeys active, even if it is not the active foreground window. I think you will need to go with the first suggestion I gave you, to use Interprocess Communications to send all the opened applications of your app a special message to let them all know to unregister their hotkeys. Then register the hotkeys for the current application.

I have thrown together and posted a fully functional and commented example below which you can test out to see if it does what your looking for, I believe it should. I used The DataCopy form of Interprocess Communications in this example, seen in the link I gave above. Hopefully the comments will help you to understand the code and what is going on in it.

To test this, create a new Form application in Visual Studio and add 1 Label to the Form. Then use the complete code below for the Form. Now you can Build the application and test running a few instances of the appplication's exe. Only the last instance that was activated will have the global hotkeys registered.

Imports System.Runtime.InteropServices

Public Class Form1

    Private Const WM_COPYDATA As Integer = &H4A
    Private Const WM_HOTKEY As Integer = &H312
    Private Const MOD_ALT As Integer = &H1
    Private Const MOD_CONTROL As Integer = &H2
    Private Const MOD_SHIFT As Integer = &H4

    <DllImport("user32.dll", EntryPoint:="RegisterHotKey")>
    Private Shared Function RegisterHotKey(ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    <DllImport("user32.dll", EntryPoint:="UnregisterHotKey")>
    Private Shared Function UnregisterHotKey(ByVal hWnd As IntPtr, ByVal id As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    <DllImport("user32.dll", EntryPoint:="SendMessageW")>
    Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Function

    <StructLayout(LayoutKind.Sequential)>
    Private Structure COPYDATASTRUCT
        Public dwData As IntPtr
        Public cbData As Integer
        Public lpData As IntPtr
    End Structure

    Private Sub Form1_Activated(sender As Object, e As EventArgs) Handles Me.Activated
        'here i iterate through all the process instances of this application that are currently running, excluding this one.
        For Each p As Process In Process.GetProcessesByName("Simple Hotkey Form").Where(Function(x) x.MainWindowHandle <> Me.Handle)

            'i am creating an array of Bytes for the string "UnRegister". This is the message i will send to all the opened processes to tell them to UnRegister their hotkeys.
            Dim Data() As Byte = System.Text.Encoding.ASCII.GetBytes("UnRegister")

            Dim cds As New COPYDATASTRUCT
            cds.cbData = Data.Length
            cds.lpData = Marshal.AllocHGlobal(Data.Length) 'allocates unmanaged memory to hold the Bytes for our message in this COPYDATASTRUCT structure
            Marshal.Copy(Data, 0, cds.lpData, Data.Length) 'copy the Byte array to the unmanaged memory

            Dim cdsPtr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(cds)) 'allocates unmanaged memory to hold the COPYDATASTRUCT strucure which contains our message
            Marshal.StructureToPtr(cds, cdsPtr, True) 'writes the structure to the unmanaged memory

            SendMessageW(p.MainWindowHandle, WM_COPYDATA, Me.Handle, cdsPtr) 'send the WM_COPYDATA message to the process's MainWindowHandle, passing the COPYDATASTRUCT.

            Marshal.FreeHGlobal(cds.lpData) 'free the unmanaged memory used for our message Bytes
            Marshal.FreeHGlobal(cdsPtr) 'free the unmanaged memory used for the COPYDATASTRUCT strucure
        Next

        'now you can register the hotkeys for this application
        RegisterHotKey(Me.Handle, 100, MOD_CONTROL Or MOD_SHIFT, Keys.P) 'Registers The Play Hotkey (Ctrl+Shft+P) with an ID of 100
        RegisterHotKey(Me.Handle, 101, MOD_CONTROL Or MOD_SHIFT, Keys.S) 'Registers The Stop Hotkey (Ctrl+Shft+S) with an ID of 101
        Label1.Text = "Registered"
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)

        If m.Msg = WM_HOTKEY Then
            If m.WParam.ToInt32 = 100 Then 'The Play Hotkey (Ctrl+Shft+P) Was Detected
                Me.Text = "Playing" 'You can call the Play control of the WMP here
            ElseIf m.WParam.ToInt32 = 101 Then 'The Stop Hotkey (Ctrl+Shft+S) Was Detected
                Me.Text = "Stopped" 'You can call the Stop control of the WMP here
            End If
        End If

        If m.Msg = WM_COPYDATA Then
            Dim cds As COPYDATASTRUCT = CType(m.GetLParam(GetType(COPYDATASTRUCT)), COPYDATASTRUCT) 'gets the COPYDATASTRUCT from the LParam of the WM_COPYDATA message
            Dim Data(cds.cbData - 1) As Byte 'create an array to copy the Byte array from the unmanaged memory to
            Marshal.Copy(cds.lpData, Data, 0, Data.Length) 'copy the Byte array from unmanaged memory to the Data array

            Dim MsgStr As String = System.Text.Encoding.ASCII.GetString(Data) 'convert the Byte array back into a String

            If MsgStr = "UnRegister" Then 'check if the String message is telling us to UnRegister the hotkeys
                UnregisterHotKey(Me.Handle, 100) 'UnRegister The Play Hotkey (Ctrl+Shft+P)
                UnregisterHotKey(Me.Handle, 101) 'UnRegister The Stop Hotkey (Ctrl+Shft+S)
                Label1.Text = "UnRegistered"
            End If

            m.Result = CType(0, IntPtr) 'set the windows message result to 0 and return it
            Return
        End If

        MyBase.WndProc(m)
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        UnregisterHotKey(Me.Handle, 100) 'UnRegister The Play Hotkey (Ctrl+Shft+P)
        UnregisterHotKey(Me.Handle, 101) 'UnRegister The Stop Hotkey (Ctrl+Shft+S)
    End Sub
End Class



This code could be shortened and cleaned up a little if you only had one message to send but, I left it set up for in case you wanted to send other messages to the other instances of your app, not just the "UnRegister" string message I used.
Was This Post Helpful? 1
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2