ZeroEffect Posted December 29, 2005 Author Posted December 29, 2005 Will do here is my import code. I'll be trying the function shortly. <DllImport("user32.dll", SetLastError:=True)> _ Shared Function GetClassNameA(ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Integer) As Integer End Function Thanks Again ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
HJB417 Posted December 29, 2005 Posted December 29, 2005 <DllImport("user32.dll", SetLastError:=True)> _ Public Shared Function GetClassName(ByVal hwnd As IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal buf As StringBuilder, ByVal nMaxCount As Integer) As Integer End Function Public Function get_ClassName() As String Dim builder1 As New StringBuilder(256) Dim num1 As Integer = NativeMethods.GetClassName(Me.Handle, builder1, 256) Return builder1.ToString(0, num1) End Function Quote
HJB417 Posted December 29, 2005 Posted December 29, 2005 I don't think the <MarshalAs(UnmanagedType.LPStr)> is required though. Quote
ZeroEffect Posted December 29, 2005 Author Posted December 29, 2005 With the code above and this line, Dim sClassName As String Dim r As Integer r = GetClassNameA(hwnd, sClassName, 100) I was able to return the number 6 but I'm not dure what to do with that ro if it is right. according to information on the support website they had this. vb6 code Dim sClassName As String * 100 but .NET doesn't like that. So that is my next step. Any thoughts are welcome. Thanks again ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
ZeroEffect Posted December 29, 2005 Author Posted December 29, 2005 Is there a Import that I am missing, stringbuilder is not defined and NativeMethods is comming up Private. Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
ZeroEffect Posted December 29, 2005 Author Posted December 29, 2005 found the import imports system.text Here is the error I am getting too. "System.Drawing.NativeMethods is not accessible in this context because it is private" I'm looking for it now. Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
ZeroEffect Posted December 29, 2005 Author Posted December 29, 2005 Removing "NativeMethods" from the code eliminated the problem and I am now returning the class name. now that I have the class name where am I to use it. I have tried placing it here, Dim PTools_hWnd As IntPtr = FindWindowExA(hwnd, 0, strWinClass, vbNullString) but all this does is return a zero, I'll have to try some more things. Here is my code so far Private Sub PT_Command(ByVal strCMD As String) Try Dim ret As Integer Dim Rec1 As Rectangle = New Rectangle 'Find Window Dim returnValue() As Diagnostics.Process returnValue = Process.GetProcessesByName(prgWindow) Dim hwnd As IntPtr = returnValue(0).MainWindowHandle strWinClass = get_ClassName(hwnd) Dim PTools_hWnd As IntPtr = FindWindowExA(hwnd, 0, strWinClass, vbNullString) 'finds child windows 'Get Left, Right, Top and Bottom of Form1 Dim success As Boolean = GetWindowRect(hwnd, Rec1) Debug.WriteLine(String.Format("Rec1={0}", Rec1)) If Not success Then Throw New Win32Exception End If 'GetWindowRect returning zero values 'Tried both hwnd & PTools_hWnd If UCase(strCMD) = "PLAY" Then MoveCursor((Rec1.Left + x1), (Rec1.Top + y1)) ElseIf UCase(strCMD) = "STOP" Then MoveCursor((Rec1.Left + x2), (Rec1.Top + y2)) End If If Not SetForegroundWindow(hwnd) Then Throw New Win32Exception End If If newPoint.Equals(Cursor.Position) Then mouse_event(2, 0, 0, 0, IntPtr.Zero) mouse_event(4, 0, 0, 0, IntPtr.Zero) Else SendKeys.Send(" ") End If Catch ex As Exception Dim tempData() As String Dim I As Integer SendKeys.Send(" ") tempData = Split(ex.ToString, vbCrLf) For I = LBound(tempData) To UBound(tempData) TextBox1.AppendText(Now & vbTab & tempData(I) & vbCrLf) Next End Try End Sub Private Sub MoveCursor(ByVal Fx As Integer, ByVal Fy As Integer) newPoint = New Point(Fx, Fy) Debug.WriteLine(String.Format("Old mouse position = {0}.", Cursor.Position)) Debug.WriteLine(String.Format("Moving mouse to {0}.", newPoint)) Cursor.Position = newPoint End Sub Public Function get_ClassName(ByVal intHandle As IntPtr) As String Dim builder1 As New StringBuilder(256) Dim num1 As Integer = GetClassName(intHandle, builder1, 256) Return builder1.ToString(0, num1) End Function Thanks again for your help ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
ZeroEffect Posted December 30, 2005 Author Posted December 30, 2005 I am Still trying to get the handle of the child window from class name. but I was able to get more info about the window using a freeware program called WinDowse I think it give me more info than spy++. *** Window Information *************************************** Text Playback 1 (1) Process ID 0000032C App instance 00400000 Handle 000105B8 Parent handle 000204AA Control ID 00000000 Function 00000000 Menu handle 00000000 Coords in parent left:82, top:93, right:469, bottom:527 Coords in screen left:82, top:112, right:469, bottom:546 Window size width:387, height:434 Client area size width:379, height:407 Style 94CC0044 Extended style 00010100 ws_overlapped*| ws_popup*| ws_visible*| ws_clipsiblings*| ws_border*| ws_dlgframe*| ws_sysmenu*| ws_thickframe*| ws_ex_windowedge*| ws_ex_left*| ws_ex_ltrreading*| ws_ex_rightscrollbar*| ws_ex_controlparent *** Class Information **************************************** Name #32770 Function 77D6E54F Icon 00000000 Small icon 00000000 Cursor 00010013 Bkg brush 00000000 Module handle 77D40000 Style 00004808 cs_dblclks*| cs_savebits*| cs_globalclass This is from the test application I am using that I know has child windows that way I can move it to the primary application I want to use this on. Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
ZeroEffect Posted December 30, 2005 Author Posted December 30, 2005 Update I have been playing with this for the last while and I can't seem to get it to return the correct window. It is returning a child window but not the one I want. Private Declare Function GetWindow Lib "user32" Alias "GetWindow" _ (ByVal hwnd As IntPtr, ByVal wCmd As Integer) As IntPtr Private Const GW_CHILD = 5 ' in a sub after the main window is found Testtest = getChildWindow(hwnd) 'the function that is called Function getChildWindow(ByVal hwnd As IntPtr) As IntPtr Dim cHandle As IntPtr getChildWindow = GetWindow(hwnd, GW_CHILD) End Function More as events arise, any thoughts? Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
HJB417 Posted December 31, 2005 Posted December 31, 2005 what's the name of the program you're trying to send mouse clicks to? Quote
ZeroEffect Posted December 31, 2005 Author Posted December 31, 2005 what's the name of the program you're trying to send mouse clicks to? For testing it is dadpro32.exe by enco it is a broadcast audio system. The one for the final product is ProTools LE (ProToolsLE.exe) an audio editing system. ProTools will only run if the hardware is attached to the computer so I am extremely limited on testing with that application. I want to fire Protools remotely. and this is how I can do it. The spacebar is the shortcut for playing and stopping the editor but if I turn off the switch and the audio has ended it'll start to play again. So that is what I am trying to accomplish. Does this help you out? Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
HJB417 Posted December 31, 2005 Posted December 31, 2005 Here's code for EnumChildWindows. I converted it to vb using reflector, it's not compilable as is under vb. But the idea is, you need to declare a delegate for EnumChildWindows to use. When you call EnumChildWindows, it will invoke the delegate each time it reads/finds a new child window. In the code below, it adds it to an ArrayList. <DllImport("user32.dll", SetLastError:=True)> _ Public Shared Function EnumChildWindows(ByVal window As IntPtr, ByVal callback As EnumWindowsProc, ByVal i As Integer) As Boolean End Function <Serializable> _ Public Delegate Function EnumWindowsProc(ByVal handle As IntPtr, ByVal i As Integer) As Boolean Private ReadOnly ChildWindows As ArrayList Public Function GetChildWindows() As IntPtr() Dim windowArray2 As IntPtr() SyncLock Me.ChildWindows NativeMethods.EnumChildWindows(Me.Handle, New EnumWindowsProc(AddressOf Me.EnumerateChildProc), 0) Dim windowArray1 As IntPtr() = CType(Me.ChildWindows.ToArray(GetType(IntPtr)), IntPtr()) Me.ChildWindows.Clear windowArray2 = windowArray1 End SyncLock Return windowArray2 End Function Private Function EnumerateChildProc(ByVal Handle As IntPtr, ByVal i As Integer) As Boolean Me.ChildWindows.Add(Handle) Return True End Function Quote
ZeroEffect Posted December 31, 2005 Author Posted December 31, 2005 (edited) Private Function EnumerateChildProc(ByVal Handle As IntPtr, ByVal i As Integer) As Boolean Me.ChildWindows.Add(Handle) Return True End Function I am working with the code now, I am running into this error when the code above is run. System.NullReferenceException: Object reference not set to an instance of an object So I am a hunting. Side note I know that you have given me alot of help with this and I am slowly catching on. This is my first attempt at a program of this type so it is taking me a little bit longer to digest the code. Thank you for the help you have supplied. Thanks ZeroEffect Edited December 31, 2005 by ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
HJB417 Posted December 31, 2005 Posted December 31, 2005 Console app where 5310006 is a handle of one of the instances of vs.net I had open. Imports System Imports System.Runtime.InteropServices Module Module1 <DllImport("user32.dll", SetLastError:=True)> _ Function EnumChildWindows(ByVal window As IntPtr, ByVal callback As EnumWindowsProc, ByVal i As Integer) As Boolean End Function <Serializable()> _ Delegate Function EnumWindowsProc(ByVal handle As IntPtr, ByVal i As Integer) As Boolean Sub Main() Dim parentHandle As IntPtr = New IntPtr(5310006) EnumChildWindows(parentHandle, New EnumWindowsProc(AddressOf EnumWindowsCallBackFunction), 0) End Sub Function EnumWindowsCallBackFunction(ByVal handle As IntPtr, ByVal i As Integer) As Boolean Console.WriteLine("EnumChildWindows Found {0}.", handle) Return True End Function End Module Quote
ZeroEffect Posted January 1, 2006 Author Posted January 1, 2006 Progress Well I am able to now return all Child windows very cool. What I am doing is as one is found I grab it heigth and width and compare it to the window I need heigth and width (This window can't be resized) to get it's handle. Sounds great right... Well It grabs and goes through the child windows but it's not finding the one I want. Now using the software I mentention above I looked through the child windows it grabbed and the window I want again is not there but If I look at the window I want, it shows that the window handle for the main program as it's parent. I am not sure what I am Missing here. I do know that the child window I am looking for can exceed the bounds of the parent, it's not trapped in the main window. Is this a different kind of child window? this is on the test app and the app I want to use the program on. I am going through the msdn site now looking for some answers. Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
HJB417 Posted January 1, 2006 Posted January 1, 2006 The EnumChildWindows may not be recusive, so you may have to search the children of the children may making a call to EnumChildWindows on each child window found. Quote
ZeroEffect Posted January 2, 2006 Author Posted January 2, 2006 The EnumChildWindows may not be recusive' date=' so you may have to search the children of the children may making a call to EnumChildWindows on each child window found.[/quote'] Thanks, that was my next step and here is the result Only one of the Child windows found has a sibling and it is an edit window for a combo box. Man this is a pain, lol. So I am now I'm not sure where to go from here, Any ideas. What if this window is opened in another thread, would that make a difference? Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
HJB417 Posted January 2, 2006 Posted January 2, 2006 I would use spy++ to get the handle of the window you want and then call EnumChildWindows recursively and see if it finds it. As long as the windows belong to the same application, it won't matter which thread it's in. All input is processed by one thread in gui apps... The message pump thread. Quote
ZeroEffect Posted January 3, 2006 Author Posted January 3, 2006 I would use spy++ to get the handle of the window you want and then call EnumChildWindows recursively and see if it finds it. As long as the windows belong to the same application, it won't matter which thread it's in. All input is processed by one thread in gui apps... The message pump thread. This is how I have done it but it isn't found is there a better way of doing this? Public Function GetChildWindows(ByVal whnd As IntPtr) As IntPtr() EnumChildWindows(whnd, New EnumWindowsProc(AddressOf Me.EnumerateChildProc), 0) End Function Private Function EnumerateChildProc(ByVal Handle As IntPtr, ByVal i As Integer) As Boolean EnumChildWindows(Handle, New EnumWindowsProc(AddressOf Me.EnumerateSiblingProc), 0) Return True End Function Private Function EnumerateSiblingProc(ByVal Handle As IntPtr, ByVal i As Integer) As Boolean Dim rec1 As New Rectangle GetWindowRect(Handle, rec1) Dim WindowName As Integer = Convert.ToInt32("000103D6", 16) 'hex from Spy++ Dim int32Handle As String = Handle.ToInt32 'WindowFound = Handle If int32Handle = WindowName Then MsgBox("Match") WindowFound = Handle End If Return True End Function Thanks ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
HJB417 Posted January 7, 2006 Posted January 7, 2006 Console app. I knew the handle of a deeply nested child window. Here's code to recursively call enumchildwindow. Imports System Imports System.Collections Imports System.Runtime.InteropServices Module Module1 <DllImport("user32.dll", SetLastError:=True)> _ Function EnumChildWindows(ByVal window As IntPtr, ByVal callback As EnumWindowsProc, ByVal i As Integer) As Boolean End Function <DllImport("user32.dll", SetLastError:=True)> _ Function GetDesktopWindow() As IntPtr End Function <Serializable()> _ Delegate Function EnumWindowsProc(ByVal handle As IntPtr, ByVal i As Integer) As Boolean Private childWindows As ArrayList Sub Main() 'arraylist to store handles of found child window. childWindows = New ArrayList 'the child handle I want to look for. Dim childHandle As New IntPtr(4129470) 'search the desktop's child windows. EnumChildWindows(GetDesktopWindow, New EnumWindowsProc(AddressOf EnumerateChildProc), 0) 'output stats n facts. Console.WriteLine("Desktop has {0:N0} child window(s).", childWindows.Count) Console.WriteLine("Requested child window found: {0}", childWindows.Contains(childHandle)) End Sub Private Function EnumerateChildProc(ByVal childWindowHandle As IntPtr, ByVal i As Integer) As Boolean 'add the child window's handle to the collection. childWindows.Add(childWindowHandle) 'do stuff here if you want like check the properties of the child window 'if it's the window you want, just 'Return True' because there's no need 'to continue searching. 'do a recursive call to retrieve the child window handles of the child window. EnumChildWindows(childWindowHandle, New EnumWindowsProc(AddressOf EnumerateChildProc), 0) Return True End Function End Module Inside the EnumerateChildProc function, I would place code to determine if the childwindow is the window you want. If not, call EnumerateChildProc on the childwindow. Quote
ZeroEffect Posted January 16, 2006 Author Posted January 16, 2006 So here is what is going on. I'm still unable to return this window, but there is a update availible for the software and they have built the window I want to find into the main window. Upside I'll be able to do what I wanted to do, downside I wasn't able to find the window I was looking for. Thank for your help and I did learn alot about finding windows and such. Thanks again, ZeroEffect Quote If you can't find it, Build It. There is no place Like 127.0.0.1 also don't forget 1 + 1 = 10
Recommended Posts