Java AutoClicker with JNativeHook Runs infinitely - java

I have been trying to write this autoclicker with java for around 7 hours now. I wrote some of this based on other people's code, some by myself. I used JNativeHook to capture clicks in windows outside of Eclipse/the console.
The idea is this: When you hold left click, the Robot will left click for you with 300 ms in between each click.
The problem, however, is that when I left click, I do not execute the code to make the robot run. When I add the line "test.run();" in the nativeMousePressed listener, YES, it DOES autoclick, but when I release left click, It still runs. The only way to then stop it is to click the stop button on eclipse.
Now, I understand I need to make it run in a new thread so I can still use listeners with it, which I attempted to do with this in my MousePressed listener:
Thread test = new Thread(new Runnable() {
public void run() {
try {
Robot robot = new Robot();
System.out.println("GOT HERE 1");
System.out.println("Got HERE 4");
try {
Thread.sleep(300);
System.out.println("Got HERE 5");
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
// robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
System.out.println("Got HERE 6");
// if ();
} catch (InterruptedException ex) {
}
} catch (AWTException e1) {
}
;
}
});
I already removed my loop because that did not seem to do anything to change it. Can somebody explain to me what is going wrong here?
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;
public class AutoClicker implements NativeMouseInputListener {
public void nativeMouseClicked(NativeMouseEvent e) {
// dont need
}
public void nativeMousePressed(NativeMouseEvent e) {
if (e.getButton() == NativeMouseEvent.BUTTON1) {
System.out.println("Mouse Pressed: " + e.getButton());
run = true;
System.out.println(run);
Thread test = new Thread(new Runnable() {
public void run() {
try {
Robot robot = new Robot();
System.out.println("GOT HERE 1");
System.out.println("Got HERE 4");
try {
Thread.sleep(300);
System.out.println("Got HERE 5");
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
// robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
System.out.println("Got HERE 6");
// if ();
} catch (InterruptedException ex) {
}
} catch (AWTException e1) {
}
;
}
});
}
}
public void nativeMouseReleased(NativeMouseEvent e) {
if (e.getButton() == NativeMouseEvent.BUTTON1) {
System.out.println("Mouse Released: " + e.getButton());
run = false;
System.out.println(run);
}
}
public void nativeMouseMoved(NativeMouseEvent e) {
// dont need
}
public void nativeMouseDragged(NativeMouseEvent e) {
// dont need
}
public void click() {
}
public static boolean run = false;
public static void main(String[] args) {
try {
GlobalScreen.registerNativeHook();
} catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING);
// Don't forget to disable the parent handlers.
logger.setUseParentHandlers(false);
// Construct the example object.
AutoClicker clicker = new AutoClicker();
// Add the appropriate listeners.
GlobalScreen.addNativeMouseListener(clicker);
}
}

Each mouse press triggers a click, So:
When you start your first click with a mouse press, it triggers the click after 300ms
which triggers another click and so on..
Basically the program gets stuck in an infinite loop of clicking, which i sometimes call the Clickening.
If i know what you're exactly trying to do, i might provide you with a better answer.
But as i understand your question now, a simple solution would just be, to only trigger the mouse release robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); and not do a mouse press. This will complete the click your started with your press after 300ms.
UPDATE: Per the OP's comment, here is the updated code, which uses alt to trigger clicking instead of the left mouse button.
Alt pressed --> clicking starts
Alt released --> clicking stops
Escape pressed --> program exits
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
import java.awt.*;
import java.awt.event.InputEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AutoClicker implements NativeKeyListener {
public static void main(String[] args) {
try {
GlobalScreen.registerNativeHook();
} catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.exit(1);
}
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING);
// Don't forget to disable the parent handlers.
logger.setUseParentHandlers(false);
// Construct the example object.
AutoClicker clicker = new AutoClicker();
// Add the appropriate listeners.
GlobalScreen.addNativeKeyListener(clicker);
}
private void startClicking() {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Robot robot = new Robot();
while (isClicking) {
Thread.sleep(300);
System.out.println("Clicked!");
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
} catch (Exception ignored) {
System.out.println("Couldn't click");
}
}
};
Thread clickingThread = new Thread(runnable);
clickingThread.start();
}
private boolean isClicking = false;
#Override
public void nativeKeyPressed(NativeKeyEvent key) {
// When alt is pressed --> Start clicking
if (key.getKeyCode() == NativeKeyEvent.VC_ALT_L || key.getKeyCode() == NativeKeyEvent.VC_ALT_R) {
if (!isClicking) {
System.out.println("Alt pressed, started clicking!");
isClicking = true;
startClicking();
}
}
// If escape is clicked, exit the program
else if (key.getKeyCode() == NativeKeyEvent.VC_ESCAPE) {
System.out.println("Escape button Pressed.EXITING!");
System.exit(0);
}
}
#Override
public void nativeKeyReleased(NativeKeyEvent key) {
if (key.getKeyCode() == NativeKeyEvent.VC_ALT_L || key.getKeyCode() == NativeKeyEvent.VC_ALT_R) {
// When alt is relesed --> Stop clicking
isClicking = false;
System.out.println("Alt released, stopped clicking!");
}
}
#Override
public void nativeKeyTyped(NativeKeyEvent key) {
}
}

