Robot.mouseMove(1000,1000) moves mouse to random locations on screen… why?

狂风中的少年 提交于 2019-12-11 17:00:06

问题


public class MoveCursor extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage stage) throws Exception {
        Button b = new Button("X");
        b.setOnAction((event) -> {
            try {
                new Robot().mouseMove(1000, 1000);
            } catch (AWTException ex) {
                Logger.getLogger(MoveCursor.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
        stage.setScene(new Scene(b));
        stage.show();
    }
}
  1. this should move the mouse cursor over to position 1000x1000 on my/your screen (i.e. 1000px away from the absolute 0x0 coordinate of my screen... and should wind up always in the same position). ... it doesn't... it depends on where the button is. why?

  2. what's causing this?

... this used to work on an old laptop. i.e. windows 10, 1 intel graphics card, 1 nvidia graphics card, 1920x1080 display.

I'm currently using Windows 10, 2 graphics cards in SLI on a 3840x2160 resolution scaled at 175%.

adjusting the scaling factor doesn't seem to do anything.

... i'm also using jdk8.

using the -Dsun.java2d.dpiaware=true or -Dsun.java2d.dpiaware=false vm options doesn't seem to do anything.

[edit] ... for quesiton duplicate issue... it's not a duplicate of that. the fix in that question is useless.

THIS DOES NOT WORK!

 for(int count = 0;(MouseInfo.getPointerInfo().getLocation().getX() != x || 
        MouseInfo.getPointerInfo().getLocation().getY() != y) &&
        count < 100; count++) {
    new Robot().mouseMove(x, y);
  }

回答1:


Yes, this is a known bug for high resolution screens. See https://bugs.openjdk.java.net/browse/JDK-8186063 for more details.

The best solution would be to run the command in a loop until its gets to the right coordinates.

The code for such a thing would be as follows:

 for(int count = 0;(MouseInfo.getPointerInfo().getLocation().getX() != x || 
        MouseInfo.getPointerInfo().getLocation().getY() != y) &&
        count < 100; count++) {
    new Robot().mouseMove(x, y);
  }

Note that this code sets the max amount of iterations to 100 to prevent an infinite loop, so it would be worthwile to perform another check right after the loop to determine if it is in the right place.




回答2:


Sub-optimal, pathetically bad solution... but it WORKS... and i've wasted far too much time on this issue than i should have.

import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.LONG;
import com.sun.jna.platform.win32.WinUser.INPUT;
import java.awt.MouseInfo;
import java.awt.Point;

public class Mouse {

    public static final int MOUSEEVENTF_MOVE = 1;

    public static void _winEvent_mi_move(int x, int y) {
        mouseAction(x, y, MOUSEEVENTF_MOVE);
    }

    public static void mouseAction(int x, int y, int flags) {
        INPUT input = new INPUT();
        input.type = new DWORD(INPUT.INPUT_MOUSE);
        input.input.setType("mi");
        if (x != -1) {
            input.input.mi.dx = new LONG(x);
        }
        if (y != -1) {
            input.input.mi.dy = new LONG(y);
        }
        input.input.mi.time = new DWORD(0);
        input.input.mi.dwExtraInfo = new ULONG_PTR(0);
        input.input.mi.dwFlags = new DWORD(flags);
        User32.INSTANCE.SendInput(new DWORD(1), new INPUT[]{input}, input.size());
    }

    public static void forceMove(int x, int y) {
        init_abs_move_0_0:
        {
            Point ip = MouseInfo.getPointerInfo().getLocation();
            _winEvent_mi_move(-ip.x, -ip.y);
        }
        moveX:
        {
            while (MouseInfo.getPointerInfo().getLocation().x < x - 1) {
                _winEvent_mi_move(1, 0);
            }
        }
        moveY:
        {
            while (MouseInfo.getPointerInfo().getLocation().y < y - 1) {
                _winEvent_mi_move(0, 1);
            }
        }
        System.out.println(MouseInfo.getPointerInfo().getLocation().toString());
    }

    public static void main(String[] args) {
        forceMove(1000, 1000);
        forceMove(2000, 1500);
    }

}

Theoretially one could achieve the same results by using an awt.Robot instance to move something pixel by pixel... this seems to work better.

yeah... and i did try to calculate the relative target position of the pointer destination based on the current position of the mouse cursor and everything... but it's still based on obscurely difficult to acquire information about whether or not DPI scaling and whatever nonsense MS has decided to implement in the WPI and GDI input event processing routines.

... moving it directly to 0x0 then 1000x1000 makes it result in a cursor position defined by (2000x1400) ... don't have the time nor the patience to figure it out. ... solution works. end of story.




回答3:


I wrote an "adjust" function and it do the dirty work. NOTE: If it has to adjust more than 30 px then it's terminate. You can call with:

If you had the same bug as me the code fix like this:

Adjust:638:598>507:537
Adjust:638:598>670:613
Adjust:638:598>630:595
Adjust:638:598>640:598
Move: 638 598 Click:true

moveAndClick(1000,1000,true);

private void moveAndClick(int x, int y, boolean click) throws AWTException {

    robot.mouseMove(x, y);

    adjustMouse(x, y);

    if (click) {
        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
    }
    System.out.println("Move: " + x + " " + y + " Click:" + click);

}

private void adjustMouse(int x, int y) {

    int realX = MouseInfo.getPointerInfo().getLocation().x;
    int realY = MouseInfo.getPointerInfo().getLocation().y;

    int aX = x;
    int aY = y;

    int count = 0;

    while (realX != x || realY != y) {
        System.out.println("Adjust:" + x + ":" + y + ">" + realX + ":" + realY + "");

        aX = realX > x ? aX-- : aX++;
        aY = realY > y ? aY-- : aY++;

        robot.mouseMove(x, y);
        try {  // you can remove this part 
            Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count++;

        realX = MouseInfo.getPointerInfo().getLocation().x;
        realY = MouseInfo.getPointerInfo().getLocation().y;
        if (count > 30) {  // you can remove or increase this part
            System.exit(0);
        }
    }


}

yields:

@ system.start - mouse position : java.awt.Point[x=1540,y=1462]
Adjust:1000:1000>191:307
Adjust:1000:1000>2212:2039
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
Adjust:1000:1000>2500:2159
Adjust:1000:1000>0:0
@ system.exit - mouse position : java.awt.Point[x=2500,y=2159]


来源:https://stackoverflow.com/questions/49577410/robot-mousemove1000-1000-moves-mouse-to-random-locations-on-screen-why

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!