Windows 表单处理程序在计算机唤醒时被忽略
Windows Forms handlers are ignored upon computer 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#->VB)
这是 this one 的一个分支。目前我不知道 hidden window 的创建(库用于捕获消息的功能)是否可以在问题中发挥任何作用。 (但它处理键盘,所以为什么电源事件也被忽略?)当我在小型 WPF 项目中测试库时,它可以很好地恢复。独立库的 WinForms 测试我还没有做。
如果您有任何快速提示,而不是冗长地拆解所有内容、分离应用程序以便于诊断等,请告诉我。
9小时后更新:
- 将标记为
problem 1
的行移到 Dispose()
之前,实现了轻微的改进。调试器不再奇怪地失去跟踪。
在我移除多线程 USB 键盘解码器后,- 处理程序
PowerModeChanged()
总是 被调用(不再被忽略)。现在它可以在挂起-恢复中存活。
除了终止所有工作线程并删除接收到 Suspend
事件的全局处理程序之外,我没有找到解决方案(解决方法?)。计算机恢复后,在我的应用程序中收到 Resume
事件后,我可以重新创建所有侦听器并重新添加全局处理程序。 (听众还不够,还需要处理程序 "refresh"。)应用此方法后,它开始正常工作。
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
(范围: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#->VB) 这是 this one 的一个分支。目前我不知道 hidden window 的创建(库用于捕获消息的功能)是否可以在问题中发挥任何作用。 (但它处理键盘,所以为什么电源事件也被忽略?)当我在小型 WPF 项目中测试库时,它可以很好地恢复。独立库的 WinForms 测试我还没有做。
如果您有任何快速提示,而不是冗长地拆解所有内容、分离应用程序以便于诊断等,请告诉我。
9小时后更新:
- 将标记为
problem 1
的行移到Dispose()
之前,实现了轻微的改进。调试器不再奇怪地失去跟踪。
在我移除多线程 USB 键盘解码器后, - 处理程序
PowerModeChanged()
总是 被调用(不再被忽略)。现在它可以在挂起-恢复中存活。
除了终止所有工作线程并删除接收到 Suspend
事件的全局处理程序之外,我没有找到解决方案(解决方法?)。计算机恢复后,在我的应用程序中收到 Resume
事件后,我可以重新创建所有侦听器并重新添加全局处理程序。 (听众还不够,还需要处理程序 "refresh"。)应用此方法后,它开始正常工作。
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