2012-04-29 13 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のウィンドウマネージャーは、メインウィンドウを「ゴーストウィンドウ」に置き換え、タイトルバーに「応答していません」と表示します。キーボード入力が処理されなくなり、ウィンドウがフックコールバックを呼び出せなくなるので、あなたの鼻が硬くなってしまいます。

UIスレッドが反応し続けるように、別のスレッドで長時間実行するタスクを実行する必要があります。または、あなたが話している特定のケースでは、代わりにUploadFileAsync()を使用してください。

+0

私はここからサンプルソースを入手しました:[MSDN example](http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx)...ここでの問題は、私は、タイマーコンポーネントでアップロードしている。アップロードする前に、アプリは画面の部分をキャプチャし、jpgに保存します。今非同期の問題は時には時々gdi + excpetionがスローされてしまうことです。 – e4rthdog

+0

これが何を意味するのか分かりませんが、あなたが見るために投稿したスニペットしかありません。キーボードがロックアップしていた当初の問題を完全に説明しています。あなたのGDI +例外に関する別の質問を開始し、それをうまく文書化してください。 –

+0

私がコメントを書いたら、私は別のトピックの文脈について新しい質問を開く必要があると理解しました。ありがとう、私はあなたの答えをマークしています。 – e4rthdog

関連する問題