创建一个服务来执行一个屏幕后,在不同的EXE(VB.NET)打开一个屏幕
我的问题可能不是很清楚,但我只是想知道如何调用此过程或创建类似的引用,所以我可以自己调查(但如果你有代码是欢迎.. LOL ...)创建一个服务来执行一个屏幕后,在不同的EXE(VB.NET)打开一个屏幕
基本上我有2个桌面程序(A和B)。对于A,我没有源代码,因为B我有。我需要的是创建一些服务/程序,在程序A弹出一个屏幕后,自动运行B.换句话说,捕获A显示特定屏幕的时刻并执行B.
我的现实生活场景是我有一个非常基本的POS,我无法收集客户的人口统计信息(邮政编码等),所以我创建了第二个应用程序来捕获,但我的收银员总是忘记运行程序,我需要找到一种方法运行它显示的画面后(假设“更改由于”在POS,让他们不要忘记运行它。
任何将勾缝可以理解!
感谢
所以这里的你如何能做到这与VB应该是很容易的,如果需要转换为C#一个很简单的例子。代码按标题搜索可见窗口。如果你打开的窗口没有标题,你将不得不多做一些工作。您大概可以找到您的主应用程序的标题,并枚举其子窗口。
首先,一些非托管代码交谈的Win32直接:
Option Strict On
Option Explicit On
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Unmanaged
<DllImport("user32.dll")>
Public Shared Function EnumWindows(ByVal lpEnumFunc As CallBack, ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Public Const SW_SHOW = 5
Public Const SW_RESTORE = 9
Public Const GW_OWNER = 4
Public Const GWL_HWNDPARENT = (-8)
Public Const GWL_EXSTYLE = (-20)
Public Const WS_EX_TOOLWINDOW = &H80
Public Const WS_EX_APPWINDOW = &H40000
Public Delegate Function CallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
End Class
那么应设置为启动对象非GUI模块:
Option Explicit On
Option Strict On
Module Module1
''//Code loosely base on http://msdntracker.blogspot.com/2008/03/list-currently-opened-windows-with.html
''//This is the title of the window that we are looking for
Public ReadOnly WatchForTitle As String = "About Mozilla Firefox"
''//This is the form that we will show when we find the above
Private MainForm As Form1
<STAThread()>
Public Sub Main()
''//Create the form but don not show it
MainForm = New Form1()
''//Create an infinite loop that checks to see if the target window is open and sleeps for a bit between checks
Do While True
Unmanaged.EnumWindows(AddressOf fEnumWindowsCallBack, IntPtr.Zero)
''//Sleep for a bit
System.Threading.Thread.Sleep(500)
Loop
End Sub
Private Function fEnumWindowsCallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
''//Ignore our own handle
If hwnd <> Form1.Handle Then
''//Make sure its visible
If Unmanaged.IsWindowVisible(hwnd) Then
Dim lExStyle = Unmanaged.GetWindowLong(hwnd, Unmanaged.GWL_EXSTYLE)
''//We probably want to ignore tool windows, but remove this if needed
If (((lExStyle And Unmanaged.WS_EX_TOOLWINDOW) = 0)) Then
''//Create a buffer to store the title of the window
Dim sWindowText As New System.Text.StringBuilder(256)
''//Get the title of the window
Dim lReturn = Unmanaged.GetWindowText(hwnd, sWindowText, sWindowText.Length - 1)
''//When you are looking for window title uncomment this line
'Trace.WriteLine(sWindowText)
''//Sanity check, make sure we found a window title
If lReturn <> 0 Then
''//See if it matches what we are looking for
If sWindowText.ToString() = WatchForTitle Then
''//If so, show our form
Form1.ShowDialog()
End If
End If
End If
End If
End If
fEnumWindowsCallBack = True
End Function
End Module
最后创建一个普通的Windows窗体称为Form1
(或任何你想要的,你只需要在上面的模块中改变它)。
如果你测试这个它会弹出,如果你去到Firefox的帮助 - >关于菜单打开窗体。
我应该指出,这只是一个开始。你会希望执行更好的错误检查,并在程序关闭或存在时进行处理。
与程序A交互的方式是不太可能的。不会有传统的“事件”发生或者类似的事情。
你最好打赌就是看一些WIN32 API调用。例如,您可以使用GetPixel()将颜色返回到屏幕上的特定位置。因此,如果程序A显示特定的图像或屏幕与任何其他屏幕显着不同,您可以编写监视屏幕并检查匹配的代码。当发现匹配时,可以执行任何你想要的代码,包括推出B.
+1,很好的答案。该OP也将需要的东西,以确保他们不会继续显示在对话框中一遍又一遍,而触发窗口是可见的(这是我打扰张贴我的答案,你给了一个更详细的一个之后的唯一原因).. 。 – forsvarir 2011-04-22 20:37:01
@forsvarir,我使用'ShowDialoag'该块,直到窗口驳回 – 2011-04-22 20:43:34
非常感谢您!这是很棒的代码。它为我提供了我所需要的快速启动。再次,谢谢! – chupeman 2011-04-26 15:49:07