计算机唤醒时忽略Windows窗体处理程序

时间:2015-02-05 15:19:38

标签: .net vb.net winforms event-handling wakeup

范围:C#和VB.NET 虽然此处的代码是在VB.NET中。)

我的WinForms应用程序运行良好,直到PC的首次暂停和恢复。恢复后,某些事件处理程序将被忽略。

记录机制记录首次暂停和首次恢复。同样,VisualStudio中的断点在首次挂起和恢复后停留在Sub PowerModeChanged()。但他们再也不会这样做了。

Sub PowerModeChanged()永远不会再被召唤 Sub FeedRawInput()永远不会被再次调用,键击会转到标准的WinForms处理程序,否则在我的应用程序中处于非活动状态。

我没有搞乱任何系统调整,它是非常标准的WinForms MDI应用程序。知道什么可以杀死一些内部绑定,所以事件永远不会在恢复后调用吗?

如果我重新启动应用程序,一切都会立即恢复运行......直到暂停 - 恢复。

Sub Initialize() 'called from MainForm_Load()
    If AreAllSettingsMissing() Then PushAllDefaultSettings() 'needs database connections available
    AddHandler Microsoft.Win32.SystemEvents.PowerModeChanged, AddressOf PowerModeChanged

    _rawInput = New RawInputProcessor.RawFormsInput(My.Application.OpenForms(0),
                                                    RawInputProcessor.RawInputCaptureMode.Foreground)
    AddHandler _rawInput.KeyPressed, AddressOf FeedRawInput
End Sub

'my attempt to log suspend/resume and to rebuild USB scanner support
Sub PowerModeChanged(sender As Object, e As Microsoft.Win32.PowerModeChangedEventArgs)
    clsLogging.Log(String.Format("{0}:{1}:{2}", sender.ToString(), [Enum].GetName(GetType(Microsoft.Win32.PowerModes), e.Mode), _rawInput.ToString()))
    If e.Mode <> Microsoft.Win32.PowerModes.Resume Then Return
    'bring all down
    If _rawInput Is Nothing Then Return
    _rawInput.Dispose()
    _rawInput = Nothing
    RemoveHandler _rawInput.KeyPressed, AddressOf FeedRawInput 'problem 1 - called too late

    'restore all back
    _rawInput = New RawInputProcessor.RawFormsInput(My.Application.OpenForms(0),
                                                    RawInputProcessor.RawInputCaptureMode.Foreground)
    AddHandler _rawInput.KeyPressed, AddressOf FeedRawInput
End Sub


Sub FeedRawInput(sender As Object, e As RawInputProcessor.RawInputEventArgs)
    'push raw input key attributes into processing queue where 
    'each detected USB keyboard has its own async processing queue,
    'marshalling complete keystroke or scan back to main thread - standard stuff
End Sub

关于RawInput库,我移植了this one(C# - &gt; VB) 这是this one的一个分支。目前我还不知道创建隐藏窗口(用于捕获消息的库)是否可以在问题中起任何作用。 (但它处理键盘,那么为什么还忽略了电源事件?)当我在小型WPF项目中测试库时,它可以很好地存活下来。 WinForms对独立库的测试我还没有。

如果您有任何快速提示,可以检查而不是长时间拆解所有内容,分离应用程序以便于诊断等,请告诉我。

9小时后更新:

  • 当标记为problem 1的行在Dispose()之前移动时,实现了轻微改进。调试器不再奇怪地失去跟踪。
  • 在删除多线程USB键盘解码器后,
  • 处理程序PowerModeChanged() 总是被调用(不再被忽略)。现在它可以在suspend-resume中存活下来。

1 个答案:

答案 0 :(得分:0)

除了终止所有工作线程并在接收Suspend事件时删除全局处理程序之外,我没有找到解决方案(解决方法?)。在计算机恢复之后,在我的应用程序中收到Resume事件后,我可以重新创建所有侦听器并重新添加全局处理程序。 (听众不够,处理程序也需要“刷新”。)应用这种方法后,它开始正常工作。

Sub PowerModeChanged(sender As Object, e As Microsoft.Win32.PowerModeChangedEventArgs)
    clsLogging.Log(String.Format("{0}:{1}:{2}",
                                 sender.ToString(),
                                 [Enum].GetName(GetType(Microsoft.Win32.PowerModes), e.Mode),
                                 Threading.Thread.CurrentThread.GetHashCode()))
    Select Case e.Mode
        Case Microsoft.Win32.PowerModes.Suspend
            My.Application.Scanners.Suspend()
                'inside: 1) send termination request to all threads
                '        2) clear USB keyboard map and any other references
                '        3) remove global raw keyboard event handler
                '        4) destroy instance of rawInput engine
        Case Microsoft.Win32.PowerModes.Resume
            My.Application.Scanners.Resume()
                'inside: undo (rebuild) steps 4, 3, 2, 1 seen in Suspend()
    End Select

    'debug printout: see list of all thread-powered device readers
    Dim logEntry As String = ""
    For Each key As IntPtr In My.Application.Scanners.Devices.Keys
        logEntry &= String.Format("{0} {1} ", key, My.Application.Scanners.Devices(key))
    Next
    clsLogging.Log(logEntry)
End Sub