Off screen element teststack white - c#

I need to automate 3rd party WPF application. I use
TestStack/White. This application has menu bar that is presented by images. After some actions menu is changing. There presents new images. When I want to click on new image:
Window mainWindow = application.GetWindow("Main window", InitializeOption.NoCache);
Image newTask = mainWindow.Get<Image>(SearchCriteria.ByControlType(ControlType.Image).AndIndex(2));
newTask.Click();
I get exception:
TestStack.White.AutomationException: Cannot perform action on Image.
AutomationId:, Name:, ControlType:image, FrameworkId:WPF, element is
offscreen.
I use Microsoft Inspect for research elements.
When I start tests, Inspect show me that image is offscreen. But if I do these actions manually, it works perfectly and in Inspect this image is not offscreen.
How can I refresh these elements or clear cache of window?

There are ReInitialize and ReloadIfCached methods on Window object. Try those to see if something changes.
Are you sure AndIndex(2) is correct element in that particular situation?
Try using GetMultiple and iterate the collection to see what images you actually have and which are not Offscreen.
WPF automation with White is pretty hard. Try Telerik Testing Framework and White could be supporting framework. It is much more easier that way.

It can be a problem with focus, try to use this before getting image:
mainWindow.Focus(DisplayState.Maximized);

Not an exact answer but the final solution I've got after all these TestStack.White not found elements, table rows, and so on. I started to move it to FlaUI. If something does not work or unstable with White then most likely I can get more stable and fast-executable FlaUI solution.
Fortunatly, such migration can be done with little steps. For example I already have TestStack.White.Application app, then I replace White portion of code with FlaUI like this:
var flApp = FlaUI.Core.Application.Attach(app.Process.Id);
using (var automation = new UIA3Automation())
{
// .. new UI element processing
}

I don’t think that caching is the problem here. You are getting the mainWindow with InitializeOption.NoCache. In Non-cache mode the controls are found on demand. So I presume that the cache is refreshed automatically. (https://github.com/TestStack/White/blob/master/src/TestStack.White/Factory/InitializeOption.cs)
Perhaps the index of the element you want to click is not 2.
Have you tried adding an explicit wait? It sounds like you have only tried adding an implicit wait.(https://github.com/TestStack/TestStack.docs/blob/master/_source/White/Advanced%20Topics/Waiting.md)

Related

Programmatically select DrawingObject in HWindowControlWPF

I'd like to select a created DrawingObject to highlight it and show the handles without the user needing to click it. I am using Halcon 13 and tried using SendMouseDoubleClickEvent() (Docu) but this only seems to be available for the new Halcon Smart Window, which is currently not an option for me as it interacts differently with the Halcon-Procedures. I also tried to use SelectObj() (Docu) but this seems to do something entirely different.
I have:
a reference to the HWindowControlWPF
the ID of the HWindowControlWPF
the ID of the DrawingObject
Any help or hint is appreciated!
I could not find a proper solution to this problem but I found a hack that achieves the same result:
First, detach all drawing objects apart from the one you want to show as selected via DetachDrawingObjectFromWindow. Then, reattach them via AtachDrawingObjectFromWindow.
This works because the Halcon Window automatically selects the last attached drawing object.

Click WPF button from another application

Was thinking it would be an easy task, but it proved to be far from that.
Spy++ doesn't generate control ID's (Only shows main window), each control has a name. Example(Button->"AddButton")
I've tried using invoked methods such as SendMessage, and i get the main window handle just fine, but always get a 0 when trying to get control handles.
I heard about UI Automation library, but didn't find any clear examples of usage for my specific task.
My Goal:Being able to retrieve data (Such as data grid cells texts), and click buttons on a WPF application, remotely from another application (I'll be using C#)
Thanks in advance!
EDIT: I've tried Ranorex Spy and was able to click the control just fine:
Press button from Ranorex
How can i simulate it?
EDIT 2:
I managed to do it after further reading some documentations, hopefully it will help other people:
string mainTitle = "";
string controlName = "";
AutomationElement prog = AutomationElement.RootElement.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.NameProperty, mainTitle));
AutomationElement btn = prog.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.AutomationIdProperty, controlName));
InvokePattern clickBtn = (InvokePattern) btn.GetCurrentPattern(InvokePattern.Pattern);
clickBtn.Invoke();
You can indeed use UI Automation which was (kinda) designed to do this kind of stuff. There is also a NuGet-Package which does some work for you already, called TestStack.White. Originally it is designed for automated UI testing, but I don't see why you couldn't use it for doing stuff like that. You can find out more about the Package here, and more about UI Automation here.

C# - Get index of Internet Explorer tabs

I'm googling and trying to solve this problem already one whole day, so I think it's right time to ask.
In my C# code, I'm trying to get hwnds of IE tabs in the same order as they are displayed in the browser.
Important note: I cannot do it with URL or Title since browser can contain two tabs with same page opened.
For that I tried different approaches:
I used Interop.SHDocVw library, where I'm trying to get all IE
windows and get their tab hwnd. This approach is working fine, but
tabs are ordered by date of creation. So if I open 4 tabs in IE it
returns me the right order, but when I move one tab to first
position, it's still shown as 4th in this approach.
List<int> hwnds = new List<int>();
ShellWindows shellWindows = new ShellWindows();
var explorer = shellWindows.Cast<InternetExplorer>()
.ToList()
.Where(item => item.Document is IHTMLDocument2);
foreach (var internetExplorer in explorer) {
hwnds.Add((internetExplorer.Document as IOleWindow).GetWindow());
}
return windows;
Other way was to implement Win32 windows searching, where I'm
filtering the windows by it's classname. This returns the order like
in Spy++ software. From my look it looks like it's sorted by last
interaction. First one is tab with which I interacted like the last,
second - previous last, etc.
Another thing that I tried was to implement IEAccessible way of getting
tabs, but that didn't work for me at all.
https://social.msdn.microsoft.com/Forums/ie/en-US/03a8c835-e9e4-405b-8345-6c3d36bc8941/ie7-ie8-tab-interaction-accessibility-class?forum=ieextensiondevelopment
Last thing that I tried is to use UI Automation, but with WinSDK
Inspect tool I could see that only hwnd of current opened tab is
visible. Otherwise I can see only button with titles without hwnds.
I would be really thankful if someone could help me with this problem - since I cannot see any other solution.
You should be able to get tabs in a proper order through UI Automation. Running Inspect.exe tool I am able to see them correctly under a lot of pane controls:

What is a good strategy for printing the contents of two panels of a windows form?

I have written a C# 4.0 Windows Forms Application that creates two panels which are both populated exclusively with text labels. I would like to add functionality to my application to print these panels exactly as they appear on the form, but I only want to print these panels and their contents, with no background or other parts of the form.
This link was especially helpful as an overview, but so far I'm only able to print what amounts to a screen capture of the form. The entire form is included, buttons, trim, background, and all. It looks like I need to "rebuild" the form by creating a graphics object (I use the term generically, as I'm not sure what specific graphics-related class I need to employ) and somehow transfer the contents of the panel into this object.
My question is: what classes and/or methods should I research in order to build this graphical object? Also helpful to know: are there any handy tricks within the .NET framework or any libraries out there to automatically fit the result to a single page when building the PrintDocument object?
OK, I found one way to do it (love to my Perl bros out there):
Wrap both panels in another parent Panel. Let's call this Panel "parentPanel." Create a bitmap (memoryBitmap)that is the size of parentPanel (parentPanel.Size).
Next: parentPanel.DrawToBitmap(memoryBitmap, new Rectangle(parentPanel.Location, parentPanel.Size)
Then, in the print page event handler: e.Graphics.DrawImage(memoryBitmap, 0, 0)
I'll leave this open in the likely event that someone else has a better idea.

how do I make my application as fast as windows explorer for rendering files

I have a folder with a large amount of files inside of it. I want to be able to render each of my files as a button. And when I click on the button something will happen.
private void Form1_Load(object sender, EventArgs e)
{
int x = 10;
int y = 10;
/// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(#"c:\lotsofDocs");
foreach (string fileName in fileEntries)
{
// do something with fileName
Button newbotton = new Button();
newbotton.AutoSize = true;
newbotton.Text = fileName;
panel1.Controls.Add(newbotton);
newbotton.Location = new Point(x, y);
x += 150;
if (x == 760)
{
y += 50;
x = 10;
}
}
As you can see there's nothing crazy in the code. I have a panel on a form and I've set auto scroll on the panel to true and auto size to false. This causes the form to maintain size and the buttons (some of them anyway) to get rendered off the form and I can scroll down to them.
All good so far.
If I have 100 or 200 file everything is ok, if I have 1932 files it takes about 10 seconds to render all the buttons.
I've read the follow question Super slow C# custom control and I understand that the approach I'm using might not be the best to use here.
And now the question at last:
how does windows explorer handle this? If I open this folder in Windows explorer it opens instantly.
What type of control is windows explorer using? Or is it doing it in a completly different way to me.
Thanks
Very long lists of controls are usually implemented via virtualised controls. That means that if only 20 buttons fit on the screen it only creates 20 buttons or so. When you scroll around it reuses the same 20 buttons with new data in them.
Controls can be very slow to create and manage in large numbers as they are usually added to a simple list or hierarchy (and are quite complex individually).
Better off managing a smaller set of buttons yourself to show a very long list of data. More work obviously, but the end result is lightning fast compared to the "simple way".
If you don't want to DIY, try a third party control. As an example the Telerik virtualised Tree, List and Grid controls can display a million records with no slowdown. Take a look at their Winforms grid here
You should look at the ListView. It provides the same basic set of functionality as the file area in Windows Explorer with comparable performance.
Make sure to call BeginUpdate before adding your items and EndUpdate when you are done for the best performance. Adding your items with Items.AddRange is also good for performance.
Can you allocate all the buttons at once? What I mean is, create an array of buttons after you read the file names (so you know how many buttons to create), then simply set their properties in the loop. I don't know how much that will speed things up, but it's worth a try. You might also see if there's an override on the panel's Add method that takes an array or list of controls and add them all at once, too.
One trick that often helps improving slow contruction / change operations is to hide the controls and / or the parent container involved. In your case, that would mean hiding panel1 before creating the controls, and showing it again afterwards. Might not help a bit in your case, but it's worth a try.
However, you will have fundamental problems creating so many controls in Win32 or WinForms. While the Window System now can handle these, it's not the thing tries to be good at.
It is also not the best user interface for that. 2000 Buttons in a 5 x 400 matrix? Holy effin' cow. I don't want to use that. What do you do if a file name does not fit 150 pixels? What do you do on displays where "150" means ".15 mm"?
Alternatives
Why not a list control? That at least has page up / page down, and type ahead to find items starting with the text I enter. Throw in a "quick filter" edit control on top of it, where where entering some text filters out any files that don't contain it, and you have a standard interface that can be used efficiently. If you expect many items, you can put the LitView control into virtual mode. While this loses some built-in features (e.g. autosizing columns), it works with insane numbers of items thrown at it.
You could also render the buttons as HTML links, and show it inside a browser control. That's not necessarily faster, but HTML renders progressively, I can use the list while you are still feeding items.

Categories

Resources