I'm trying to make an application that will test some features of an existing app and I wanted it not to be window-size dependent and not to require focusing the window or etc.
I've already figured out how to get window handles for different controls in the tested app so I can click buttons, enter text to textboxes etc. with Send/Post Message but still got a few unsolved problems.
The first is selecting an item from a pop-up menu that can be triggered by button click (TAdvGlowMenuButton class) or right click somewhere- I can't even see any messages related to it in Spy++ so I have no idea how to do it, is it possible to select an item by name? as I don't have it's id
The second thing is clicking next to something, for example 10 pixels to the right of a button.
I have the button handle so I can get it's size and it's parent but I still don't know how to get it's position inside the parent - any ideas?:)
And also a quick one but I don't believe it is possible - can I somehow get position of a label in the tested app? I can't even see it in Spy++ .
I hope you can help me to find it out ;)
Edit: I forgot about the most important thing:P , I'd like to achieve it with Send/Post Message if only it is possible.
My recommendation would be to abandon the message sending/posting model altogether and instead use UI Automation. Automated testing tools is exactly what the UI Automation APIs were designed for, and they are much more capable than SendMessage/PostMessage.
Yes, I realize that this is exactly the opposite of the answer you were looking for. But you will have no end of trouble getting messages to do what you want. A fair number of them rely on the application having the focus, and it is completely reasonable for your code to make this assumption when you receive e.g. a WM_KEYDOWN message. A testing tool should not flag that as a bug.
I notice you've tagged this question with the C# and .NET tags. In that case, you may be interested to learn that the UI Automation APIs have been wrapped in the .NET Framework.
Related
I am currently working on a Windows Presentation Foundation app and I need to make use of Message boxes. I want to get few information from user inside Message Box popup.
But they appear always like this:
But I think the actual look of it should be like that:
Does anybody know, why this is, and how to solve it? I tried all everything listed
here
, but nothing worked.
I agree with Keithernet, build your own. Its more of an Input Dialog box. You may want to plan it to create a window, create it with ex: 4 parameters which you could override so you can apply them in the form including
The title,
The prompt you want the user to fill in
optional default button 1 text
optional default button 2 text.
have the input value stored into a public property in the window for the text to be bound to during entry.
If the user clicks the cancel button (or similar), clear the text entry and close the window. If ok button, just close the window.
Then, when you call it with a YourWindow.ShowDialog(), upon return, you can look at the public property for that input text value.
You could even do with a property / flag if the user cancelled directly or not. I have done similar in a couple of my WPF apps.
MessageBox is very limited. Based on your screenshot, you should just create your own child Window with your own XAML so you can get the user input.
You can find sample service implementations/NuGets for this on GitHub. Here is one I've created sometime ago: https://github.com/Dirkster99/MsgBox
Just create your own is an oversimplifying statement in my opinion because this is usually a dialog that you want to show in different parts of the application. Therefore, you have to settle for a software design pattern (I chose a service implementation as suggested here).
Likewise, there are other design decisions that should be taken. I have for instance made sure that the API has a compatible subset of Show API calls with the standard .Net MessageBox to make its application as flexible as possible. I also settled for light and dark themes hoping this will make its application easy in any other theme...
Does anyone know how to collect the recently clicked 5 buttons, and save them to a new group in the Hometab for reusing? Using C# in VSTO.
It seems a simple thing, however, I find now way to dynamicly monitor the control event in the ribbon and get the ID.
Have searched for several weeks.
Thanks a lot if anyone can help.
Hmm I don't think it's possible or at least I don't know about any way how to do that.
First there is no way how to easily monitor which button was pressed by any API Microsoft provides. You know, there is no command there is called for every button where you can hook your code and listen. I know that out there are amazing tools that can help you with things I originally thought are impossible RubberDuck, Watch Dog, MZ Tools but first, they are mainly for VBA, second it's probably not easy solution that you are looking for.
You would probably have to - somehow - mimic Office ribbon by your own ribbon => way too much work, use one callback, monitor it and determine the last 5 buttons.
Then you would have to change the Home tab by changing the ribbon XML which has two drawbacks
1, I believe it's not possible adding/removing buttons dynamically (you can use callback to change visibility but for adding/removing there is probably nothing)
2, you would have to restart the Office application to see your changes
As you see I'm not entirely sure it's impossible but I do see it as way too much work.
Anyway I'd love to hear if there is a way how to do that, so please if you find any way do let me know. Thanks
I have whipped up a C# clipboard application that stores multiple 'clippings' for later use. I use low-level keyboard hooks to pop open my application's window(s) on command. When the window is closed (or a clipping is double-clicked), it is supposed to paste the selected clipping into the last active window (the window prior to my application's window). I use low-level WINAPI methods to determine the last active application, snag its handle, and then return focus to it before simulating a Ctrl+V keystroke to paste.
This typically works except in one very unique scenario: I am in a WPF application project, Quick Finding in a XAML file, the cursor automatically switches to the body text, not the Quick Find textbox, and pastes it there. It seems to have something to do with the loss of focus/activation, as it moves the cursor whenever I activate another window, regardless of my own application's running.
VB files, C# files, what have you, and XAML opened in WinForm projects do not steal the Quick Find focus when switching between the VS2013 application and my own; upon returning to the last active application, the text pastes into the Quick Find box.
Only the XAML in WPF application projects gives me this problem.
So far. I know it is a fringe case, but I expect to run into more. This program is meant to be used in a coding environment and it's pretty important that it be able to handle these kinds of scenarios.
I've tried getting the internal control handle using code from http://www.codeproject.com/Articles/34752/Control-in-Focus-in-Other-Processes, so that I can return the focus to it, but it seems that the handle for the body text and the handle for the Quick Find text box are the same.
A partial solution is found in: How do I prevent the original form from losing focus when I show another form? The popup window I use is navigated primarily through my low-level shortcuts, and therefore has no need of explicit activation.
Using the mouse on it or any of my other windows (as I expect my users will sometime), will cause it to gain activation and circumvent this fix. However, it's such a fringe case it doesn't seem to matter. Hopefully this helps anyone in a similar situation (if not necessarily specifically this one).
What am I doing?
I am automating a 3rd party application. The login window looks like this
Note: there is a background image embed within the form and both the USERNAME and PASSWORD are actually part of an image. Just in case anyone wonders why the below classes treeview from Window Detective doesn't have, possibly ยป Label controls.
Where am I at?
I don't have any problems getting handles of components. I mean, I can generally access each window/control using FindWindowEx function.
I can implement a GetWindowTextLength and/or GetWindowText functions for buttons to distinguish which one I have got a handle of. While this approach works fine with Buttons (.Caption) it would not benefit me when working with Edit controls. It seems that the Edit controls do not have any unique properties to distinguish which one is which. (correct me if I am wrong)...
The problem
Assume that I need to know at the compile stage which Edit control I am going to be handling, so I don't send a password to the username and other way around. There are only two but like I've said I'm not sure how to get the right one.
I wouldn't mind figuring it out at run-time but I am unsure of how to distinguish the difference without sending a message and actually visually identify which one is which...
Current solution
I wouldn't really call this a solution but for now I am relying only on the fact that each time I run my code I always get a handle of the second (password) Edit control as the first handle returned.
Question
Can I be 100% sure the second Edit control will always be returned first in the hierarchy returned by the FindWindowEx function?
If someone can confirm my idea than I'd already have had a solution BUT if I can't always expect the second Edit control to be returned then I would like to hear some insight on how to handle this situation.
Note: I didn't think any code is actually required for my question but if anyone would like to see the code then please leave a comment and I will add it to the question.
Thanks a lot for your time.
Each child HWND has a property called ID. Use GetWindowLongPtr( hWnd, GWLP_ID ) to get it. Depending on how the target application is coded, that ID may be a way to distinguish between child control. Knowing the ID you can get the child HWND with the GetDlgItem API (works fine when the parent is not a DialogBox, the API should have been called GetChildByID).
Beware: some target applications really use random/unreliable values for IDs.
It seems that there is a general consensus: Enumeration APIs rely on the Z-Order. See for example that SO answer (maybe making your question some sort of 'duplicate')
While some applications may "play" with the Z-Order of their child windows, in the standard case they won't, which means that the first created child window is at the top of the Z-order, and the last created one is at the bottom.
I tried writing code several different times, but I came to an error with each one.
Basically, I'm trying to make "windows" similar to say Explorer, Paint, MediaPlayer, where you could drag then around, interact with them, minimize and close. Of course, if you clicked on a window, the one below it (they can overlap) shouldn't get affected.
I know how to do this, I have a list of the class I call Window, loop through it, and I only interact with the first window to contain the location of the mouse-click. This way, other windows overlap won't get affected.[1]
Next, I had to make it so that two buttons that are overlapping don't get activated when the user clicks in the "intersection of both buttons." I handled this by using the same method I used above.[2]
But the problem I'm facing now is that, if I hold the left click, but then I decide not to click a button, I drag the mouse away from the button, and release the left click, so that the button-click event won't be activated. But, when I remove the mouse from the boundaries of the button, and say, into another.. the new button get activated. Which it should not.[3]
My set up is like this:
I have a class called Window.
In Window, I have a list of the class called Interface (similar to the Control class in WinForms).
And each Interface has a struct in it that contains 4 bools, if the left/right is currently down, and if they were down in the previous processing. (prevLeft, prevRight, currLeft, currRight)
So, I'm ready to discard that (I have not yet, so I still have the source code), but I need a good structure for making an object-oriented type of application. However, I am not using WinForms. I need help with the structure alone, so no actual code is necessary, description is enough. I need to avoid the 3 problems I mentioned above.
Creating your own Window Manager is not an easy task. I know it because I'm making one too ;)
You can use an existing, though maybe not the best solution, like for example Nuclex.UI, which I personally rejected when I first saw it, but if you're not dead set on making your own WM, I suggest to use that or hybrid WinForms-XNA approach.
But if you're really dead set on implementing a custom Window Manager, you have to understand how any other WM works. Since we're talking about XNA, it means Windows, and that means Windows Explorer, which is a great thing to learn from.
You have to recognize how the simplest things work, and it's really not so hard. The hard part is figuring out what logic is updated when, and how to not spend all the CPU on only UI updates. Let me just give you a few hints on how to solve the problems you mention in your question.
To keep track of all windows, I'm using a Dictionary<string, Window>, where Window is a custom class, and the string is its unique name for rare cases where I have to call windows by name. Think of it as a window GUID or Handle. But you can just make it so that a "Form" can only appear once, and store all references in static variables.
To make WM understand what control you're clicking I use rectangles and check if they contain a Point which is at Cursor coordinates and has {1; 1} pixel size, which is probably about the same way it's done in Windows Explorer. To do that your WM needs to know in which order to update the active windows. Usually you'd want to start from the topmost window and continue towards the end of the list of active windows. For that you can just iterate through the list with a foreach loop.
But that's not all, because every window itself is a Container, which means it contains other controls, some of which may even be Containers themselves, like WinForms Panel class. This means you have to iterate through each of the Windows' Children controls. The update order should make sense too - update from the topmost child to the bottommost, recursively for Container controls, in case they also have Containers in them. This basically means you'd want to implement a recursive GetAllControls() method for your WindowManager class that would iterate through all Containers and return a list of all Controls.
Drawing all those Controls should be done in reverse order of updating them, so you can just GetAllControls().Reverse() and iterate through that in a foreach loop.
Where to draw and what to update depends on all the parent containers the current container has and their combined offset from the top-left corner of the game window. I solve this by storing a ParentContainer reference in all children controls to get the appropriate DrawRectangles and update areas via recursive properties.
When you click somewhere on the screen and a click is registered on a Control, make the WindowManager remember that (bool clickRegistered) and not run any OnClick events on any underlying Controls.
Windows Explorer remembers the control you clicked and will activate its OnRelease event if the cursor is then released in the update area of the very same control. So basically Windows Manager only does something when you release the mouse button. You can make your WindowManager and Controls to handle click events differently, like firing an event right after you press the mouse button, i.e. OnMouseDown. But remember that Microsoft aren't noobs and there's a reason for that behavior in Windows Explorer, and it's because if you accidentally press a mouse button somewhere you didn't intend, you can still fix it by moving the cursor outside the pressed control's update area and not run its action.
At this point you might be thinking "Is it really worth implementing all this?" For me the answer was "maybe", because I was a total noob in both C# and XNA at the time I started, and now I know my game, which was originally supposed to use some Window Manager, is going to benefit from my own WM implementation far more than from ready third-party solutions. And besides, it's a great exercise in logic and programming.
But if you'd like to think of yourself as a game developer, you should think in terms of reaching your goal as quickly as possible, i.e. actually making a game, and not the game engine. So in this case, better make use of existing solutions and start selling your product.
Instead of having the structure with the 4 booleans (similar to xna), how about you make a way to tell where the mouse "is." So in a sense, the mouse is in Window number 5 which is Paint, and the user is holding the mouse down on interface/control number 2 which is a button.
That sounds like it could work.