2016-07-07 23 views
-2

Ich habe eine Anwendung mit vb.net entwickelt, die den Feststelltaste-Status meines Systems angibt. Es gibt ein Kontrollkästchen im Hauptformular, wenn die Feststelltaste durch Drücken der Feststelltaste aktiviert wird, wird das Kontrollkästchen aktiviert und wenn es deaktiviert ist, wird das Kontrollkästchen deaktiviert. Im Folgenden sind die Codes:Wie Ereignisse ausgelöst werden, wenn mein Formular keinen Fokus hat (vb .net)

Public Class Form1 

Dim keyStCL As Boolean = False 

Private WithEvents KeyHook As New KeyboardHook 

Private Const VK_CAPSLOCK As Integer = &H14 
Private Const VK_SCROLLLOCK As Integer = &H91 
Private Const VK_NUMLOCK As Integer = &H90 

Private Const KEYEVENTF_EXTENDEDKEY As Integer = &H1 
Private Const KEYEVENTF_KEYUP As Integer = &H2 

Private Sub SimulateKeyPressCaps(ByVal bVKCode As Byte, ByVal bScanCode As Byte) 
    Call keybd_event(VK_CAPSLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0) 
    Call keybd_event(VK_CAPSLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0) 
End Sub 

Private Sub checkbutton_caps_CheckedChanged(sender As Object, e As EventArgs) Handles checkbutton_caps.Click 

    If keyStCL = True Then 
     SimulateKeyPressCaps(VK_CAPSLOCK, &H45) 
     checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_off.png") 
     checkbutton_caps.Checked = False 

    ElseIf keyStCL = False Then 
     SimulateKeyPressCaps(VK_CAPSLOCK, &H45) 
     checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_on.png") 
     checkbutton_caps.Checked = True 

    End If 
End Sub 

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Activated 

    Me.KeyPreview = True 

    If My.Computer.Keyboard.CapsLock = True Then 
     keyStCL = True 
     My.Computer.Audio.PlaySystemSound(Media.SystemSounds.Beep) 
     checkbutton_caps.Checked = True 
     checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_on.png") 
    ElseIf My.Computer.Keyboard.CapsLock = False Then 
     keyStCL = False 
     checkbutton_caps.Checked = False 
     checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_off.png") 
    End If 

Private Sub Form1_KeyPressCaps(ByVal sender As Object, e As KeyEventArgs) Handles Me.KeyDown 

    If e.KeyCode = Keys.CapsLock Then 
     If keyStCL = True Then 
      checkbutton_caps.Checked = False 
      checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_off.png") 
      keyStCL = False 

     ElseIf keyStCL = False Then 
      checkbutton_caps.Checked = True 
      checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_on.png") 
      keyStCL = True 

     End If 
    End If 
End Sub 

Nun ist das Problem all Ereignisse in dem oben genannten Codes ist nur angehoben werden, wenn die Hauptform des Fokus hat und nicht, wenn es den Fokus verloren hat. Ich plane, dieses Programm im Hintergrund zu laufen, so dass, wenn ich die Feststelltaste klicke, ich benachrichtigt werde, aber das ist nicht möglich, da die Tastaturereignisse nicht ausgelöst werden, wenn das Programm den Fokus verloren hat. Wie kann ich mit meinem Programm Ereignisse erhöhen, selbst wenn es keinen Fokus hat?

Und unten ist die Keyboard Hook-Klasse, die ich verwendet habe. (Ich habe nichts in der Keyboard Hook-Klasse geändert, ich habe es verwendet, wie es auf https://sim0n.wordpress.com/2009/03/28/vbnet-keyboard-hook-class/ ist) Nach der Verwendung dieser Klasse bekomme ich jetzt einen Fehler: Keyboard Hook konnte nicht eingestellt werden. Diese Fehlermeldung wurde von der Keyboard Hook-Klasse selbst erstellt.

Imports System.Runtime.InteropServices 

Public Class KeyboardHook 

<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ 
Private Overloads Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As KBDLLHookProc, ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer 
End Function 
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ 
Private Overloads Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer 
End Function 
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ 
Private Overloads Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean 
End Function 

<StructLayout(LayoutKind.Sequential)> _ 
Private Structure KBDLLHOOKSTRUCT 
    Public vkCode As UInt32 
    Public scanCode As UInt32 
    Public flags As KBDLLHOOKSTRUCTFlags 
    Public time As UInt32 
    Public dwExtraInfo As UIntPtr 
End Structure 

<Flags()> _ 
Private Enum KBDLLHOOKSTRUCTFlags As UInt32 
    LLKHF_EXTENDED = &H1 
    LLKHF_INJECTED = &H10 
    LLKHF_ALTDOWN = &H20 
    LLKHF_UP = &H80 
End Enum 

Public Shared Event KeyDown(ByVal Key As Keys) 
Public Shared Event KeyUp(ByVal Key As Keys) 

Private Const WH_KEYBOARD_LL As Integer = 13 
Private Const HC_ACTION As Integer = 0 
Private Const WM_KEYDOWN = &H100 
Private Const WM_KEYUP = &H101 
Private Const WM_SYSKEYDOWN = &H104 
Private Const WM_SYSKEYUP = &H105 

Private Delegate Function KBDLLHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer 

Private KBDLLHookProcDelegate As KBDLLHookProc = New KBDLLHookProc(AddressOf KeyboardProc) 
Private HHookID As IntPtr = IntPtr.Zero 

Private Function KeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer 
    If (nCode = HC_ACTION) Then 
     Dim struct As KBDLLHOOKSTRUCT 
     Select Case wParam 
      Case WM_KEYDOWN, WM_SYSKEYDOWN 
       RaiseEvent KeyDown(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys)) 
      Case WM_KEYUP, WM_SYSKEYUP 
       RaiseEvent KeyUp(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys)) 
     End Select 
    End If 
    Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam) 
