Autohotkey get control from tooltip - controls

I need to find the control's name to which its tooltip is linked.
I'm asking this because I need to control click within TeamCenter 10, but the control names keep changing just as you click on any of them. This makes it difficult to keep my code running smoothly when I need to repeat tasks.
If there is a better way of doing this (in Autohotkey), please let me know.

You can try this (Replace title of TeamCenter 10 with the exact title of the TeamCenter window as shown in Window Spy):
F1::
; Retrieve the control name for each control in a window:
WinGet, List, ControlList, title of TeamCenter 10
; Examine the individual control names one by one, using a parsing loop:
Loop, Parse, List, `n
{
If InStr(A_LoopField, "SWT_Window02") ; use only the part of the control name that is always shown in Window Spy
ControlClick, %A_LoopField%, title of TeamCenter 10
break
}
return
https://autohotkey.com/docs/commands/WinGet.htm#ControlList

Related

AHK Cannot ControlClick on hidden elements in nested child window

I'm trying to automate a many clicking process, just to narrow it to the user input.
I encountered problems in controlClicking interface elements, which seems not to be standard Windows GUI elements.
When pointing them with WinSpy they don't appear as separate buttons, but I can point the whole child Window which is drawn in the main program window.
As on pic1, I pointed the whole window and I can find each tab/button by it's text inside and on pic2 I can inspect the ClassNN of that element and it's ID.
As far as clicking other buttons in the main menu bar of the program works, a simple:
ControlClick, ClaTab_01000000H26, WindowName
doesn't work. I think during the day, and many possibilities I tried, I could ControlClick the above button by pointing it with its ID, but that ID changes every instance. I could confirm that tomorrow if it works by ID.
Of course I tried SetControlDelay -1 and ,NN option. But don't take that for granted, I can try any of your suggestions tomorrow.
Both tabs marked with purple color, are to find in the Windows->SiblingWindows tab. I really don't want using x,yCoords (that actually work), but I need the script to be as reliable as possible.
So my questions are:
Am I missing something or you have any suggestions how to click that elements?
Is it correct, that no matter how deep the child windows get (one has buttons to open another on top of it), all the time the WinName stays the same pointing to the main program ***.exe?
Could you provide an example from the web or yours, to find an element's ID by providing the text attached to the button (pic1-red line and also pic2 in "text")?
I also cannot maximize the child window. Double clicking it works, but I can't find the appropriate ClassNN of the window to call.
Could you provide an example, how to use the Messages tab? I assume, if I find the button as on the pictures, I could send a message with controlClick and see if there's a reaction?
1.Ugh. I found the solution, which is awesome, but a little frustrating that with a bit of luck I tried another aproach that's not that logical for a newbie like me:
instead:
ControlClick, ClaTab_01000000H6, ahk_class ClaWin01000000H_2,,,, NA
it's just
ControlFocus, ClaTab_01000000H6, ahk_class ClaWin01000000H_2,,,, NA
2._Yep. One child window creates another and another and another, but winTitle stays the same. In my case:
ahk_class ClaWin01000000H_2
3._Code below returns the handle/ID of the element you specify. Change ClaTab and ClaWin to your chouice.
ControlGet, OutputVar, hwnd,, ClaTab_01000000H1, ahk_class ClaWin01000000H_2
MsgBox, %OutputVar%`
Probably to be continued.
I highly recomend to both use
WinSpy https://www.autohotkey.com/boards/viewtopic.php?t=28220
SimpleSpy https://www.the-automator.com/downloads/simple-spy/
First one has lots of useful information and the window tab provides information of hidden buttons/windows. Second one in a more clear way indicates the parent window and its class.

How can I determine what part of text in a scroll view is visible on screen from an Xcode UI test?

