I wanted to monitor the Windows clipboard with JNA, so I did a lot of research. Helpful site: https://stackoverflow.com/a/28693513 https://java-native-access.github.io/jna/4.2.0/com/sun/jna/platform/win32/WinUser.WindowProc.html https://www.codota.com/code/java/methods/com.sun.jna.platform.win32.User32/DefWindowProc http://kaitei.net/winapi/window-procedures/ https://github.com/EsotericSoftware/clippy/blob/master/src/com/esotericsoftware/clippy/Win.java https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats https://www.cnblogs.com/tangchun/p/9288626.html https://blog.csdn.net/tcjiaan/article/details/8951280 https://www.cnblogs.com/iszero/p/4020207.html https://reehappy.com/java009/
Rough flow:
Sample code. ** Validated with jna-5.5.0.jar **
MyUser32.java
package clipbord;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import com.sun.jna.win32.W32APIOptions;
final public class MyUser32 {
static {
Native.register(NativeLibrary.getInstance("user32", W32APIOptions.DEFAULT_OPTIONS));
}
static public final int WM_CLIPBOARDUPDATE = 0x31D;
// https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
static public final int CF_TEXT = 1;
static public final int CF_UNICODETEXT = 13;
static public final int CF_HDROP = 15;
// Clipboard
static public native boolean AddClipboardFormatListener(Pointer hWnd);
static public native boolean RemoveClipboardFormatListener(Pointer hWnd);
static public native boolean OpenClipboard(Pointer hWnd);
static public native boolean CloseClipboard(Pointer hWnd);
static public native boolean EmptyClipboard();
static public native boolean IsClipboardFormatAvailable(int format);
static public native Pointer GetClipboardData(int format);
static public native Pointer SetClipboardData(int format, Pointer hMem);
static public native Pointer GetClipboardOwner();
}
ClipboardWatcher.java
package clipbord;
import java.util.Scanner;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinUser.WNDCLASSEX;
import com.sun.jna.platform.win32.WinUser.WindowProc;
public class ClipboardWatcher {
public static void main(String[] args) {
new ClipboardWatcher().start();
}
private Thread thread;
private HWND _hWnd;
final public void start() {
this.thread = new Thread(this::myThread);
this.thread.start();
{
System.out.println("watching clipboard. press any key to exit...");
Scanner sc = new Scanner(System.in);
sc.next();
sc.close();
}
this.stop();
}
final public void stop() {
boolean remove = MyUser32.RemoveClipboardFormatListener(this._hWnd.getPointer());
System.out.println("RemoveClipboardFormatListener:" + remove);
User32.INSTANCE.PostMessage(this._hWnd, User32.WM_QUIT, null, null);
System.out.println("exit");
}
private final WindowProc callback = new WindowProc() {
@Override
public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) {
//System.out.println(uMsg);
switch (uMsg) {
case WinUser.WM_CREATE:
System.out.println("WM_CREATE");
return new LRESULT(0);
case WinUser.WM_DESTROY:
System.out.println("WM_DESTROY");
User32.INSTANCE.PostQuitMessage(0);
return new LRESULT(0);
case MyUser32.WM_CLIPBOARDUPDATE:
// System.out.println("WM_CLIPBOARDUPDATE");
MyUser32.OpenClipboard(hWnd.getPointer());
if (/*MyUser32.IsClipboardFormatAvailable(MyUser32.CF_TEXT) ||*/ MyUser32.IsClipboardFormatAvailable(MyUser32.CF_UNICODETEXT)) {
/* do something here */
System.out.println(MyUser32.GetClipboardData(MyUser32.CF_UNICODETEXT).getWideString(0));
}
MyUser32.CloseClipboard(hWnd.getPointer());
return new LRESULT(0);
default:
return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
};
private void myThread() {
//WString className = new WString("myclass");
String className = "myclass";
WNDCLASSEX wx = new WNDCLASSEX();
wx.clear();
wx.lpszClassName = className;
wx.lpfnWndProc = callback;
if (User32.INSTANCE.RegisterClassEx(wx).intValue() != 0) {
this._hWnd = User32.INSTANCE.CreateWindowEx(0, className, null, 0, 0, 0, 0, 0, null, null, null, null);
boolean add = MyUser32.AddClipboardFormatListener(this._hWnd.getPointer());
System.out.println("AddClipboardFormatListener:" + add);
WinUser.MSG msg = new WinUser.MSG();
msg.clear();
while (User32.INSTANCE.GetMessage(msg, this._hWnd, 0, 0) > 0) {
User32.INSTANCE.TranslateMessage(msg);
User32.INSTANCE.DispatchMessage(msg);
}
}
}
}
that's all
Recommended Posts