Jump to content

kamyers1

Active Members
  • Posts

    41
  • Joined

  • Last visited

Everything posted by kamyers1

  1. Although I have no access to the source code, I do know that the application I am attempting to control was written using VB 6 as a completely local, non-IE, non-HTML application. The treeview control in question is identified as a TreeView20WndClass object by AutoIt Windows Info. Besides, I'm not having any problems using other ControlTreeView commands on this control. It is only commands related to the text (GetText and Select by node text) that I am having a problem with. P.S. - Maybe it wasn't obvious from my prior message, but it is MY controller application which uses the AutoItX COM object that is written using VBScript, not the application that I am attempting to control. Thanks, Kevin M.
  2. Folks, I am cross-posting this from the AutoItX (COM control) forum (with a little more info). I have posted on that forum several times with no response, and am hoping to have better luck here, since more people apparently use this forum. Also, the ControlTreeView related stuff that I need to use should be almost identical between regular AutoIt and AutoItX... I am attempting to use the ControlTreeView method GetText command on a tree view control (TreeView20WndClass) from a vbscript application under Windows XP. Here is the code that I used: text=AutoIt.ControlTreeView("Output", "", "TreeView20WndClass3, "GetText", "#0","") Using that command, text comes back blank, and AutoIt.error=1. However, text does appear on the nodes of this control, and I am able to successfully execute other ControlTreeView commands on this control, including Exists, GetItemCount, Collapse, and Expand. The TreeView object in question exists on a tab control, and the relevant tab is active (displayed) when I am attempting to manipulate the TreeView. The owning application window is also active. I have tried enabling and giving focus to the TreeView control, but none of that seems to make any difference. I am able to send keystrokes to the TreeView, and can also select a node by index. However, selecting a node based on its text doesn't seem to work either. This is AutoItX 3.3.0.0 under Windows XP SP3 with all critical updates applied. Am I doing something wrong? Any suggestions? Thanks, Kevin M.
  3. I am attempting to use the ControlTreeView method GetText command on a tree view control (TreeView20WndClass) from a vbscript application under Windows XP. Here is the code that I used: text=AutoIt.ControlTreeView("Output", "", "TreeView20WndClass3, "GetText", "#0","") Using that command, text comes back blank, and AutoIt.error=1. However, text does appear on the nodes of this control, and I am able to successfully execute other ControlTreeView commands on this control, including Exists, GetItemCount, Collapse, and Expand. Select doesn't return an error, but also doesn't seem to work. Am I doing something wrong? Any suggestions? Thanks, Kevin M.
  4. Still needing some help on this. Is anyone out there??? I tried the following series of statements: wscript.echo "control=" & control wscript.echo "OutType=" & OutType wscript.echo "IsVisible=" & AutoIt.ControlCommand("Output", "", control, "IsVisible", "") wscript.echo "error=" & AutoIt.error wscript.echo "IsEnabled=" & AutoIt.ControlCommand("Output", "", control, "IsEnabled", "") wscript.echo "error=" & AutoIt.error wscript.echo "Exists=" & AutoIt.ControlTreeView("Output", "", control, "Exists", OutType, "") wscript.echo "error=" & AutoIt.error wscript.echo "Exists=" & AutoIt.ControlTreeView("Output", "", "TreeView20WndClass3", "Exists", "Exports", "") wscript.echo "error=" & AutoIt.error wscript.echo "GetItemCount=" & AutoIt.ControlTreeView("Output", "", "TreeView20WndClass3", "GetItemCount", "Exports", "") wscript.echo "error=" & AutoIt.error wscript.echo "GetText=" & AutoIt.ControlTreeView("Output", "", "TreeView20WndClass3", "GetText", "#0", "") wscript.echo "error=" & AutoIt.error wscript.echo "GetText=" & AutoIt.ControlTreeView("Output", "", "TreeView20WndClass3", "GetText", "#0|#0", "") wscript.echo "error=" & AutoIt.error Here are the results: control=TreeView20WndClass3 OutType=Exports IsVisible=1 error=0 IsEnabled=1 error=0 Exists=0 error=0 Exists=0 error=0 GetItemCount=0 error=0 GetText= error=1 GetText= error=1 P.S. - I think that this problem may have something to do with the fact that this treeview control is located within a tab control. One of the other tabs has a listview conrol, and I am also having problems reading the text from items in that listview, whereas I have been able to read text from other listview controls not located within tab controls without difficulty. Is there something special that I need to do in order to deal with treeview and listview controls when they are located within a tab control?
  5. Well I thought I had this figured out, but guess that I don't after all. In the very first case that I tested, I have a listview that looks as follows: There is a single top level item with the text Exports, and eleven second level items beneath that. When I try the following code, what gets printed is 0 (zero). wscript.echo AutoIt.ControlTreeView("Output", "", "TreeView20WndClass3", "Exists", "Exports", "") I have double, triple, and quadruple checked the text (spelling, case, no blank padding, etc.) for the window, the treeview control, and the item in the tree. They all appear to be exactly as listed in the above statement. Based on clicking on the items so that they are highlighted, there don't appear to be any extraneous blanks that could be confusing things. Based on my reading of the docs, I thought that function call should return a 1, since a top level node with the text "Exports" *does* exist. What am I doing wrong? Thanks, Kevin M.
  6. Never mind, I finally located the [ACTIVE] option under the Window Titles and Texas (Advanced) docs. Sorry for the extra message.
  7. In AutoItX, is there a method available to find the currently active window? I may be blind, but I'm sure not finding one in the docs. I suppose that I could loop over all of the windows returned using WinList and check the state using WinGetState for each window, but that would be really slow. Sure there must be a better was...?
  8. I may be missing the obvious, but it is unclear to me how to navigate the nodes in a treeview control using the ControlTreeView commands available in AutoItX. I have a treeview with nodes that are two levels deep, and I need to select one of the leaf nodes based on a text value for the parent node and separate text value for the child node. There can be duplicate text for leaf nodes with different parent nodes. So basically, I need to find the parent node based on a text value, then find a leaf node for that parent node based on a different text value, then select that leaf node. Can someone please provide an example of how to do this? Since I am posting this in the ActiveX/COM forum, hopefully it is obvious that I need to do this using AutoItX. Thanks, Kevin M.
  9. Right, but I think that I would appreciate a more definitive answer, from someone in the know if possible. By the way, I don't think that the two possibilities you mentioned are technically equivalent, are they? If not, then it could matter to users which one of these is really happening.
  10. Based on what I have seen so far, I'm not certain this is even possible. But if it is... I'd like very much to have a method for sending keystrokes to an inactive window, i.e. a window that does not have focus. Similar to a hybrid of Send and ControlSend, that doesn't need the destination window to be active and doesn't need a specific control to send the keys to. Thanks, Kevin M.
  11. I was doing some testing, using AutoItX to control Windows Notepad, when I happened to find that the follow unexpectedly worked: set AutoIt=WScript.CreateObject("AutoItX3.Control") AppWindowName="Untitled - Notepad" AutoIt.ControlSend AppWindowName,"","","^o" Can someone please explain exactly what this (using ControlSend without a control name) actually does? Does it send directly to the application window, or to the first child window of the application window, or something else? The reason that I care is that I am looking hard for some way to send accelerator keystrokes to inactive windows. Since the windows are inactive, Send won't do the job, and I can't find the appropriate control to send accelerator keys to for some applications. So, if ControlSend without a control name is actually sending to the application window itself, or to some control that is set by default to receive keystrokes for the application, then using ControlSend in this manner *might* solve some of my problems. On the other hand, if this use of ControlSend is simply sending keystrokes to the *first* child control of the application window, then that most likely won't do me any good in general. Thanks, Kevin M.
  12. Ok, been working on this all day and all night, still no luck. I've got to be missing something simple. Currently I am able to send text to the Edit control in a Notepad application using VB, but I can't seem to figure out the right mechanism for sending accelerator keys, e.g. Ctrl-O for File->Open, even if the Notepad window is already active. I know that can be done, because the AutoItX Send method can do it, so I must be doing something wrong. Once again, my purpose in doing this is that I need to send accelerator keys to an *inactive* window, which AutoItX can't currently seem to do (I've already tried). So I am writing VB code to try to work around this limitation. But if I can't manage to send the appropriate messages to a simple application like Notepad when it is already active, then I don't stand a prayer of accomplishing my real goal with other apps that aren't currently active. I know this isn't a VB forum, but folks on here are experienced with writing code to control other apps, so I am hoping that someone can spot what I am missing. Current version of code that I am trying to run is listed below. By the way, Notepad "beeps" when this code runs, and Winspector Spy seems to show that it is receiving the appropriate messages, so surely I must be fairly close... Oh by the way, the WM_COMMAND version that is commented out below *does* work, but I don't want to use that for general purpose work, because it requires knowing menu id values that are application specific and a bit of a pain to come up with. Much nicer if I could just manage to send the stupid accelerator keys! Thanks, KM Module crazy Private Declare Auto Function FindWindow Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr Private Declare Auto Function PostMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Boolean Private Declare Auto Function GetWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal uCmd As Integer) As IntPtr Private Const WM_KEYDOWN = &H100 Private Const WM_CHAR = &H102 Private Const WM_KEYUP = &H101 Private Const WM_COMMAND = &H111 Private Const GW_CHILD = 5 Sub Main() Dim whnd As IntPtr = FindWindow(vbNullString, "untitled - notepad") Dim Cwhnd As IntPtr = GetWindow(whnd, GW_CHILD) 'PostMessage(whnd, WM_KEYDOWN, &H11, &H11D0001) 'PostMessage(whnd, WM_KEYDOWN, &H4F, &H440001) 'PostMessage(whnd, WM_CHAR, &HF, &H440001) 'PostMessage(whnd, WM_KEYUP, &H4F, &HC0440001) 'PostMessage(whnd, WM_KEYUP, &H11, &HC11D0001) 'PostMessage(whnd, WM_COMMAND, &H10002, &H0) PostMessage(Cwhnd, WM_KEYDOWN, &H11, &H1D0001) PostMessage(Cwhnd, WM_KEYDOWN, &H4F, &H180001) PostMessage(Cwhnd, WM_CHAR, &HF, &H180001) PostMessage(Cwhnd, WM_KEYUP, &H4F, &HC0180001) PostMessage(Cwhnd, WM_KEYUP, &H11, &HC01D0001) 'Dim Txt As String = "CRAZY" 'For x As Integer = 0 To Txt.Length - 1 ' PostMessage(Cwhnd, WM_KEYDOWN, CInt(Asc(Txt.Chars(x))), &H2F0001) 'Next End Sub End Module
  13. Sorry, just posted re-formatted code. I wasn't familiar with this forum's methods for handling code.
  14. I made some corrections to my VB code that eliminates the non-zero result value from calling SendMessage, but I'm still not having any luck getting apps to respond to the sent text in any way, not even if they are active. Not even simple apps like Notepad and Calculator. Latest VB code below... Imports System.Runtime.InteropServices Imports System Module SendCharsByHandle <DllImport("user32", EntryPoint:="FindWindow")> _ Private Function FindWindow( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Int32 End Function <DllImport("user32", EntryPoint:="GetWindow")> _ Private Function GetWindow( _ ByVal hwnd As Int32, _ ByVal wCmd As Int32) As Int32 End Function <DllImport("user32", EntryPoint:="GetWindowText")> _ Private Function GetWindowText( _ ByVal hwnd As Int32, _ ByVal lpString As System.Text.StringBuilder, _ ByVal cch As Int32) As Int32 End Function <DllImport("user32", EntryPoint:="SendMessageA")> _ Private Function SendMessage( _ ByVal hwnd As UInteger, _ ByVal wMsg As UInteger, _ ByVal wparam As UInteger, _ ByVal lparam As UInteger) As UInteger End Function Sub Main() Dim MyStr As String Dim nArgs, nArg, nChars, nChar As Short Dim result As UInteger Dim handle, handle2 As UInteger Dim message As UInteger Dim wparam As UInteger Dim lparam As UInteger Dim gotHandle As Boolean Const WM_CHAR As UInteger = &H102 message = WM_CHAR 'WM_CHAR message constant lparam = 0 nArgs = UBound(Environment.GetCommandLineArgs()) Console.WriteLine("nArgs=" & nArgs) If nArgs > 0 Then If IsNumeric(Environment.GetCommandLineArgs(1)) Then handle = CLng(Environment.GetCommandLineArgs(1)) gotHandle = GetHandleFromPartialCaption(handle2, "Untitled - Notepad") Console.WriteLine("Handle=" & handle & ", handle2=" & handle2) If gotHandle Then handle = handle2 For nArg = 2 To nArgs MyStr = Environment.GetCommandLineArgs(nArg) nChars = Len(MyStr) Console.WriteLine("nArg=" & nArg & ", MyStr=" & MyStr & ", nChars=" & nChars) For nChar = 1 To Len(MyStr) wparam = CLng(Asc(Mid(MyStr, nChar, 1))) Console.WriteLine("wparam=" & wparam) Console.WriteLine("handle=" & handle & ", message=" & message & ", wparam=" & wparam & ", lparam=" & lparam) result = SendMessage(handle, message, wparam, lparam) Console.WriteLine("result=" & result) Next Next Else Console.WriteLine("Invalid arguments. Correct syntax is: SendKeysByHandle <handle> <string>") End If Else Console.WriteLine("Invalid arguments. Correct syntax is: SendKeysByHandle <handle> <string>") End If End Sub Private Function GetHandleFromPartialCaption(ByRef lWnd As Int32, ByVal sCaption As String) As Boolean Dim Caption As New System.Text.StringBuilder(256) Dim lhWndP As Int32 Const GW_HWNDNEXT As Int32 = 2 GetHandleFromPartialCaption = False lhWndP = FindWindow(vbNullString, vbNullString) Do While lhWndP <> 0 GetWindowText(lhWndP, Caption, Caption.Capacity) If InStr(1, Caption.ToString(), sCaption) > 0 Then GetHandleFromPartialCaption = True lWnd = lhWndP Exit Do End If lhWndP = GetWindow(lhWndP, GW_HWNDNEXT) Loop End Function End Module
  15. But I tried several different apps including Notepad and Calculator, and none of them responded! I suspect there is probably something wrong with my VB code, maybe something do with the handle. Perhaps the handle value needs to get converted from a Long to a "true" handle, but I don't know how to do that if so. Was hoping that some of the gurus on this site might know. I have also posted to Microsoft's VB forum with no luck so far.
  16. Using AutoitX (not Autoit!), I would like to send characters to an inactive window in order to force that window to execute one of its menu options. The menu is non-standard, so WinMenuSelectItem doesn't work. Send works, but only if the window is active, and that isn't adequate for my needs. ControlSend can send characters to various controls on the window, but I can't find any way to get it to activate the menu items. The window in question is the main form (ThunderRT6MDIForm) of a VB6 based application. I thought that I had another solution, but it doesn't work. Here is what I tried: 1. I get the window handle using WinGetHandle from AutoitX. That part works ok, and I have verified that the correct handle value is returned by using other tools. 2. I wrote a little VB utility to send characters to a specific window handle by using the SendMessageA Windows API function. When I run the VB utility, still no luck! My VB code is pretty simple, and I output stuff from each step in my code so that I can verify they are working as anticipated. Everything seems perfect until I make the actual API call. But then there is no response from the application, and I get back a result value of 8975925931411505152 from the API call. I assume that is some kind of error code, but have no idea what it means. My VB code is posted below. Can anyone here help out? Thanks, Kevin M. With a new Notepad window open, if I run the code listed below from a console window, here is what I get: C:\myApp\bin>test.vbs handle=1512254 SendCharsByHandle 1512254 ☼ nArgs=2 Handle=1512254 nArg=2, MyStr=☼, nChars=1 wparam=15 handle=1512254, message=258, wparam=15, lparam=0 result=8975925931411505152 Here is test.vbs: set AutoIt=WScript.CreateObject("AutoItX3.Control") set Shell=CreateObject("WScript.Shell") AppWindowName="Untitled - Notepad" AutoIt.WinActivate AppWindowName WScript.Sleep(1000) handle=AutoIt.WinGetHandle(AppWindowName) WScript.Echo "handle=" & CLng("&h" & handle) rem char(15) is CTRL-O, should execute Notepad's File->Open menu item. command="SendCharsByHandle " & CLng("&h" & handle) & " " & chr(15) WScript.Echo command execCmd(command) WScript.Quit(0) function execCmd(command) set oCommand=shell.exec(command) do until oCommand.Status=1 and oCommand.StdOut.AtEndOfStream if oCommand.StdOut.AtEndOfStream then WScript.Sleep 100 else WScript.Echo oCommand.StdOut.ReadLine end if loop 'until oCommand.Status=1 and oCommand.StdOut.AtEndOfStream execCmd=oCommand.ExitCode end function 'execCmd Here is SendCharsByHandle.VB: Imports System Module SendKeysByHandle Public Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wparam As Long, _ ByVal lparam As Long) As Long Sub Main() Dim MyStr As String Dim nArgs, nArg, nChars, nChar As Short Dim result As Long Dim handle As Long Dim message As Long Dim wparam As Long Dim lparam As Long Const WM_CHAR = &H102 message = WM_CHAR 'WM_CHAR message constant lparam = 0 nArgs = UBound(Environment.GetCommandLineArgs()) Console.WriteLine("nArgs=" & nArgs) If nArgs > 0 Then If IsNumeric(Environment.GetCommandLineArgs(1)) Then handle = CLng(Environment.GetCommandLineArgs(1)) Console.WriteLine("Handle=" & handle) For nArg = 2 To nArgs MyStr = Environment.GetCommandLineArgs(nArg) nChars = Len(MyStr) Console.WriteLine("nArg=" & nArg & ", MyStr=" & MyStr & ", nChars=" & nChars) For nChar = 1 To Len(MyStr) wparam = CLng(Asc(Mid(MyStr, nChar, 1))) Console.WriteLine("wparam=" & wparam) Console.WriteLine("handle=" & handle & ", message=" & message & ", wparam=" & wparam & ", lparam=" & lparam) result = SendMessage(handle, message, wparam, lparam) Console.WriteLine("result=" & result) Next Next Else Console.WriteLine("Invalid arguments. Correct syntax is: SendKeysByHandle <handle> <string>") End If Else Console.WriteLine("Invalid arguments. Correct syntax is: SendKeysByHandle <handle> <string>") End If End Sub End Module
  17. Thanks a lot for your suggestion. I have started a separate thread where I already ventured down this path (see Status Bar Pixel Checksum in this forum). However, I have a problem with this approach because my app needs to run in the background, i.e. as an inactive window. Therefore PixelChecksum won't work, unfortunately. :-( I don't suppose you happen to know of any way to perform a pixel checksum on an inactive (potentially minimized) window? Kevin M.
  18. I see now that the coordinates for PixelChecksum must be screen coordinates rather than window coordinates, since there is no window identifier argument to the function (well DUH!). So, this means that 1) my code needs to add the top left window coordinates (easily done), and 2) this code will only work while the target application window is on top. That's a bummer, because I need to be able to do this while the application window is *inactive*, and very likely hidden behind other windows, maybe even minimized. :-( Seems like every thing I try to do with this application using AutoIt is running up against brick walls. Kevin M.
  19. I am attempting to control an application where I need to detect changes in the text displayed in a status bar. But the status bar is owner drawn, therefore you can't get at the text directly. All of that has been discussed at length in a separate thread. So, now what I want to try is computing a checksum on the part of the status bar that I care about, and compare that checksum to a checksum that has been computed when I know that the status bar is displaying the specific text that I am waiting for. I wrote some code to test out this approach, but it doesn't seem to be working right. The pixel checksum values are changing even when everything in the application window is completely static, not changing at all. Can anyone tell me what I am doing wrong? The code that I am trying to use is attached. Thanks, Kevin M.
  20. Guys, this may be real old news by now, but just FWIW, you can run editbin.exe on AutoIt3.exe, producing a new version of AutoIt3.exe that allows writes to a console window directly from uncompiled scripts. It is common to use this technique with the GIMP and other *nix based software that runs under Windows. Typically, console mode is enabled while debugging an application, and turned off for the production release. But it can always be turned back on by the user by using editbin, if desired. I believe that the only disadvantage to turning on console mode is that any console mode app *must* have a console window in order to run. Because of this, a console mode app will actually start its own console window if the app wasn't started directly from console window. This can be confusing for users of a GUI app who aren't expecting to see the extra console window and try to close it, etc. Hope that makes sense and some of it may be useful. Kevin M.
  21. Finally found that 1000 hex (high word) *does* mean that the status bar part is "owner drawn". Which means that there is no direct way to obtain the displayed text. SO, I'm wondering now if there is some way that I can use AutoIt to perform a bit map comparison against this portion of the status bar instead...? Kevin M.
  22. Using _Status_GetTextFlags returns 268435456 (10000000 hex) for the first five parts. I haven't yet located a reference that provides the decoded bit values in the high word. Can anyone tell me if this means that these status bar parts are "owner-drawn"? Kevin M.
  23. Well, that could have been a big help, and was certainly worth a try, but unfortunately it didn't work. _Status_GetParts did return seven parts from the status bar, but unfortunately _Status_GetText returned null strings for all seven parts. :-( Let me know if any other ideas, and thanks again. Kevin M.
  24. Ok, a more intelligent question than my last post (sorry about that one)... I am attempting to control an application where I need to detect when a certain action that requires very substantial execution time has completed. The amount of time required may vary from a few seconds to several hours. I need to detect when this long-winded action has completed so that I know when the application is ready to execute further actions. The appearance of "Ready" in the status bar is the only consistent indication in the application that I have noted which shows when the long-winded action has completed. This action does not produce any external files or any other effects external to the application that could be detected to my knowledge. The application doesn't appear to effectively buffer keystrokes or mouse actions while the long-winded action is executing, so I can't simply attempt to execute addtional actions without waiting for the long winded action to complete. And I can't simply pause script execution while the long-winded action completes due to the extreme variability in the amount of time that may be required. AutoIt Window Info detects the status bar and identifies it to be a StatusBar20WndClass control, but it doesn't report any text for either the status bar or the control. Can someone advise how I may be able to detect the appearance of "Ready" in this control? Thanks, Kevin M.
  25. Thanks for your very prompt, helpful, and courteous reply! Somewhat undeserved in this case I'm afraid. I was being too lazy. I should have found this on my own if I had thought about it for about two more minutes before posting a message. Guess I was just getting a headache from attempting to deal with the problem that I posted under the Enhancement Requests forum regarding sending keystrokes to an inactive window, and trying to figure out if/how I might be able to use _SendMessage for that purpose. Kevin M.
×
×
  • Create New...