I don't know if I should be replying to this considering it is an old thread but I think I had might've found a way without using ALT or a trigger to enable the auto clicker. I had seen that if you were holding mouse button 1, and 100 ms later, the program programmatically releases mouse button1, then you release your real button 1, it says release twice (assuming you had added a print statement in the pressed method in JNativehook). This can be a signal to turn off the auto clicker when it says mouse button 1 that had been released. Hopefully that makes sense!

Related

Java: simulate keypresses when mouse clicked?

So, I'm fairly new to programming and I like to fiddle with it and one day my friend asked me to make a program where when you click, "ctrl" and "s" would be "pressed". I looked at lots of forums trying to make a functional code but, since I'm new to Java, I only got separate pieces of codes and threw it all together.
My code looks like this:
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.event.*;
import java.awt.Robot;
import java.util.Scanner;
public class MyClass {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
System.out.println("press any key to exit.");
keyboard.next();
System.exit(0);
}
public void mouseClicked(MouseEvent evt) {
try {
Robot robot = new Robot();
// Simulate a key press
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_CONTROL);
} catch (AWTException e) {
}
}
}
Your program has no GUI and, therefore, nothing to invoke your mouse listener. The code within the listener appears correct, all you need to do is search for how to create a basic GUI and add the mouse listener to it so you get the results you want.
The following code may help you to handle Ctrl + S
public class SwingApp1 extends JFrame implements KeyListener {
public SwingApp1() {
setSize(500, 500);
setLocationRelativeTo(null);
setBackground(Color.blue);
addKeyListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingApp1 main = new SwingApp1();
main.setVisible(true);
}
#Override
public void keyTyped(KeyEvent evt) {
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Pressed=>" + e.getKeyCode());
if (e.getKeyCode() == 83) {
System.out.println("Pressed Ctrl + S");
} // Ctrl + S
}
#Override
public void keyReleased(KeyEvent e) {
}}

Using java Robot when an another app is active

I'd like to use a simple java Robot that types a text when I click Ctrl+Q. But this has to be done even if I am focused an another app (eg. a game). My code works fine, but it runs only if my JFrame is in focus.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Robot robot = null;
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
robot.mouseMove(350, 150);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.keyPress(KeyEvent.VK_T);
robot.keyRelease(KeyEvent.VK_T);
// Solution for different keyboard layouts (ALT values)
try {
alt(KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD4, KeyEvent.VK_NUMPAD7);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
robot.keyPress(KeyEvent.VK_Q);
robot.keyRelease(KeyEvent.VK_Q);
}
you should try the jnativehook
example usage
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
import java.util.logging.*;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.event.InputEvent;
public class Example implements NativeKeyListener
{
public void nativeKeyPressed(NativeKeyEvent e)
{
if(NativeKeyEvent.getKeyText(e.getKeyCode()).equals("A"))
{
Robot bot = new Robot();
bot.keyPress(KeyEvent.VK_A);
}
}
public void nativeKeyReleased(NativeKeyEvent e)
{
}
public void nativeKeyTyped(NativeKeyEvent e)
{
}
public static void main(String[] args)
{
Example ex = new Example();
try
{
GlobalScreen.registerNativeHook();
Logger logger =
Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.OFF);
}
catch(NativeHookException eb)
{
System.out.println(eb.getMessage());
}
GlobalScreen.addNativeKeyListener(ex);
}
}
This code uses native methods of windows but the good thing is, its easily readable by a java programmer and not a c#,c++,c etc programmer.This library of classes will listen to the key pressed on any application(it is a global keyboard listener), if a certain key is press then perform the Robot class methods(e.g. mousePress() etc.).
P.S. the documentation of classes used is in the file of jnativehook that you are going to download

