MoveToElement when element is just onscreen - c#

When using this code to bring an element into the browser view, it works most of the time.
protected void MakeVisible(IWebElement link, bool always)
{
var actions = new Actions(this.Driver);
actions.MoveToElement(link).Perform();
...
However, when the element is just (say a button that is 50% there) on screen, it doesn't, but it isn't onscreen enough to register for a click event.
(The bottom of the snip is the bottom of the browser viewport)
How can I handle this edge case?
This was encountered using the FireFox driver.

I've never seen this behavior before. Generally when I click on an element, if it's offscreen, the viewport (automatically) is scrolled so that it's visible and it is clicked. I'll give you my best guess and hopefully it will give you some ideas that you can investigate and hopefully solve the problem.
So I think the issue is that .MoveToElement() moves to the center of the element. If the center of the element in question is on the page but is not able to be clicked because it's not fully visible, then it seems like a solution is to make sure the entire element is on the page. One way I can think of to do this is to use MoveToElement(IWebElement, Int32, Int32). The offsets are from the top-left corner of the element. If you use this to move to the top-left and then the bottom-right, that combination should fully display the element then it can be clicked. The top-left would be 0,0 and the bottom right would be found using IWebElement.Size to get the width and height of the element.
A function would look something like this
public void ShowElement(IWebElement e)
{
Actions action = new Actions(Driver);
action.MoveToElement(e, 0, 0).MoveToElement(e, e.Size.Width, e.Size.Height).Build().Perform();
}

Related

Unexpected output from checking if mouse within control

I am implementing a custom drag and drop interface with winForm Buttons and after viewing several solutions on how to obtain mouse position and check it against control bound have not been able to get it to work.
I have tried:
button.ClientRectangle.Contains(PointToClient(Cursor.Position))
and
button.ClientRectangle.Contains(PointToClient(Control.MousePosition))
Both of these have failed to work. Checking the mouse bounds seem like a simple operation, but I really am stumped.
My speculation of the unexpected values are:
Process of obtaining cursor position may be in wrong corner of cursor image
Method/Function does not work on Buttons for some reason
You are using the wrong object reference, calculating the mouse position relative to the form instead of the button. And you are writing it in a way that make this very hard to debug. Fix:
var pos = button.PointToClient(Cursor.Position);
System.Diagnostics.Debug.WriteLine(pos); // Now it is easy
if (button.ClientRectangle.Contains(pos)) {
// etc...
}

Winrt - Adjusting flyout according to where it appears

I have a GridView in a windows store project, that contains some big squares, and inside those i have a list of user images, when i tap on of those images a flyout appears on the right showing some information like this.
the problem is that my gridview extends to the edges of the screen and beyond, and when that does i get this situation, i press the user with the red border near the edge of the screen and flyout appears on left.
My flyout placement is set to Right, and im guessing since the element i press is near the edge it follows the Fall back order with according to this is Right > Left > Top > Bottom.
What i would like to know is how to detect this happens, so i can adjust my flyout position, or another viable alternative :)
After searching through properties and Dependency properties on Flyout and FlyoutBase, I haven't found a way to simply get the actual placement of the Flyout (which is unfortunate because I think that can be important, as we see in your case). Perhaps you can try what was proposed here by implementing a method that compares the desired size of the Flyout with the available space.
You can subscribe to FlyOut.Opened event and compare absolute coordinates of the flyout and the element you're showing it at. Here is an example for top/bottom flyout placement (easily extendable to check for left/right as well):
private void FlyOut_Opened(object sender, object e)
{
GeneralTransform flyOutTransform =
flyOut.Content.TransformToVisual(Window.Current.Content);
Point flyOutPosition =
flyOut.TransformPoint(new Point(0, 0));
GeneralTransform showAtElementTransform =
showAtElementTransform.TransformToVisual(Window.Current.Content);
Point showAtElementPosition =
showAtElementPosition.TransformPoint(new Point(0, 0));
if(flyOutPosition.Y < showAtElementPosition.Y)
{
// top
}
else
{
// bottom
}
}

Client/Screen Coordinate Conversion

