2016-07-07 3 views
-2

Я разработал приложение, использующее vb.net, которое указывает статус блокировки кепки моей системы. В основной форме есть флажок, всякий раз, когда блокировка колпаков включается, нажимая клавишу блокировки колпачков, флажок устанавливается, и при выключении флажок не снимается. Ниже приведены коды:Как поднять события, когда моя форма не имеет фокуса (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 

Теперь проблема все события, упомянутые в приведенных выше кодов получить рейз только тогда, когда основной формой имеет фокус и не тогда, когда он потерял фокус. Я планирую запустить эту программу в фоновом режиме, чтобы всякий раз, когда я нажимал клавишу блокировки caps, я получаю уведомление, но это невозможно, поскольку события клавиатуры не возникают, когда программа потеряла фокус. Как я могу сделать свою программу поднять события, даже если у нее нет фокуса?

И ниже - класс клавиатуры, который я использовал. (Я ничего не изменил в классе Keyboard Hook, я использовал его, поскольку он находится на https://sim0n.wordpress.com/2009/03/28/vbnet-keyboard-hook-class/) После использования этого класса я теперь получаю сообщение об ошибке: Не удалось установить Keyboard Hook. Это сообщение об ошибке было создано самим классом Keyboard Hook.

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

Возможный дубликат [Как слушать клавиатуру в фоновом режиме и нажатия клавиш по требованию?] (Http://stackoverflow.com/questions/15038413/how-to-listen-keyboard -in-background-and-fire-keystrokes-on-demand) –

+0

Вы можете достичь этого только с помощью глобального ключевого крючка – Mono

+0

Переходя на вопрос о http://stackoverflow.com/questions/15038413/how-to-listen-keyboard -in-background-and-fire-keystrokes-on-demand Я использовал класс клавиатуры для клавиатуры и теперь получаю сообщение об ошибке: Не удалось установить клавиатурный крючок – Xlam

ответ

-2

Таким образом, проблема вы столкнулись в том, что вы хотите получать уведомления, когда происходит событие, но это только уведомляет вас, когда форма, которая имеет флажок на нем имеет фокус. Теперь я не эксперт-программист, но я только что закончил книгу по визуальному основному. Я думаю, ваша проблема заключается в линии обработчика событий. Сейчас у вас есть:

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

Эта строка запускает подпрограмму для того, когда нажата любая клавиша вниз на Me форме, выбранная форма. Я не могу экспериментировать с VB прямо сейчас, потому что моя лицензия закончилась, и я скоро получаю еще один. Но вы можете попробовать и указать все формы вместо Me. Или укажите, когда форма минимизирована. Я действительно хотел бы я имел IntelliSense прямо сейчас, но то, что вы могли бы попробовать, может быть

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

или

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

Я понимаю, что оба из них, вероятно, неправильный синтаксис, но логика остается правильным, или я так верить. Я не знаю, что такое глобальный keyhook, но может быть стоит исследовать в вашем случае, если мой ответ не сработает для вас. Это мой первый ответ, так что я надеюсь, что это поможет

+0

Кроме того, вы можете попробовать положить обработчик события keydown внутри form.minimize обработчик событий таким образом, он будет готов к событию keydown после того, как форма была сведена к минимуму. Не уверен, что это сработает, но вы должны попробовать! – Lacuna

+1

Совершенно совершенно и совершенно неправильно, я боюсь. Нет объекта 'AllForms' и никакого события' Me.Minimized.KeyDown' –

+0

@MattWilko Да, сэр. Я знаю, что нет объекта 'AllForms', и, как я уже сказал, он, вероятно, неверен, но логика пытается указать каждую форму в проект имел бы смысл. Что касается второго, я также знаю, что для события «Me.Minimized.KeyDown» события нет.Но, опять же, логика попытки обработать событие KeyDown после формы была бы сведена к минимуму. – Lacuna

 Смежные вопросы

  • Нет связанных вопросов^_^