Java: Thread.sleep mousepress delay

I've been trying to create an autoclicker in java using jnativehook.
It works fine, even compiles and runs. My problem is using Thread.sleep to try and add a delay between clicks:
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
If I were to input a delay of 0 it will function fine. But given no delay it will click too fast.
When I add a delay it will click fine but, when I release the trigger key it will keep clicking for a few seconds given the time it's been clicking. A delay of 0 will not do this however.
Full code:
public class App implements NativeKeyListener{
private JPanel panel1;
private JTabbedPane tabbedPane1;
private JButton spoilerButton;
private JSlider slider1;
private JSlider slider2;
//Removed irrelevant code...
static Robot bot;
static {
try {
bot = new Robot();
} catch (Exception e) {
e.printStackTrace();
}
}
static boolean pressed;
public void click() throws InterruptedException {
try {
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
e.printStackTrace();
}}
#Override
public void nativeKeyPressed(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode()) == "Delete") {
pressed = true;
while (pressed){
try {
click();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}}
#Override
public void nativeKeyReleased(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode())=="Delete"){
pressed=false;
}}
#Override
public void nativeKeyTyped(NativeKeyEvent e) {
}
public static void main(String[] args) {
JFrame frame = new JFrame("Autoclicker");
frame.setContentPane(new App().panel1);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(400,148);
frame.setResizable(false);
try{GlobalScreen.registerNativeHook();
} catch (Exception e){
System.exit(1);}
GlobalScreen.addNativeKeyListener(new App());
}
}
Looks like the method nativeKeyPressed() gets called continuously when you keep pressing the trigger key. This results in several calls to click() method (assuming it's multi threaded) and due to the sleep() between mouse press and release (mouse click is complete when released) this can happen.
Hence you can try two options depending on the root cause:
1. move the sleep() call after mouse released. If the nativeKeyPressed gets called concurrently this won't work.
2. Use a different thread to execute the click() method when trigger is pressed. In this case, you may need to submit a Runnable object to your thread each time with the 'pressed' check and click() call in it. This will ensure it won't run after pressed becomes false.

SWT StackLayout topControl apparently not working

I am testing a simple SWT StackLayout example to learn how it works but things are not working as I expected.
I created a StackLayout with two buttons on them, both set to cycle the top control between the two of them five times when they are selected, with a 2-second pause every time the top control changes. However, when I run the problem I do not see anything happen.
Any ideas on what I am missing?
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
public class MyApp {
protected Shell shlMyFirstSwt;
Button btnOne;
Button btnTwo;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
MyApp window = new MyApp();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shlMyFirstSwt.open();
shlMyFirstSwt.layout();
while (!shlMyFirstSwt.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
* #throws InterruptedException
*/
protected void createContents() {
shlMyFirstSwt = new Shell();
shlMyFirstSwt.setSize(621, 416);
shlMyFirstSwt.setText("My First SWT Application");
StackLayout layout = new StackLayout();
shlMyFirstSwt.setLayout(layout);
Button btnOne = new Button(shlMyFirstSwt, SWT.NONE);
btnOne.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
for (int i = 0; i != 10; i++) {
layout.topControl = i % 2 == 0? btnOne : btnTwo;
shlMyFirstSwt.layout();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
});
btnOne.setText("One");
Button btnTwo = new Button(shlMyFirstSwt, SWT.NONE);
btnTwo.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
for (int i = 0; i != 10; i++) {
layout.topControl = i % 2 == 0? btnOne : btnTwo;
shlMyFirstSwt.layout();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
});
btnTwo.setText("Two");
}
}
Elaborating after first answer:
Trying a simpler approach without delaying. Now I modified the event handler to simply have one button switch the top control to be the other button, as shown below. I expected the two buttons to alternate as top control, but instead when I click on the first button, the window turns blank. Any idea why?
Button btnOne = new Button(shlMyFirstSwt, SWT.NONE);
btnOne.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
layout.topControl = btnTwo;
shlMyFirstSwt.layout();
}
});
btnOne.setText("One");
Button btnTwo = new Button(shlMyFirstSwt, SWT.NONE);
btnTwo.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
layout.topControl = btnOne;
shlMyFirstSwt.layout();
}
});
btnTwo.setText("Two");
Your Thread.sleep calls are blocking the user interface thread so the GUI does not get updated. You must never block the user interface thread like this. Calls to methods like layout do not update instantly - they require that display.readAndDispatch runs to dispatch the various updates that are generated.
If you want to delay something use Display.timerExec:
Display.getDefault().timerExec(2000, new Runnable() {
#Override
public void run()
{
... code to be run after the delay
}
});
So you will have to rework your code to use this to do the timed updated.
Figured it out: just the silly mistake of including btnTwo in the first event handler before it was initialized, even though it is used after initialization.