I've fallen down a deep rabbit hole. There are actually two issues that I've dealt with. I don't think anyone will have a solution for the first issue (mentioned in the next paragraph), so I guess the real question is how the heck to use PointToScreen/PointToClient reliably.
I want to use balloons to show validation failures for a user control I've written. The way to do this is to use a tooltip with IsBalloon set. In my validation error handler, I call Show() on the tooltip with my user-control as the parameter. This works if I click on another control, but not if I use tab to leave the control. I've even tried hacks like queuing a task on another thread to sleep a bit, then try to show the balloon. Nothing works.
So, I decided to try to go around this and use the main window ("this") as the parameter and specify coordinates, i.e.:
_balloon.Show(text, this, pos);
I can't seem to calculate the position (pos), though.
I'd like for the position to be the bottom right corner of the control, so here that is:
var clientBottomRight = new Point(_ctrlCallbackPhone.Width, _ctrlCallbackPhone.Height);
Then, I try to get the actual screen coordinates of that spot like so:
var screenPosition = _ctrlCallbackPhone.PointToScreen(clientBottomRight);
Finally, I try to get the coordinates on the main form ("this") like so:
var mainPosition = this.PointToClient(screenPosition);
Then I show the balloon. You have to do it twice because of a Windows bug.
_balloon.Show(string.Empty, this, mainPosition);
_balloon.Show(text, this, mainPosition);
The result is well above and slightly to the left of where it should be. Although the margin of error looks like about the size of the title bar, I don't see how that's it. I'm getting the screen coordinates of a spot, and asking for the client coordinates of that same spot.
Now, of course, if someone has a real solution to making the balloon work when I tab away from the control, I'd stop caring about the screen coordinates thing. I imagine this is some sort of Windows weirdness, though, that I won't be able to solve.
I don't fully understand why this works, but this results in the correct coordinates:
var mainPosition = this.PointToClient(screenPosition);
mainPosition = new Point(
mainPosition.X + SystemInformation.VerticalResizeBorderThickness,
mainPosition.Y + SystemInformation.CaptionHeight + SystemInformation.HorizontalResizeBorderThickness);

How to get the mouse position and use it in the client

I am making a form which has a ListView. I want to show a "Picture Window" whenever mouse hovers above one of the listView Item in the ListView. I implemented this by using "ListView"'s "ItemMouseHover" event. I want to show this "Picture Window" just near to the mouse position. But , I couldn't get the mouse position from the itemmousehover event. Can anybody say how to achieve this?
Note: I am using .Net 4.0
EDIT:
"Danbystrom" gave the exact answer. But I found the root cause is some other. See my answer for that.
The static method Control.MousePosition will give you the coordinates in screen space. Then you can convert that into client coordinates with the Control.PointToClient instance method.
var pt = listView.PointToClient( Control.MousePosition );
The new window will be placed on your will, only if you choose "Manual" instead of "WindowsDefaultLocation" in the Property "StartPosition". Otherwise "OS" will try to put your new window's location somewhere near to the mouse position. If the new window hides the mouse in that position, then it will try through some nearby points which will result in flickering.

Getting the top left coordinates of a WPF UIElement

I am working on extending the Microsoft resize Adorner example and need to be able to reposition the element after say the bottom left drag handle has been dragged.
So if I have a textbox of say 150 wide, 35 high postitioned on my form, and the bottom left drag handle changes the width to 200 wide, the right hand of the text box remains unchanged but the left hand edge moves to the left.
So I need to know the top left coordinates of the UIElement. I have tried Canvas.GetLeft and Canvas.GetTop but they return NaN which is confusing.
I just tried VisualTreeHelper.GetOffset which does return an offset but when you try and use it in the arrange method of the element it disappears, presumably as the values in the offset are too high.
In the days before Wpf the coordinate system was quite simple, wpf has overcomplicated things I think.
And if someone just wants the control's screen coordinates:
Point targetLoc = targetCtrl.PointToScreen(new Point(0, 0));
(this doesn't match the thread's description, but it does match the title. Figured it might help people coming in off search results)
You can transform coordinates of the UIElement to its parent. In your case it's a form. Here is an example of a method that returns coordinates of a visual:
private Point GetPosition(Visual element) {
var positionTransform = element.TransformToAncestor(MyForm);
var areaPosition = positionTransform.Transform(new Point(0, 0));
return areaPosition;
}

Categories