Retrieve toolstripbutton using UIAutomation - c#

Using UIAutomation on windows Forms, I'm trying to retrieve any control under mouse on a specific form.
The goal is to work on controls of an app, retrieving and acting on them.
The problem I'm facing since so many times is that I can't find a toolstripbutton.
Everytime I'm getting a pane (not parent nor child of the toolstripbutton I want, but parent's sibling).
This is the toolstripbutton I want to retrieve : .
The same control but in Inspect.exe (highlighted: the control I'm getting) :
I though that it was because of z order of the controls, then I tried using sibling controls, for controls where their bounds contains the mouse (for getting all controls under the cursor anyway their z order).
That fails because the toolstripbutton isn't retrieved.
I currently use UIAutomation and not CodedUI, because I need to run a custom program which retrieve controls and executes automatic tests on a specific server, but I actually have the Visual Studio Enterprise 2017 licence installed on my machine, but a second licence (for the server) and a third licence for a colleague for work with me on it would be a bit expensive.
Remembering that the programs have to retrieve dynamically the controls under the mouse, may someone gives me any idea which can help me to investigate deeper ?
Thanks & Greetings
Method used:
var aimed = AutomationElement.FromPoint(new System.Windows.Point(Cursor.Position.X, Cursor.Position.Y));

Solved by work around.
I made a recursive method that search deeper in the children for controls which contains the mouse (BoundingRectangle.Contains` method).
In that way, I can find the controls within the toolstrip.
But AutomationElement.FromPoint method doesn't search inside the toolstrip.

Related

How to programmatically add buttons to a window after Instantiation à la Revit API's TaskDialog class

I apologize if the question isn't as accurate to what I want, but I'm fairly new to coding any type of window/form without a visual element or robust IDE (currently don't have access to Visual Studio, but want to begin work on a GUI while I wait as I have a bulk of the driving code done). I've had a difficult time finding out if/how this is possible due to the wording of my queries so far being too similar to other topics, like enabling/disabling buttons.
What I want is to emulate the programmatic functionality of adding buttons to a window present in the Revit API TaskDialog class. For those unfamiliar, this is a sample of how one creates a TaskDialog with a basic message and two buttons in C#:
TaskDialog dialog = new TaskDialog("Sample");
dialog.MainContent = "This is an example of how a TaskDialog is coded in the Revit API";
dialog.CommonButtons = TaskDialogCommonButtons.OK | TaskDialogCommonButtons.Close;
dialog.DefaultButton = TaskDialogResult.Close; // optional, will default to first button in box if unassigned
TaskDialogResult response = test.Show();
This type of framework would then be used on a window/form/user control that's used by multiple different modules, each with slightly different UI needs. Most modules will need a list box and Confirm/OK and Cancel buttons as a basis, but some will need additional buttons for additional functionality within the window.
If this functionality is better done in WinForms, I'm open to moving my GUI to that platform, I have interacted with both in the past and am somewhat familiar with the flow of each, just not the more advanced topics yet. This said, the data binding is an important feature for me, so wpf is preferred.
Any input would be greatly appreciated!
Edit
So, after some more digging around, I think I have a better understanding of how to ask my question:
What I want is the ability to programmatically add buttons (not RadioButtons like in this solution) to a window (wpf or winforms) by setting a variable in using the constructed window instance in the main code, passing it values from an enum with [Flags]. I want to have defined, common buttons (e.g. OK, Cancel, Close, etc) whose information and enum for adding to my window are in a module. I can then access these buttons through their enum, as Revit API allows with the TaskDialogCommonButtons enum, and assign them to a property of the window (in my example that would be the TaskDialog.CommonButtons property). This would then tell the window to show these buttons and none of the other buttons contained within the enum.
Unfortunately, the only results I get are how to data bind RadioButtons (not regular Buttons) that are then explicitly created within, or hard coded into, the xaml or codebehind of a window class and not dynamically added after the custom window class has been instantiated from the main code. This is clearly possible, otherwise the Revit API would not work in the way it does, but I can't seem to find anything relating to how or why it works and how to duplicate it.
Is simply a matter of including all of these buttons as hidden in the window class and using the enum to set the window instance's button visibility to show/true, thereby granting UI access? Or is it actually possible to add buttons programmatically from the driving code (not the codebehind of the window) using an enum?

UIA Verify shows no name property for buttons

I need to automate a workflow and tried to rely on teststack white and UIA Verify to find the buttons in another application.
However when I try to identify the buttons I was greeted with just empty name properties for the controls inside the window I need to control (see attached screenshot).
The controls are apparently of type Custom.
I want to be able to press buttons and enter text into textboxes as well as check a checkbox.
Is there a way? Can I access them via for example an index (e.g. button = third control in window)?
Edit: As requested a screenshot from inspect.exe
Would you mind taking a look at those controls with Inspect.exe and posting a screen shot of the properites? You might be able to find another unique property on them to identify it with. Inspect.exe can be found C:\Program Files (x86)\Windows Kits\8.1\bin\x64\inspect.exe.
With White you wont be able to get a collection of all the buttons but with raw ui-automation you will be able to get a collection of the AutomationElements using FindAll.
Here is an example of how to get all controls of a certain type.
Retrieve Multiple UIItems ByClassName
Edit:
So after looking at the updated image from inspect I am afraid the application you are trying to automate didn't expose their application to ui-automation properly. I was certain that it wasn't exposed properly before but I was hoping they may have accidentally exposed some properties. I have seen this before with some 3rd party controls for VB6. It would be possible using the technique I linked above to get all the controls with a name of "" but then you would have to use the bounding rectangle property to move your mouse to the correct position and click (if that property is reporting the correct position) since I would wagger the invoke pattern is not supported. If you have access to the source code you could implement these properties and pattern.

Spy++/UISpy, objects on windows form only exist when they are active

I am working on a C# .NET application in VS2008 to automate filling out a form on another 3rd party application (no access to source). My application uses the UIAutomationClient class to do things like focus on or select elements on the form. The problem I am running into is that some of the objects that I need to work with are only visible when they have focus. For example I can only select an item from a list if the current active element is the list. My work around for this has been to send "tab" until the element I am looking for exists (sometimes there are hundreds of elements on the forms). Technically it works... But there has to be a more elegant way to make the elements visible.
Similarly, I am using the UISpy, Inspector and Spy++(32 or 64) to help identify the objects, and again they can only identify some elements when they are active. Once they lose focus they no longer show up in the tree. I assume this is because these applications most likely were developed using the same HWND search methods.
My question is, can UIAutomation identify these non-active objects? Is there a hook or alternative class that can expose them and pragmatically identify them?
Thanks,

WPF UI Automation - Control Tree not poluated till region is clicked for a TabControl

I am doing a UI automation for a WPF application using the Microsoft UI Automation library and it works well.
However my app has four screens in a TabControl. Even when I click the tab item through code its child control tree isnt populated. The only control I can see is the "thumb" Control. Same happens when I see the control tree with UISpy.
However if the window is clicked then all the controls appear. As a Workaround I am simulating a mouseclick through code and it works. I wanted to know if there is some better way of doing it.
I ran into a problem similar to this. What was happening was some data was being retrieved on threads and the controls were not generated at the point automation peers were generated. I would suggest if you have access to the code base for the application you are attempting to automate looking into whether threading is being used. In my specific case it was because BeginInvokes were used to retrieve the data, I switched them to Invokes and it worked fine.
Also from what I could tell the reason the controls were being show on mouse over was because the tool tip generated a popup and caused the automation peers to be updated.
Why don't you click the control using mouse events if that is what works.
(Now, if you still are having that problem..)
How to simulate Mouse Click in C#?

How can I create a button with an embedded close button

I am trying to create a panel which will have a set of "buttons" on it.
These buttons should have the following behaviour:
Appear similar to a tag (with
rounded edges)
Contain a red
cross to remove the filter/tag from
the panel, similar to the way internet
explorer tabs have an embedded cross to close the individual tab.
allow the user to click
on the tag and respond like a normal
button (as long as the click is not
in the red cross)
Number 1 is no problem, this is just appearance, however, regarding numbers 2 and 3, I am not sure if there is already code out there do to something similar...and I dont really want to reinvent the wheel if I can avoid it!
My question is: Does anyone know if there is something out there in infragistics which will do this simply, or will I need to write this myself by subclassing winform buttons?
Thanks in advance!
Is this new development or maintenance of an existing project?
If it is maintenance, you have a somewhat tougher time ahead. You'll implement a UserControl, probably segmented into two buttons. Use docking to get the behavior as correct as possible. The far right button would contain your cross image; the left (which would need to auto-expand as you resize the control) would contain your primary button behavior. Play with the visual styles until you get them right (EG, removing borders, etc).
If this is new development, and you haven't gotten too far into it, you might consider using Windows Presentation Framework (WPF) instead of WinForms. It will be easier to build the control and get it to look exactly how you want it. WPF includes an extremely powerful control compositing system which allows you to layer multiple controls on top of each other and have them work exactly as you'd expect, and it carries the added advantage of allowing full visual control out-of-the-box.
Either way, this is more work than dropping in an external component ... I've used Infragistics for years, and I can't think of anything they have which is comparable. The closest, but only if you're building an MDI application and these controls are for window navigation, is the Tabbed MDI window management tools -- and there, only the tabs (which replace window title bars) have this behavior.
I don't think that infragistics can do something like this. The UltraButton control can't.
Implementing a own control wouldn't be that hard.
your probably going to have to make a costume control for this type of work.

Categories