仅消息窗口不接收 PostMessage
我有一个由第三方制作的 Vb.net 应用程序,我需要使用模拟环境中的外部资源进行控制,并且不得与桌面交互。为了模拟用户通常从带有特定键的特殊屏幕输入的输入,我构建了一个测试控制库来控制它并将表单图像发送到 .bmp。表单无法在任务栏中可见和显示,bmp 输出将由模拟环境显示。
只要我不使用 PostMessage 和 sendKeys 就可以很好地工作,但主窗体的 ShowInTaskbar = False 。经过多次阅读和阅读后,测试后,我已经学到了足够多的知识来尝试似乎唯一可行的方法。我创建了一个使用 HWND_MESSAGE 参数设置父级的表单,这应该创建一个仅消息 Windows,应该接收 postMessage,并对其事件进行子类化。msdn。
不幸的是
,我似乎无法让它工作,并且我希望有人能告诉我我做错了什么。我一直在测试在网络上找到的关于 .net 的几种不同方法,并且没有进入消息线程查看和提要(也许(可能是)我最后的希望) ,它们似乎都有效,直到我从任务栏中取出表格。
好的,这是代码:
MsgOnly.vb
公共类MsgHandling
DllImport("user32.dll", SetLastError:=True,CharSet:=CharSet.Auto)> _ 公共共享函数 SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As 内部指针 结束函数
私有共享 HWND_MESSAGE 作为 IntPtr = New IntPtr(-3)
公共事件CallBackProc(ByRef m As Message) 公共子集Parent() SetParent(Me.Handle, HWND_MESSAGE) 结束子 受保护的覆盖 Sub WndProc(ByRef m 作为消息) RaiseEvent CallBackProc(m) '然后 RaiseEvent MyBase.WndProc(m) 结束子 结束课程
表单中的部分子类化(无法显示处理子类、隐私问题的内容。希望这就足够了)
Public WithEvents Msg As New MsgHandling
Private Sub XXXXX_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'----snips
Msg.setParent()
'----snips
end sub
Private Sub CallBackProc(ByRef m As System.Windows.Forms.Message) Handles Msg.CallBackProc
Me.Text = "Rx events " & m.LParam.ToString() & " " & m.WParam.ToString()
WndProc(m)
End Sub
测试表
Public Class Form1
<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
Public Shared Function SetWindowPos( _
ByVal hWnd As IntPtr, _
ByVal hWndInsertAfter As IntPtr, _
ByVal X As Int32, _
ByVal Y As Int32, _
ByVal cy As Int32, _
ByVal uFlags As Int32) _
As Boolean
End Function
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Private Declare Function AllowSetForegroundWindow Lib "user32" Alias "AllowSetForegroundWindow" (ByVal dwProcessId As Integer) As Boolean
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
Public myProcess As Process = New Process()
Private Const WM_KEYDOWN As Long = 100
Private Const WM_RBUTTONDOWN As Long = 204
Public Shared HWND_MESSAGE As IntPtr = New IntPtr(-3)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
myProcess.StartInfo.FileName = "...\XXXXXX.exe" 'Not real name
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal
myProcess.EnableRaisingEvents = True
AddHandler myProcess.Exited, AddressOf Me.SendKeysTestExited
myProcess.Start()
End Sub
Friend Sub SendKeysTestExited(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim myRxProcess As Process = DirectCast(sender, Process)
myRxProcess.Close()
End Sub
Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Dim tHwnd As Long
Dim rslt As Boolean
If myProcess.Responding Then
tHwnd = FindWindowEx(HWND_MESSAGE, 0, 0, 0)
PostMessage(HWND_MESSAGE, WM_RBUTTONDOWN, 0, "TEXT TO SEND")
Else
myProcess.Kill()
End If
End Sub
Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
myProcess.Close()
End Sub
End Class
不太确定我现在可以提供哪些其他详细信息。有人有我没有找到的想法或方法吗?
感谢您的任何意见
I have an Vb.net application made by a third party , that I need to control using outside resources from a simulated environment and must not interact with the desktop. To simulate inputs that a user would normally input from a special screen with specific keys around it, I've built a test control library to control it and send the form image to a .bmp. The form cannot be visible and showed in taskbar , the bmp output will be displayed by the simulated environment.
Using PostMessage and sendKeys work well as long as I don't but ShowInTaskbar = False for the main form. After many read & testing, I have learned enough to try what seems to be the only thing that would work. I've created a form that I setparent using HWND_MESSAGE parameter, this should create a Message-Only Windows, that are supposed to received postMessage, and subclass it's events.msdn.
StackOverflow already about this
Unfortunately , I can't seem to get it to work, and I was hoping someone could tell me what I'm doing wrong.I have been testing several different ways found through out the web about .net , and short of going into message thread peek and feed(maybe(may be)my last hope), they all seem to work until I take the forms out of the taskbar.
Ok, here are the code:
The MsgOnly.vb
Public Class MsgHandling
DllImport("user32.dll", SetLastError:=True,CharSet:=CharSet.Auto)> _
Public Shared Function SetParent(ByVal hWndChild As IntPtr,
ByVal hWndNewParent As IntPtr) As
IntPtr
End FunctionPrivate Shared HWND_MESSAGE As IntPtr = New IntPtr(-3)
Public Event CallBackProc(ByRef m As Message) Public Sub setParent() SetParent(Me.Handle, HWND_MESSAGE) End Sub Protected Overrides Sub WndProc(ByRef m As Message) RaiseEvent CallBackProc(m) 'then RaiseEvent MyBase.WndProc(m) End Sub End Class
Part subclassing in the form(Can't show more than what handles the sub classing, privacy issues. Hopefully this will suffice )
Public WithEvents Msg As New MsgHandling
Private Sub XXXXX_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'----snips
Msg.setParent()
'----snips
end sub
Private Sub CallBackProc(ByRef m As System.Windows.Forms.Message) Handles Msg.CallBackProc
Me.Text = "Rx events " & m.LParam.ToString() & " " & m.WParam.ToString()
WndProc(m)
End Sub
Test form
Public Class Form1
<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
Public Shared Function SetWindowPos( _
ByVal hWnd As IntPtr, _
ByVal hWndInsertAfter As IntPtr, _
ByVal X As Int32, _
ByVal Y As Int32, _
ByVal cy As Int32, _
ByVal uFlags As Int32) _
As Boolean
End Function
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Private Declare Function AllowSetForegroundWindow Lib "user32" Alias "AllowSetForegroundWindow" (ByVal dwProcessId As Integer) As Boolean
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
Public myProcess As Process = New Process()
Private Const WM_KEYDOWN As Long = 100
Private Const WM_RBUTTONDOWN As Long = 204
Public Shared HWND_MESSAGE As IntPtr = New IntPtr(-3)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
myProcess.StartInfo.FileName = "...\XXXXXX.exe" 'Not real name
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal
myProcess.EnableRaisingEvents = True
AddHandler myProcess.Exited, AddressOf Me.SendKeysTestExited
myProcess.Start()
End Sub
Friend Sub SendKeysTestExited(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim myRxProcess As Process = DirectCast(sender, Process)
myRxProcess.Close()
End Sub
Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Dim tHwnd As Long
Dim rslt As Boolean
If myProcess.Responding Then
tHwnd = FindWindowEx(HWND_MESSAGE, 0, 0, 0)
PostMessage(HWND_MESSAGE, WM_RBUTTONDOWN, 0, "TEXT TO SEND")
Else
myProcess.Kill()
End If
End Sub
Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
myProcess.Close()
End Sub
End Class
Not really sure what other details I can provide for now. Anyone as any idea or ways I haven't found?
Thanks for any input
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我找到了解决方法。问题似乎出在搜索功能找不到窗口句柄这一事实。我尝试了几种方法,但是由于未枚举仅消息,因此我无法循环,或者至少没有成功。
因此,我创建一个带有句柄的文件,外部程序读取该文件并使用该句柄来创建 PostMessage。目前这效果很好。我希望我能找到更好的方法,但至少我可以提出一些解决方案。
我仍然愿意接受建议或其他可能的解决方法:)。
I've found a work around. It seems like the problem comes from the fact that the windows handle is not find with the search functions. I have tried several ways, but since message-only are not enumerated, I can't loop, or at least I wasn't successful.
So I create a file with the handle, that the external program reads and the use that handle to make the PostMessage. This works well for now. I wish I could find a better way, but at least I have something to propose as a solution.
I'm still open to suggestion or other possible workaround:).