3

This is more of a hypothetical question, I'm brainstorming some ideas for a project that I'm planning, and was curious if anyone knew of any APIs or methods of getting any highlighted text instantly on any window, for example from a browser or word processor. It could also have possibly a key command that would only read when pressed (Akin to CTRL+C adding the selected text to a clipboard)

Any knowledge in what APIs exist for this would be greatly appreciated.

Kai
  • 38,985
  • 14
  • 88
  • 103
Matt C
  • 137
  • 1
  • 3
  • 15
  • 1
    Java is quite poor when it comes to monitoring activity in *other apps*. You'd need some native OS-level support for that. – Thilo Dec 12 '12 at 12:30
  • 1
    I suspect you need to write a DLL which integrates with the windows GUI libraries, not in Java. – Peter Lawrey Dec 12 '12 at 12:31
  • @Thilo Java is designed not grab data from other applications in ways which would be useful for hackers. ;) – Peter Lawrey Dec 12 '12 at 12:32
  • Using JNA I imagine you could do that but that will be OS specific. I also imagine that you will need to constantly poll the window that has focus to get the text from it because I don't know if there is some kind of hook that will alert you whenever selection change in any application. – Alex Dec 12 '12 at 12:56
  • Ok it's not for a hacking tool ;) What about reading from the Clipboard would that work, that would I assume also allow multi-platform support? – Matt C Dec 12 '12 at 13:19
  • I found a way of doing this through reading the clipboard. [Reading pure text from clipboard][1] [1]: http://stackoverflow.com/questions/7105778/java-get-pure-text-from-clipboard – Matt C Dec 12 '12 at 13:43
  • Yes but the user need to copy himself the text into its clipboard, there is a way using JNA on Windows to easilyy get the currently selected text into the clipboard by emulating a `Ctrl-c`. – Alex Dec 13 '12 at 07:25

2 Answers2

5

You can use JNA to actually emulate a Ctrl-C (copy action) on the foreground window, and then read what is in the clipboard, after that you just need to restore what was in the clipboard.

This is a short sample:

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.win32.StdCallLibrary;

public class Foo implements ClipboardOwner {
    public interface CustomUser32 extends StdCallLibrary {
        CustomUser32 INSTANCE = (CustomUser32) Native.loadLibrary("user32", CustomUser32.class);
        HWND GetForegroundWindow();
        void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
    }

    public void lostOwnership(Clipboard clipboard, Transferable contents) {
        // dummy: needed for `ClipboardOwner`
    }

    void controlC(CustomUser32 customUser32) {
        customUser32.keybd_event((byte) 0x11 /* VK_CONTROL*/, (byte) 0, 0, 0);
        customUser32.keybd_event((byte) 0x43 /* 'C' */, (byte) 0, 0, 0);
        customUser32.keybd_event((byte) 0x43 /* 'C' */, (byte) 0, 2 /* KEYEVENTF_KEYUP */, 0);
        customUser32.keybd_event((byte) 0x11 /* VK_CONTROL*/, (byte) 0, 2 /* KEYEVENTF_KEYUP */, 0);// 'Left Control Up
    }

    String getClipboardText() throws Exception {
        return (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
    }

    void setClipboardText(String data) throws Exception {
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(data), this);
    }

    String getSelectedText(User32 user32, CustomUser32 customUser32) throws Exception {
        HWND hwnd = customUser32.GetForegroundWindow();
        char[] windowText = new char[512];
        user32.GetWindowText(hwnd, windowText, 512);
        String windowTitle = Native.toString(windowText);
        System.out.println("Will take selected text from the following window: [" + windowTitle + "]");
        String before = getClipboardText();
        controlC(customUser32); // emulate Ctrl C
        Thread.sleep(100); // give it some time
        String text = getClipboardText();
        System.out.println("Currently in clipboard: " + text);
        // restore what was previously in the clipboard
        setClipboardText(before);
        return text;
    }

    public static void main(String[] args) throws Exception {
        Foo foo = new Foo();
        Thread.sleep(2000); // take some time for you to select something anywhere
        System.out.println(foo.getSelectedText(User32.INSTANCE, CustomUser32.INSTANCE));
    }
}

When you run it, you will have two seconds to select some text somewhere on any application, and then it will normally print it.

Will take selected text from the following window: [java - Monitor text that is highlighted - Stack Overflow - Google Chrome]

Currently in clipboard: I'm brainstorming some ideas for a project that I'm planning

You don't need to accept my answer, it was just to show you what I said in my comment above.

Alex
  • 25,147
  • 6
  • 59
  • 55
0
public static String getSelectedData() {
    try {
        Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_CONTROL);
        Thread.sleep(2*1000);
        robot.keyPress(KeyEvent.VK_C);
        Thread.sleep(2*1000);
        robot.keyRelease(KeyEvent.VK_C);
        Thread.sleep(2*1000);
        robot.keyRelease(KeyEvent.VK_CONTROL);
        Thread.sleep(2*1000);
    } catch (Exception ex) {
        System.out.println(ex);
    }
    String word = getSelectedData();
    return word;
}

private static String getDataFromClipboard() {

Toolkit toolkit = Toolkit.getDefaultToolkit();
Clipboard clipboard = toolkit.getSystemClipboard();
try {
    String result = (String) clipboard.getData(DataFlavor.stringFlavor);
    return result;
} catch (Exception e) {
    System.out.println("ERROR");
    return null;
}
}
aminography
  • 21,986
  • 13
  • 70
  • 74
SOF
  • 1