How can I do full screen in Java on OSX

I've been trying and failing to use the java full screen mode on the primary display of an OSX system. Whatever I've tried I can't seem to get rid of the 'apple' menu bar from the top of the display. I really need to paint over the entire screen. Can anyone tell me how to get rid of the menu?
I've attached an example class which exhibits the problem - on my system the menu is still visible where I would expect to see a completely blank screen.
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
public class FullScreenFrame extends JFrame implements KeyListener {
public FullScreenFrame () {
addKeyListener(this);
setUndecorated(true);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
if (gd.isFullScreenSupported()) {
try {
gd.setFullScreenWindow(this);
}
finally {
gd.setFullScreenWindow(null);
}
}
else {
System.err.println("Full screen not supported");
}
setVisible(true);
}
public void keyTyped(KeyEvent e) {}
public void keyPressed(KeyEvent e) {}
public void keyReleased(KeyEvent e) {
setVisible(false);
dispose();
}
public static void main (String [] args) {
new FullScreenFrame();
}
}
I think your problem is here:
try {
gd.setFullScreenWindow(this);
}
finally {
gd.setFullScreenWindow(null);
}
finally blocks are always executed, so what happens here is that you window becomes full screen for a brief instant (if that) and then relinquishes the screen immediately.
Also, setVisible(true) is not necessary when you have previously called setFullScreenWindow(this), according to the Javadocs.
So I would change the constructor to this:
public FullScreenFrame() {
addKeyListener(this);
GraphicsDevice gd =
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
if (gd.isFullScreenSupported()) {
setUndecorated(true);
gd.setFullScreenWindow(this);
} else {
System.err.println("Full screen not supported");
setSize(100, 100); // just something to let you see the window
setVisible(true);
}
}
On OS X (10.7 and higher), it is better to use the native fullscreen mode available. You should use:
com.apple.eawt.FullScreenUtilities.setWindowCanFullScreen(window,true);
com.apple.eawt.Application.getApplication().requestToggleFullScreen(window);
where window is the window (JFrame, etc) that you want to take fullscreen
Thats a bit pedantic, the answer is to follow the tutorial completely, which has the essentials and is somewhat more expansive than would fit in a post. The above sample does not work because it is missing a validate(); and some content. I suspect the Java Tutorial will not disappear any time soon. Below is a modified version
package test;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class FullScreenFrame extends JFrame implements KeyListener {
public FullScreenFrame () {
addKeyListener(this);
setUndecorated(true);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
if (gd.isFullScreenSupported()) {
try {
this.getContentPane().addKeyListener(this);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add("Center", new JLabel("Full Screen, back to normal in 10 seconds"));
gd.setFullScreenWindow(this);
validate();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} finally {
gd.setFullScreenWindow(null);
}
} else {
System.err.println("Full screen not supported");
}
}
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped:" + e.getKeyChar() + "source:" + e.getSource() );
}
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed:" + e.getKeyChar() + "source:" + e.getSource() );
}
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased:" + e.getKeyChar() + "source:" + e.getSource() );
setVisible(false);
dispose();
}
public static void main (String [] args) {
new FullScreenFrame();
}
}

Categories