I'm trying to implement the automation test via UIAutomation for our project. But lots of the controls are not standrad, and proper patterns are also not implemented for that controls. How should I to manipulate the controls via UIAutomation framework in this case?
For example, a button in our product is implemented via a Pane, and the invoked pattern is not implemented as well. How should I click the button? (To avoid installing VS on the test machine, I don't want to use Mouse.Click() in Microsoft.VisiualStudio.TestTools.UITesting namespace) Is there a way to do that only using UIAutomation framework or something else embedded in .net framework? Thanks in advance! (If the proper pattern is implemented, Below code will work. And as a new user, I cannot post the screenshot for your reference, sorry!)
object temp = null;
if (btnTest.TryGetCurrentPattern(InvokePattern.Pattern, out temp))
{
InvokePattern btnTestPattern = temp as InvokePattern;
btnTestPattern.Invoke();
}
The only way to interact when Control Patterns are not implemented is to go clicking around stuff.
I would suggest try following to avoid maximum errors.
Before sending the click, make sure the parent of button(pane or window is set to foreground)
Instead of sending the click to corner of the AutomationElement, try sending it in midpoint, of the element,
Also, try hovering over the element first, the wait like 200ms, and then send click, So that you are sure to see execution.[Trust me, this helps debugging a lot and avoids many issues.]
The best thing would be, if those guys who implement the system would implement server-side UIA provider to their UI Elements!
But often that's not possible..., I used the following workaround (at least for clicking/toggling):
AutomationElement yourAE = ...// some code to find the right AutomationElement (AE)
clickablePoint = yourAE.GetClickablePoint();
also BoundingRectangleProperty could be of help
If you receive that clickable point you can use
System.Windows.Forms.Cursor.Position = new System.Drawing.Point((int)clickablePoint.X, (int)clickablePoint.Y);
to move to the location, and than click it via InputSimulator or some win32 (user32.dll) commands.
(note: of course you can also use InputSimulator or win32 to move the mouse - but I had some problems with the InputSimulator when it came to several screens with different locations or resolutions - so Cursor.Position was the easiest approach, which is also very reliable)
Related
At the moment i'm working with Caliburn Micro. But i got to a problem which i don't know how to solve.
The problem is i want to disable Buttons, but every website has only a solution with propertys. the functions of my buttons for example just start a thread to establish a connection over tcp with Netmq. So i don't know how i'll be able to disable them. Searched a lot through google but didn't find anything helpful.
Example of a button function
public void startPubButton()
{
Thread entryThread = new Thread(startPublisher);
entryThread.IsBackground = true;
entryThread.Start();
}
is there maybe a possibility to enable the Buttons only when the thread runs ?
That is the one premise behind CM wiring up by convention all you have to do is provide a CanstartPubButton Boolean property run a code check to see if you can enable or disable button according to the logic with that guard property. Call with NotifyOfPropertyChange(() => CanstartPubButton); in some fashion to do what you want. The logic with in the property (get only needed) is up to you. one other thing I will drop on you is a thread presently in the GitHub discussions on the repository itself. Might help and it might not
https://github.com/Caliburn-Micro/Caliburn.Micro/issues/422
I am working on a real-time language analysis tool that needs to highlight words to draw attention from the writer in Word 2016 using a VSTO add-in, written in .NET4.6.1 with C#. Think of the grammar/spelling check, which adds a squiggly line underneath a word to show you that the word has grammatical or spelling errors. I'm adding a similar feature for some of my own defined rules.
I searched around on adding squiggly lines, and stumbled on Font.Underline and Font.UnderlineColor. I set this on the range of a word, and it appears to provided that visual stumili I was after to draw attention. There is a problem, though. Every underline I add or underline color I change adds an undo action to the undo stack.
I don't want this to happen, or I want a way to pop the action I just did in code from the stack. The aim is to have the user be able to use CTRL+Z to remove text he changed, and not affect my language anlysis result.
How would I go about doing this?
I stumbled on this question, which is asking exactly the same thing:
Prevent actions to be added to the word undo redo OR Remove actions from the undo redo CommandBarComboBox
As #Manu pointed out that same question was also asked over at MSDN where the answer was:
The UndoClear method will empty the list. That's the best you can do.
There is also a similar question on here Word VSTO override CTRL+Z / CTRL+Y
which suggests the Microsoft.Office.Interop.Word.UndoRecord route or MessageHooks in AddIns.
After more research I noticed a great idea at the end of this thread: MSDN Draw my own squigglies on Word document where you keep track of your actions and then skip past them in Undo and Redo operations.
Here is an excellent example of code to do "transactional undo/redo's" Can I create an undo transaction in Word or Excel? (VSTO) . You can do this same method in VSTO except for one big problem, as noted by Dirk Vollmar in his answer:
I don't think that overwriting built-in Word commands is possible using VSTO alone, though
I have overwritten some built-in commands in VSTO using keyboard hooking events to intercept commands: How to perform .Onkey Event in an Excel Add-In created with Visual Studio 2010?
However I'm not sure if you can recreate the Ribbon to intercept button commands. More specifically, the Undo and Redo are built-in galleries in the Ribbon UI and you can do nothing with a built-in Ribbon gallery. And in versions like 2010 the Undo/Redo buttons are in the title bar - and you cannot add/edit buttons on the title bar using VSTO:
So if you're concerned with trapping the button commands (everyone I know uses Ctrl+Z & Y), you might inject VBA code to get access to EditUndo and EditRedo events, eg:
VB._VBComponent vbModule = VBProj.VBE.ActiveVBProject.VBComponents.Add(VB.vbext_ComponentType.vbext_ct_StdModule);
String functionText = "Public Sub EditUndo() \n";
functionText += "MsgBox \"Undo Happened\"\n";
functionText += "End Sub";
vbModule.CodeModule.AddFromString(functionText);
Main problem with this approach is Trust needs to be granted.
Another answer in this same QA
Can I create an undo transaction in Word or Excel? (VSTO) is by Mike Regan who answered 3 months after Dirk. He used a hidden document and placed it in the real document when needed to make any amount of VSTO actions a single undo.
Still doesn't solve the problem of preventing an action being recorded in the Undo History.
I did try a Registry key to limit the UndoHistory to 0 and reset it back to 100 (in order to disable the History while adding an action), but it appears its only for Excel
https://support.microsoft.com/en-gb/kb/211922
There maybe an undocumented reg key to disable the Undo/Redo history altogether but it would only be read by Word on startup. I thought the UndoHistory key containing a number would be read before each Undo/Redo, but no luck with this approach at all.
It's not an easy problem to solve there are big limitations, so it might be easier to:
a) Accept that your spell/grammer checker Add-In is included in the Undo/Redo list (defeat).
b) Work out where the line/text is on screen and show a transparent tooltip highlighting the problem. This is a lot harder than it seems and is less than ideal, here are two great answers to guide you on this method: Detecting text changes in Word 2016 from VSTO add-in or a much simpler approach to detect XY positions from this Microsoft email thread: https://groups.google.com/forum/#!topic/microsoft.public.word.vba.general/pKq4PsqD3cM
//position dialog relative to word insertion point (caret)
int left = 0;
int top = 0;
int width = 0;
int height = 0;
MSWord.Range r = Globals.ThisDocument.Application.Selection.Range;
MSWord.Window w = Globals.ThisDocument.ActiveWindow;
w.GetPoint(out left, out top, out width, out height, r);
frmPopUp newForm = new frmPopUp();
newForm.SetDesktopLocation( left + width + 2, top - newForm.Height + height );
c) Only trap Undo/Redo events by the Keyboard with Transactional Undo/Redo's and let users see the atomic Undo/Redo's using the buttons. It would be extremely dodgy to remove the Undo/Redo buttons and that will cause heaps of Where's my Undo button gone? support cases. So don't do this, if you're curious, quick access toolobar customization can be done from ".qat" files. Ref: https://support.microsoft.com/en-us/kb/926805
d) Use a Mouse Hook and detect when the Undo/Redo buttons are clicked. Here is the code to hook up the mouse, note this wont play nice with corporate Anti-Virus products and I dont recommend it: https://blogs.msdn.microsoft.com/andreww/2009/02/24/message-hooks-in-add-ins/ or https://github.com/gmamaladze/globalmousekeyhook.
e) Try to intercept raw windows messages, eg Excel CustomTaskPane with WebBrowser control - keyboard/focus issues just beware as per my comment referencing BUG: Cant choose dates on a DatePicker that fall outside a floating VSTO Add-In that message pumps in Office sometimes exhibit weird behaviour.
Unfortunately, it doesn't look like there is an easy solution to this problem. From what I've seen, you have two options:
You could clear the entire undo stack using Document.UndoClear. However, this won't be very user friendly, since all previous actions aren't in the undo list anymore.
Work with the UndoRecord class. Between your calls to StartCustomRecord and EndCustomRecord, all actions in your code will only generate one item in the undo stack. CTRL+Z will still affect your language analysis, but the whole undo stack won't be as polluted as before.
I know this isn't what you want, but even Microsoft MVPs don't have a better solution.
I'm building a "WPF Application" which is made to be run in the background (minimised state) and detects KeyStrokes of each and Every key on the keyboard & every Mouse Clicks.
So, my question is how to detect every keyStrokes whether app (Window) is minimised or not.
Simply, if my app is in focus then i use this code to count keystrokes.
Public int count;
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
{
//base.OnKeyDown(e);
count++;
tBlockCount.Text = count.ToString();
}
I just want to do the same even if my app is minimised.
I've searched a lot and come across many suggestions like..
http://www.pinvoke.net/default.aspx/user32/registerhotkey.html
http://social.msdn.microsoft.com/Forums/vstudio/en-US/87d66b1c-330c-42fe-8a40-81f82012575c/background-hotkeys-wpf?forum=wpf
Detecting input keystroke during WPF processing
Detect if any key is pressed in C# (not A, B, but any)
Most of those are indicating towards Registering HotKeys. But I'm unable to match scenario with mine.
Any kind of suggestion are most welcome.
Although I'm not really condoning the use of a keylogger (This is what you are trying to do). I would recommend taking a look at this q/a, the section near the bottom of this article, and this article for some inspiration. These should help point in the right direction for the coding side.
What you essentially need to do is just set up an event to intercept any keys that come in from the computer, then you can gather the key and do whatever you like with it (in your case, record it)
Edit: In fact, reading the third article, it actually gives a full code snippet on how to implement and use it in WPF, so I recommend just reading that one.
I am using the Business Silverlight application. I have incorporated some MVVM into this and were off an running with it. We are using some telerik controls, mostly the ribbon control and the docking. We register all the telerik ribbon controls in the about.xaml.cs file, the method is DisplayUI - its here where we register the docking control then we register the ribbon after this. What happens is that when you click the ABOUT link it shows our first tab with buttons(perfect). when you click the HOME link next to the ABOUT link, we go back to the home page..but when you click the ABOUT link again it registers the controls again so we end up with two tabs that are the same.
Is there a way to check to see if this about.xaml.cs file has already been initialized? Im guessing that is has a handle on the first call in memory as I am able to see the first tabs rendering..
Thanks
here is the about code
public About()
{
InitializeComponent();
DisplayUI();
this.Title = ApplicationStrings.AboutPageTitle;
}
that display UI does all the work in registering the dockpanel and the ribbons. We'd like to not have the DisplayUI() called if this has already been rendered once.
If you do it by event handler can you unsubscribe from the event at the end of the method? Without seeing some code it's hard to work out what to change.
It's not the nicest way of doing it, but if this code needs to run once and only once then you could have a static boolean variable on the class set to false and when you call DisplayUI you check the value of this. If it's false you set it to true and run the method, and if it's true you just return.
I have subclassed a Treeview and on instantiation it loads a new ImageList (and the associated Images).
Whenever I switch to the designer view, it's also trying to run this code, however the images aren't in the designer's path, so it crashes. I ended up putting in a hack to see if the current directory is "Visual Studio", then do nothing... but that's so ugly.
I find this happening for other things. If a control is trying to use objects during load/initalization that are only available while the program is running, then the Design View cannot bring up the control.
But is there a way to get around this?
I guess what I'm hoping for is having a try/catch for the Designer (only) with the ability to ignore a few errors I know will be happening (like FileNotFoundException, etc.).
Thanks
Everything that inherits from System.Windows.Forms.Control has a DesignMode property that returns a boolean indicating if you are in design mode or not. You could use this to determine when to/when not to load external resources.
Usually it is better to move the loading of these resources to an override of OnLoad as they are rarely required directly at construction. This fixes the issue you are seeing and means that only trees which get displayed at least once will perform these additional resource loading steps.
Otherwise, you can just exclude these steps during design time by checking the DesignMode property and acting accordingly.
This is a fine pattern to use if you're making a control library with a sample of images when shown in the designer or hook ins to other designer features but as a pattern for development I'm not sure it's very effective.
I would suggest shifting your "business logic" (in this case your loading of certain images into a treeview) outside of the bounds of your treeview control. In your case I would place the logic within the Load event of the form that the control is inside:
public void Load(object sender, EventArgs e)
{
string path = "c:\somePath\toAwesome\Images";
myFunkyTreeView.AddImages(path);
}
For larger apps I personally think you want to shift the logic even out of the forms themselves, but this is debatable measure as it requires additional plumbing as a trade-off for the flexibility this provides.
Thanks for pointing me in the right directioon guys.
I had tried registering to the OnLoad event, but that event is triggered when the Design View comes up, so that didn't quite work for me (am I doing something wrong?).
Anyway, I looked a bit more into the DesignMode property. It can only work for Controls, and sometimes your object may not even be a control.
So here's the answer I prefer:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) {
// design-time stuff
} else {
// run-time stuff
}
Found it here.