End Function 

Public Sub New() 
    HHookID = SetWindowsHookEx(WH_KEYBOARD_LL, KBDLLHookProcDelegate, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0) 
    If HHookID = IntPtr.Zero Then 
     Throw New Exception("Could not set keyboard hook") 
    End If 
End Sub 

Protected Overrides Sub Finalize() 
    If Not HHookID = IntPtr.Zero Then 
     UnhookWindowsHookEx(HHookID) 
    End If 
    MyBase.Finalize() 
End Sub 

End Class 
+1

Mögliche Duplikate von [Wie Tastatur im Hintergrund zu hören und Tastenanschläge auf Nachfrage Feuer?] (Http://stackoverflow.com/questions/15038413/how-to-listen-keyboard -in-background-and-fire-keystrokes-on-demand) –

+0

Das erreichen Sie nur mit einem globalen Keyhook – Mono

+0

Beziehen Sie sich auf die Frage auf http://stackoverflow.com/questions/15038413/how-to-listen-keyboard -in-background-and-fire-keystrokes-on-demand Ich habe die Keyboard Hook-Klasse benutzt und jetzt bekomme ich einen Fehler: Tastatur-Hook konnte nicht gesetzt werden – Xlam

Antwort

-2

Also das Problem, das Sie konfrontiert sind, ist, dass Sie benachrichtigt werden möchten, wenn ein Ereignis eintritt, aber es benachrichtigt Sie nur, wenn das Formular, das das Kontrollkästchen auf sie hat den Fokus hat. Jetzt bin ich kein Experte Programmierer, aber ich habe gerade ein Buch über Visual Basic abgeschlossen. Ich denke, dein Problem liegt in der Event-Handler-Zeile. Gerade jetzt haben Sie:

Private Sub Form1_KeyPressCaps(ByVal sender As Object, e As KeyEventArgs) Handles Me.KeyDown 

Diese Zeile startet die Unterroutine für, wenn eine Taste gedrückt wird auf der Me Form, die die aktuell ausgewählte Form. Ich kann jetzt nicht mit VB experimentieren, weil meine Lizenz abgelaufen ist und ich bald eine andere bekomme. Aber Sie können versuchen, alle Formulare anstelle der Me anzugeben. Oder geben Sie an, wann das Formular minimiert wird. Ich wünschte wirklich, ich hatte intellisense jetzt aber etwas, was Sie können

Private Sub Form1_KeyPressCaps(ByVal sender As Object, e As KeyEventArgs) Handles AllForms.KeyDown 

oder

Private Sub Form1_KeyPressCaps(ByVal sender As Object, e As KeyEventArgs) Handles Me.Minimized.KeyDown 

Ich weiß, könnte versuchen, dass beide wahrscheinlich die falsche Syntax sind aber die Logik bleibt richtig, oder so ich glauben. Ich weiß nicht, was ein globaler Keyhook ist, aber es kann sich lohnen, in Ihrem Fall zu recherchieren, wenn meine Antwort nicht für Sie funktioniert. Dies ist meine erste Antwort, so hoffe ich, es hilft

+0

Sie könnten auch versuchen, den Ereignishandler keydown in den form.minimize-Ereignishandler zu setzen, damit er für ein Keydown-Ereignis bereit ist, nachdem das Formular minimiert wurde. Nicht sicher, ob das funktioniert, aber Sie sollten es versuchen! – Lacuna

+1

Völlig völlig und völlig inkorrekt habe ich Angst. Es gibt kein "AllForms" -Objekt und kein "Me.Minimized.KeyDown" -Ereignis –

+0

@MattWilko. Ja, ich weiß, dass es kein 'AllForms'-Objekt gibt und wie gesagt, es war wahrscheinlich inkorrekt, aber die Logik, jedes Formular in der Projekt würde Sinn machen. Was die zweite betrifft, weiß ich auch, dass es kein Ereignis für das Ereignis "Me.Minimized.KeyDown" gibt.Aber noch einmal, die Logik zu versuchen, das "KeyDown" -Ereignis zu behandeln, nachdem das Formular minimiert wurde, wäre sinnvoll. – Lacuna