2012-04-29 2 views
0

here 클래스를 사용하여 광산 앱에서 키보드 조합을 전역으로 연결합니다.앱이 다른 작업을 수행하는 동안 키보드 후크가 키보드를 고정시킵니다.

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 

앱에 초점이 맞았는데 문제가 있어도 멋지게 작동합니다. 내 응용 프로그램을 사용 중입니다

My.Computer.Network.UploadFile 

업로드하는 동안 kayboard 스트로크가 응답하지 않습니다. 마우스가 괜찮습니다.

응용 프로그램 내에서 다른 작업 중에 키보드를 활성 상태로 유지하려면 어떻게해야합니까?

답변

0

예, 문제가 있습니다. Windows는 프로그램이 메시지 루프를 펌핑 할 때만 후크 콜백 메소드를 호출 할 수 있습니다. Windows에서 급격한 재진입 문제를 일으키지 않고 주 스레드에서 전화를 걸 수있는 다른 방법은 없습니다.

주 스레드가 파일 업로드와 같은 다른 작업을 수행하면 작동이 멈 춥니 다. 이것은 GUI 응용 프로그램의 일반적인 요구 사항이며, 다른 작업과 함께 기본 UI 스레드를 사용하면 사용자 인터페이스가 부담 스럽습니다. 입력에 응답하지 않고 페인팅을 중지합니다. 몇 초 후에 Windows 창 관리자가 들어가서 주 창을 '고스트 창'으로 바꿉니다. 제목 표시 줄에 "응답 없음"이 표시됩니다. 키보드 입력이 처리되는 것을 멈추기 때문에 코를 더 세게 문지릅니다. Window는 후크 콜백을 호출 할 수 없습니다.

UI 스레드가 응답 할 수 있도록 다른 스레드에서 장기 실행 작업을 수행해야합니다. 또는 특정 경우에 대해, UploadFileAsync()를 대신 사용하십시오.

+0

여기에서 예제 소스를 얻었습니다. [MSDN 예제] (http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx) ... 여기의 문제는 타이머 구성 요소에 업로드했습니다. 업로드하기 전에 응용 프로그램은 화면 부분을 캡처하고 jpg로 저장합니다. 비동기 문제는 때로는 때로는 작동하여 가끔씩 gdi + excpetion을 던진다는 것입니다. – e4rthdog

+0

나는 이것이 무엇을 의미하는지 모르겠다. 내가 보았던 스 니펫 만 보았습니다. 키보드가 잠겨있을 때 원래 갖고 있던 문제에 대한 설명입니다. GDI + 예외에 대한 또 다른 질문을 시작하여 잘 문서화하십시오. –

+0

내가 코멘트를 썼을 때 나는 다른 주제의 문맥에서 새로운 질문을 열어야한다는 것을 이해했다. 고마워, 네 대답을 표시하고있어. – e4rthdog

관련 문제