marcoauto Posted May 5, 2022 Posted May 5, 2022 (edited) ciao I have a Delphi compiled program that I use for work and I can read some logs with this function: Func __ReadExternalListBox() Local $hListBox, $iItemCount $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]") ConsoleWrite("$hListBox = " & $hListBox & @CRLF) $iItemCount = _GUICtrlListBox_GetCount($hListBox) For $i = $iStart To $iItemCount - 1 ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF) Next EndFunc ;==>__ReadExternalListBox I can find pid and full path of the process. The problem is when I must open another process: I can't read the new ListBox because the title of the window to read is the same and the function $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]") return me only one handle. With Autoinfo I can read handle: is, for this instance, 0x0001099C and is $hListBox But I need to automize some function and I can't always change in runtime this values. Ideas? Is there e method to read this title windows associated to a determined pid? PS: I don't need the handle from the pid windows application, but from its control if I use _WinAPI_EnumProcessWindows() the function return me window handle, not Control handle I In this case Windows Handle is 0x001007DA but I need Control Handle that is 0x0001099C Thankyou Marco Edited May 5, 2022 by marcoauto
Danp2 Posted May 5, 2022 Posted May 5, 2022 It sounds like you already know the PID of the target application. I would use this with _WinAPI_EnumProcessWindows() to obtain the handle of the desired window. Then pass this handle as the first parameter to ControlGetHandle. Latest Webdriver UDF Release Webdriver Wiki FAQs
marcoauto Posted May 5, 2022 Author Posted May 5, 2022 3 minutes ago, Danp2 said: It sounds like you already know the PID of the target application. I would use this with _WinAPI_EnumProcessWindows() to obtain the handle of the desired window. Then pass this handle as the first parameter to ControlGetHandle. It don't works. The TlistBox is not in the main window. If I use Autoit Windows Info (see pictures above) then you can see that handle that I need is in "control tab" 😔
Danp2 Posted May 5, 2022 Posted May 5, 2022 Post your revised code showing how you used the PID to locate the window. Without that, we can't know why it isn't working as expected. Latest Webdriver UDF Release Webdriver Wiki FAQs
marcoauto Posted May 5, 2022 Author Posted May 5, 2022 the problem that i don't use pid to locate windows. I use "title". I know that "Software Setup" is the Window Title where TListBox is in. I found with Autoit Info. I use title and class with th function that i wrote in my first post: Func __ReadExternalListBox() Local $hListBox, $iItemCount $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]") ConsoleWrite("$hListBox = " & $hListBox & @CRLF) $iItemCount = _GUICtrlListBox_GetCount($hListBox) For $i = $iStart To $iItemCount - 1 ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF) Next EndFunc ;==>__ReadExternalListBox I know the process pid because I use a run process to start it, but i don't need for read TListBox $pid = Run(@ComSpec & ' /c programmDelphi.exe', $sPercorsoEncoder, @SW_HIDE) The problem is when I need to start a second, or third programDelphi.exe. I could knows their pids, but title is the same for all istances. I can associate title with pid. Sorry but my english is not very good. I don't know if I can explain my problem Thanks Marco
Earthshine Posted May 6, 2022 Posted May 6, 2022 (edited) It’s a pascal based control I doubt AutoIt can natively manipulate it. Post the code Long as it’s win32 control than AutoIt should work Edited May 6, 2022 by Earthshine My resources are limited. You must ask the right questions
Danp2 Posted May 6, 2022 Posted May 6, 2022 39 minutes ago, marcoauto said: I know the process pid because I use a run process to start it, but i don't need for read TListBox You do need it if you want to be sure that you are accessing the window from the correct instance of the application. I previously tried to explain how you could do this, but it seems that you concluded that it wouldn't work without even attempting it. 😒 16 minutes ago, Earthshine said: It’s a pascal based control I doubt AutoIt can natively manipulate it. It sounds like he had it working, just not for other instances of the app. FWIW, I have been able to access some Delphi controls in the past. Latest Webdriver UDF Release Webdriver Wiki FAQs
marcoauto Posted May 6, 2022 Author Posted May 6, 2022 6 hours ago, Earthshine said: It’s a pascal based control I doubt AutoIt can natively manipulate it. Post the code Long as it’s win32 control than AutoIt should work hi, hi, the code I use is the one I wrote in the first post. And it works perfectly. The problem is when opening an additional instance of the program. I re-write here: Func __ReadExternalListBox() Local $hListBox, $iItemCount $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]") ConsoleWrite("$hListBox = " & $hListBox & @CRLF) $iItemCount = _GUICtrlListBox_GetCount($hListBox) For $i = $iStart To $iItemCount - 1 ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF) Next EndFunc ;==>__ReadExternalListBox for the moment my program is very basic. Before continuing to develop it I wanted to figure out if I could use it with multiple instances, but the above code works great. I read everything I need from the program compiled in Delphi.
marcoauto Posted May 6, 2022 Author Posted May 6, 2022 6 hours ago, Danp2 said: You do need it if you want to be sure that you are accessing the window from the correct instance of the application. I previously tried to explain how you could do this, but it seems that you concluded that it wouldn't work without even attempting it. 😒 It sounds like he had it working, just not for other instances of the app. FWIW, I have been able to access some Delphi controls in the past. I think my English is worse than I thought ... I tried as you said with the _WinAPI_EnumProcessWindows () function but, as I wrote in the first post, it doesn't work! Or at least, what comes back to me isn't what I need. In the array I have 3 return values: the first for "TSetUpForm", the second for "TMainForm", and third for "TApplication" but I need the handle associated with the TListBox class: INSTANCE: 1 With ths function I read all I need, but only if I one only instance of running program: Func __ReadExternalListBox() Local $hListBox, $iItemCount $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]") ConsoleWrite("$hListBox = " & $hListBox & @CRLF) $iItemCount = _GUICtrlListBox_GetCount($hListBox) For $i = $iStart To $iItemCount - 1 ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF) Next EndFunc ;==>__ReadExternalListBox Now, I ran the function. Program PID is 10248 if I use _arraydisplay(_WinAPI_EnumProcessWindows(10248)) the array is but $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]") ConsoleWrite("$hListBox = " & $hListBox & @CRLF) $hListBox = 0x00540406 I don't need this: but I need this: if I use ControlGetHandle I read everything, but in the case of multiple open instances it returns only one and I don't know how to read the value of that handle associated with that particular pid, since I find the value through the title which is obviously identical for all instances of the program thank you all Marco
Danp2 Posted May 6, 2022 Posted May 6, 2022 @marcoautoYour English is fine. Maybe I didn't properly explain the steps needed, so let's try again -- Get the PID of the desired instance. You already have this from your Run() command. Use this PID with _WinAPI_EnumProcessWindows() to obtain the handle of the desired window. Store the result into an array Locate the desired row with "TSetupForm" in the second column Grab the window handle from the first column Now that you have the correct window handle, use it in conjunction with ControlGetHandle to obtain the desired control handle. Your code would look something like this -- $pid = Run(@ComSpec & ' /c programmDelphi.exe', $sPercorsoEncoder, @SW_HIDE) $aWindows = _WinAPI_EnumProcessWindows($pid) $iIndex = _ArraySearch($aWindows, "TSetupForm", 0, 0, 0, 0, 1, 1) $hWnd = $aWindows[$iIndex][0] $hListBox = ControlGetHandle($hWnd, "", "[CLASS:TListBox; INSTANCE:1]") To be clear, the above code is untested, needs error handling, etc. 😉 Earthshine 1 Latest Webdriver UDF Release Webdriver Wiki FAQs
marcoauto Posted May 6, 2022 Author Posted May 6, 2022 10 hours ago, Danp2 said: @marcoautoYour English is fine. Maybe I didn't properly explain the steps needed, so let's try again -- Get the PID of the desired instance. You already have this from your Run() command. Use this PID with _WinAPI_EnumProcessWindows() to obtain the handle of the desired window. Store the result into an array Locate the desired row with "TSetupForm" in the second column Grab the window handle from the first column Now that you have the correct window handle, use it in conjunction with ControlGetHandle to obtain the desired control handle. Your code would look something like this -- $pid = Run(@ComSpec & ' /c programmDelphi.exe', $sPercorsoEncoder, @SW_HIDE) $aWindows = _WinAPI_EnumProcessWindows($pid) $iIndex = _ArraySearch($aWindows, "TSetupForm", 0, 0, 0, 0, 1, 1) $hWnd = $aWindows[$iIndex][0] $hListBox = ControlGetHandle($hWnd, "", "[CLASS:TListBox; INSTANCE:1]") To be clear, the above code is untested, needs error handling, etc. 😉 hi, thanks for your time and your help. I can't read handle I need. For now I have a workaround for my problem using a different program, but I'll continue to investigate and try. Thankyou again
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now