I'm new to the Xcode User Interface testing framework. I can successfully manipulate the screen elements, but cannot work out how to produce a meaningful assertion about what text is visible in a scrolling view.
The test I would like to write would go as follows: launch the app, type lots of text into a text view (enough that the first line scrolls out of view), assert that the first line of text is not visible, scroll the view back up to the top, then assert that the first line is now visible. Note that the purpose of this test is to ensure my app has wired things up correctly, not to test Apple's code.
XCUIApplication allows me to type into my NSTextView instance, and also allows me to scroll the associated NSScrollView. But how do I assert whether the first line of text is currently visible? The value attribute on XCUIElement provides the entire text content of the view, whether or not it is currently displayed.
The accessibilityRange(forLine:) and accessibilityString(for:) methods on NSTextView would be ideal, but I can't see how to access them as the UI test only has access to an XCUIElement, not the underlying NSTextView.
Have I missed something, or is there a better way to approach this?
If you set the accessibility identifier in the storyboard or in code for the text view you can get the text view via (assuming you gave it the id "textview1" and the window it's in has the default accessibility identifier of "Window"):
let textview1TextView = app.windows["Window"].textViews["textview1"]
but that won't actually get you what you need.
Instead, set the accessibility identifier of the scrollview and get that:
let scrollview = app.windows["Window"].scrollViews["scrollview1"]
Then use that to get the scrollbars (you should only have one in this case; you can use scrollbars.count to check.
let scrollbars = scrollview.scrollBars
print("scrollbars count: \(scrollbars.count)")
Then you can use the value attribute of the scrollbar to get it's value:
(you're converting a XCUIElemenTypeQueryProvider into an XCUIElement so you can get it's value):
let val = scrollbars.element.value
it will be 0 at the top and a floating point value when scrolled (one line of text in my test code showed a value of {{0.02409638554216868}}.
Documentation that will help you explore further:
XCUIElementTypeQueryProvider
XCUIElementAttributes
Note that you can put a breakpoint in the middle of your test, run it and then use the debugger console to examine things:
(lldb) po scrollbars.element.value
t = 749.66s Find the ScrollBar ▿ Optional<Any>
- some : 0
(lldb) po scrollbars.element.value
t = 758.17s Find the ScrollBar ▿ Optional<Any>
- some : 0.05421686746987952
and while in the debugger you can even interact with your app's window to scroll it manually (which is what I did between typing in those two po calls), or perhaps add text and so on.
OK OP now noted that they're interested in the specific text showing or not rather than the first line in view or not (which is what I previously answered above).
Here's a bit of a hack, but I think it'll work:
Use XCUICoordinate's click(forDuration:, thenDragTo:) method to select the first line of text (use the view frame to calculate coordinates) and then use the typeKey( modifierFlags:) to invoke the edit menu "copy" command. Then use NSPasteboard methods to get the pasteboard contents and check the text.
Here's a quick test I did to validate the approach (selecting the first line of text using XCUICoordinate as noted above is left as an exercise for the reader):
NSPasteboard.general.clearContents()
// stopped at break point on next line and I manually selected the text of the first line of text in my test app and then hit continue in the debugger
textview1TextView.typeKey("c", modifierFlags:.command)
print( NSPasteboard.general.pasteboardItems?.first?.string(forType: NSPasteboard.PasteboardType.string) ?? "none" );
-> "the text of the first line" was printed to the console.
Note that you can scroll the selection off screen so you have to not scroll after doing the select or you won't be getting the answer you want.

Positioning mouse cursor on another Application's List item entry based on its text value

I want to do an automation using Excel VBA. First of all I am not sure if its possible so I need to explain the problem first.
I would launch an application which has a list of reports , that one can run by right clicking on any of these and selecting an entry from the popup menu caled say "Run this report". The problem is the report names are displayed in a listbox.
There are so many entries I only need to run a few of them based on their names.
To achieve this I thought about placing the mouse cursor on the text displaying the appropriate report name and then trigger the right click event. These can be done using Windows APIs.
The challenge I am facing is how to hover my mouse on any particular list item based on its display text.
I can enumerate all the windows controls based on the handle of the application's window, but is it possible to get the location of any item on the screen based on the text displayed on list item.

Messagebox centered to parent Window / Form

I am trying to build my own HTA right now to act as a front end for some of my batch scripts. I would like to use a msgbox (or anything equivalent) that I can use to output any errors, clicking Ok will just get rid of the prompt.
Here is the code I have been using:
x=msgbox("Error text" ,48, "Error: Title")
I would preferably like the following conditions, to be able to use a custom icon, the box to center on X and Y to the parent window/form, and to allow me to define the text in the box and it's title.
If this is not possible then just a messagebox that can be centered on X and Y to the parent window would suffice.
Is there any way of doing this in VBScript?
Or should I look into doing an HTML/CSS version that would popup on the screen?
I don't know the answer to your first question, but whatever the answer is there must be necessarily limits to what a box message box that pops up outside of the HTML can do.
So for customization that includes icon, centering and anything else expressible in HTML/CSS, I think you should do HTML/CSS that pops up on the screen.
You might want to look at jqueryui or bootstrap to get you going faster so you don't have to start from scratch.
https://jqueryui.com/dialog/#modal-message
http://getbootstrap.com/javascript/#modals
They both use jquery underneath so if you aren't already using it, you'll pick up some more bytes in your initial download.

Get Context Menu text of specific TaskBar button

I've got some code that grabs the TaskBar buttons and their text from the windows TaskBar using User32.SendMessage with the TB_GETBUTTON message to retrieve a TBBUTTON structure (Win32 API via C# P/Invokes). But I'm trying to figure out how to then, once I have the handle to the button, grab the associated context menu text. There is some status information on there for a specific application that I would like to retrieve. The button text gets me some of it, but I need to the context menu text to complete it.
Any ideas?
This is not completely clear... Context menus don't have text, as such - they have menu items, each one of which will have text. By "context menu text", do you mean the text of the menu items in the taskbar button's popup/context menu? For example, "Restore", "Minimize" etc in the screenshot below?
If so, I suspect you're going about this the wrong way:
This menu doesn't belong to the button, but is the system menu of the window represented by the taskbar button. If the button has a context menu, this is probably for a grouped collection of windows, not one specific window (or even windows for one process.)
Making judgements based on the context menu of a window sounds like a dodgy approach to me, especially based on text since that will change depending on where in the world your user is located. Applications can also change the contents of this menu so there's no guarantee it will contain something you expect to be there. It would be better to check the window style, if it's minimized, etc, to find out the information that also affects the contents of the menu.
I'm going to answer this based on what your needs seem to be from the question, not what you've directly asked, since (a) it's not possible as asked and (b) I think you're trying to do something else. (As a general guideline, in a question it's good to state why you're trying to do something - and even maybe ask about that, ie 'how do I achieve X' - in case there's a better method than the one you're using. Here, X is probably 'find out information about this window' not 'get the text of the context menu', because that's probably only one possible method to get to X.) Also I think extracting data from the internals of a third-party application like Explorer (the taskbar is an Explorer window) is fragile and prone to break in future versions of Windows.
The system menu or window information (whichever one) belongs to application windows. Unless taskbar buttons are grouped (and then it's the subitems) one taskbar button corresponds to one specific window in the system. So what you want to do is find these windows. You do this by:
Using the EnumWindows function
Then for each window that is passed to the callback, checking the extended window style using GetWindowLong with GWL_EXSTYLE to see if the WS_EX_APPWINDOW bit is set
In addition, sometimes other windows are shown: these heuristics should help.
Each one of these windows is a window that should appear on the taskbar, Alt-Tab dialog, etc.
You say you're getting the text of the taskbar button - this is probably the window caption of the window, and GetWindowText is the canonical (read: probably a lot more reliable) way to get the caption of a window belonging to another process.
If you really want the popup menu, then:
Use GetSystemMenu to retrieve the handle for the system menu for the window. Applications can customise this, so if your app is doing this (and that's why you want the popup menu) ensure you pass false to the bRevert parameter
You can then get the number of menu items using GetMenuItemCount and for each one call GetMenuItemInfo to get info about each menu item. Pass true to the fByPosition parameter to indicate you're accessing the menus by position (since you know the count, you're getting item 0, 1, 2... count-1).
This fills a MENUITEMINFO structure, which (I think, I haven't ever had to code this so I haven't tested) will tell you the text associated with an item via the dwTypeData field "if the MIIM_STRING flag is set in the fMask member".
If you really want information about the window status, you can get this information using methods like IsIconic to see if it's minimized, GetWindowLong again to get other information, etc. I'd suggest you ask another SO question about how to get whatever specific information about a window for details.
Hope that helps!

Resources