Chinaunix首页 | 论坛 | 博客
  • 博客访问: 530516
  • 博文数量: 135
  • 博客积分: 3568
  • 博客等级: 中校
  • 技术积分: 1942
  • 用 户 组: 普通用户
  • 注册时间: 2006-10-19 17:52
文章分类

全部博文(135)

文章存档

2012年(29)

2011年(41)

2010年(26)

2009年(12)

2008年(9)

2007年(12)

2006年(6)

分类: Java

2012-03-07 01:43:40



TestJNA.java

  1. import com.sun.jna.Library;
  2. import com.sun.jna.Native;
  3. import com.sun.jna.Platform;
  4. import com.sun.jna.platform.win32.Kernel32;
  5. import com.sun.jna.platform.win32.User32;
  6. import com.sun.jna.platform.win32.WinBase;
  7. import com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES;
  8. import com.sun.jna.platform.win32.WinDef.DWORD;
  9. import com.sun.jna.platform.win32.WinDef.HMODULE;
  10. import com.sun.jna.platform.win32.WinDef.HWND;
  11. import com.sun.jna.platform.win32.WinDef.LPARAM;
  12. import com.sun.jna.platform.win32.WinDef.LRESULT;
  13. import com.sun.jna.platform.win32.WinDef.WPARAM;
  14. import com.sun.jna.platform.win32.WinNT.OSVERSIONINFOEX;
  15. import com.sun.jna.platform.win32.WinUser;
  16. import com.sun.jna.platform.win32.WinUser.HHOOK;
  17. import com.sun.jna.platform.win32.WinUser.HOOKPROC;
  18. import com.sun.jna.platform.win32.WinUser.KBDLLHOOKSTRUCT;
  19. import com.sun.jna.platform.win32.WinUser.LowLevelKeyboardProc;
  20. import com.sun.jna.win32.StdCallLibrary;
  21. import com.sun.jna.win32.W32APIOptions;

  22. /**
  23.  * JNA 小试 。
  24.  * @author btpka3@163.com
  25.  */
  26. //
  27. //
  28. public class TestJNA {

  29.     public static void main(String[] args) {

  30.         // case01();
  31.         // case02();
  32.         // case03();
  33.         case04();
  34.     }

  35.     // 示例 1. 调用 C 函数
  36.     // PS: 一些IO函数,比如 fopen 等,还不知道怎么调用,主要是那个结构体和一些标准常量 比如 stdin 等。
  37.     public static void case01() {
  38.         System.out.println("============================= CASE 1");
  39.         for (int i = 0; i < 10; i++) {
  40.             CLibrary.INSTANCE.printf("%s = %d: \n", "num" + i, i);
  41.         }
  42.         CLibrary.INSTANCE.printf("Hello, World\n");
  43.         System.out.println();
  44.     }

  45.     public interface CLibrary extends Library {
  46.         static CLibrary INSTANCE = (CLibrary) Native.loadLibrary(
  47.                 (Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);

  48.         void printf(String format, Object... args);
  49.     }

  50.     // 示例 2. 打开外部程序(浏览器)
  51.     // PS: 遗留问题,每次都是新浏览器窗口,如何使其在已打开浏览器窗口的新Tab页中打开?
  52.     public static void case02() {
  53.         System.out.println("============================= CASE 2");

  54.         // 打开 IE 浏览器
  55.         // %28v=vs.85%29.aspx
  56.         Kernel32 kernel32 = Kernel32.INSTANCE;
  57.         SECURITY_ATTRIBUTES procSecAttr = new SECURITY_ATTRIBUTES();
  58.         SECURITY_ATTRIBUTES threadSecAttr = new SECURITY_ATTRIBUTES();
  59.         WinBase.PROCESS_INFORMATION.ByReference pi = new WinBase.PROCESS_INFORMATION.ByReference();
  60.         WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();
  61.         boolean success = kernel32.CreateProcess(null,
  62.                 "explorer.exe ", procSecAttr, threadSecAttr,
  63.                 false, new DWORD(0x00000010), null, null, startupInfo, pi);

  64.         // 将使用默认浏览器打开(我这里是火狐浏览器)
  65.         // Shell32.INSTANCE.ShellExecute(null, "open", "",
  66.         // null, null, 9);

  67.         if (!success) {
  68.             System.out.println("打开IE浏览器失败");
  69.         } else {
  70.             System.out.println("打开IE浏览器成功");
  71.         }

  72.         kernel32.CloseHandle(pi.hProcess);
  73.         kernel32.CloseHandle(pi.hThread);

  74.         System.out.println();
  75.     }

  76.     // 示例 3. 打开计算器并修改输入
  77.     public static void case03() {
  78.         System.out.println("============================= CASE 3");

  79.         // 打开计算器
  80.         Kernel32 kernel32 = Kernel32.INSTANCE;
  81.         SECURITY_ATTRIBUTES procSecAttr = new SECURITY_ATTRIBUTES();
  82.         SECURITY_ATTRIBUTES threadSecAttr = new SECURITY_ATTRIBUTES();
  83.         WinBase.PROCESS_INFORMATION.ByReference byRef = new WinBase.PROCESS_INFORMATION.ByReference();
  84.         WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();
  85.         startupInfo = new WinBase.STARTUPINFO();
  86.         boolean success = kernel32.CreateProcess(null, "calc.exe", procSecAttr,
  87.                 threadSecAttr, false, new DWORD(0x00000010), null, null,
  88.                 startupInfo, byRef);
  89.         if (!success) {
  90.             System.out.println("计算器打开失败");
  91.             System.out.println();
  92.             return;
  93.         }

  94.         // 找到计算器的窗口
  95.         // PS:仅仅是为了学习。如果程序是自己打开的,应该使用 startupInfo。
  96.         User32 user32 = User32.INSTANCE;
  97.         int tryTimes = 0;
  98.         boolean found = false;
  99.         HWND h1 = null;
  100.         while (!found && tryTimes < 3) {
  101.             h1 = user32.FindWindow(null, "计算器");
  102.             if (h1 == null) {
  103.                 tryTimes++;
  104.                 try {
  105.                     Thread.sleep(1000);
  106.                 } catch (InterruptedException e) {
  107.                     break;
  108.                 }
  109.             } else {
  110.                 found = true;
  111.             }
  112.         }
  113.         System.out.println("tryTimes = " + tryTimes);
  114.         if (h1 == null) {
  115.             System.out.println("找不到计算器");
  116.             System.out.println();
  117.             return;
  118.         }

  119.         // 使计算器窗口置前
  120.         user32.SetForegroundWindow(h1);

  121.         // 找到输入框并设置文本(XP OK,Win7 的计算器已经改变)
  122.         OSVERSIONINFOEX osVerInfo = new OSVERSIONINFOEX();
  123.         boolean setText = kernel32.GetVersionEx(osVerInfo);
  124.         if (setText) {
  125.             int major = osVerInfo.dwMajorVersion.intValue();
  126.             int minor = osVerInfo.dwMinorVersion.intValue();
  127.             if (!(major == 5 && minor == 0) // Windows 2000
  128.                     && !(major == 5 && minor == 1) // Windows XP
  129.                     && !(major == 5 && minor == 1) // Windows 2003 (R2)
  130.             ) {
  131.                 setText = false;
  132.             }
  133.         }
  134.         if (setText) {
  135.             MyUser32 myUser32 = MyUser32.INSTANCE;
  136.             HWND h2 = myUser32.FindWindowEx(h1, null, "Edit", null); //
  137.             final int WM_SETTEXT = 0xC;
  138.             myUser32.SendMessage(h2, WM_SETTEXT, new WPARAM(0), "123ABC中文");
  139.             try {
  140.                 Thread.sleep(3000);
  141.             } catch (InterruptedException e) {
  142.                 e.printStackTrace();
  143.             }

  144.             // 模拟 Esc 按键的 down 与 up,清除设置的不合法输入
  145.             final int VK_ESCAPE = 0x1B;
  146.             WPARAM wParam = new WPARAM(VK_ESCAPE);
  147.             int repeatCount = 1;
  148.             int scanCode = 0;
  149.             int i***tendedKey = 0;
  150.             int contextCode = 0;
  151.             int preKeyState = 0;
  152.             int transitionState = 0;
  153.             LPARAM lParam = new LPARAM(repeatCount | scanCode | i***tendedKey
  154.                     | contextCode | contextCode | preKeyState | transitionState);
  155.             user32.PostMessage(h1, User32.WM_KEYDOWN, wParam, lParam);

  156.             repeatCount = 1;
  157.             scanCode = 0;
  158.             i***tendedKey = 0;
  159.             contextCode = 0;
  160.             preKeyState = 1 << 31;
  161.             transitionState = 1 << 31;
  162.             user32.PostMessage(h1, User32.WM_KEYUP, wParam, lParam);

  163.             try {
  164.                 System.out.println("文字应当已经被清除,请确认。");
  165.                 Thread.sleep(3000);
  166.             } catch (InterruptedException e) {
  167.                 e.printStackTrace();
  168.             }
  169.         }

  170.         // 调用 PostMessage, 计算 1+2+3+4+5+6+7+8+9=
  171.         // FIXME : 区别 SendInput SendMessage PostMessage
  172.         for (int i = 0; i < 10; i++) {
  173.             user32.PostMessage(h1, User32.WM_CHAR, new WPARAM('0' + i),
  174.                     new LPARAM(0));
  175.             if (i < 9) {
  176.                 user32.PostMessage(h1, User32.WM_CHAR, new WPARAM('+'),
  177.                         new LPARAM(0));
  178.             } else {
  179.                 user32.PostMessage(h1, User32.WM_CHAR, new WPARAM('='),
  180.                         new LPARAM(0));
  181.             }
  182.             try {
  183.                 Thread.sleep(500);
  184.             } catch (InterruptedException e) {
  185.                 e.printStackTrace();
  186.             }
  187.         }
  188.     }

  189.     public interface MyUser32 extends StdCallLibrary, WinUser {
  190.         static MyUser32 INSTANCE = (MyUser32) Native.loadLibrary("user32",
  191.                 MyUser32.class, W32APIOptions.DEFAULT_OPTIONS);

  192.         HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,
  193.                 String lpszClass, String lpszWindow);

  194.         // 注意:最后一个参数的类型,该函数在Java里可以声明多个类型。
  195.         LRESULT SendMessage(HWND hWnd, int Msg, WPARAM wParam, String lParam);

  196.         LPARAM GetMessageExtraInfo();
  197.     }

  198.     public static HHOOK hHook;
  199.     public static HOOKPROC lpfn;
  200.     public static volatile boolean quit = false;

  201.     /**
  202.      * 全局键盘钩子 http://www.cnblogs.com/chuncn/archive/2009/01/12/1374109.html
  203.      *
  204.      * FIXME 如何做到线程键盘钩子?
  205.      */
  206.     public static void case04() {

  207.         HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);

  208.         lpfn = new LowLevelKeyboardProc() {
  209.             int count = 1;

  210.             public LRESULT callback(int nCode, WPARAM wParam,
  211.                     KBDLLHOOKSTRUCT keyInfo) {
  212.                 System.out.println("nCode =" + nCode + ", wParam =" + wParam
  213.                         + ", vkCode=" + keyInfo.vkCode);
  214.                 count++;
  215.                 if (count > 10) {
  216.                     quit = true;
  217.                 }
  218.                 return User32.INSTANCE.CallNextHookEx(hHook, nCode, wParam,
  219.                         keyInfo.getPointer());
  220.             }
  221.         };

  222.         // 如果是全局钩子,则线程ID为0
  223.         int threadId = 0;
  224.         // int threadId =
  225.         // user32.GetWindowThreadProcessId(user32.FindWindow(null, "无标题 - 记事本"),
  226.         // null);
  227.         System.out.println("threadId = "
  228.                 + Integer.toHexString(threadId).toUpperCase());
  229.         int idHook = User32.WH_KEYBOARD_LL;
  230.         hHook = User32.INSTANCE.SetWindowsHookEx(idHook, lpfn, hMod, threadId);

  231.         if (hHook == null) {
  232.             System.out.println("键盘钩子安装失败,error = "
  233.                     + Kernel32.INSTANCE.GetLastError());
  234.             return;
  235.         }
  236.         User32.MSG msg = new User32.MSG();
  237.         while (!quit) {
  238.             User32.INSTANCE.PeekMessage(msg, null, 0, 0, 0);
  239.             try {
  240.                 Thread.sleep(100);
  241.             } catch (InterruptedException e) {
  242.                 e.printStackTrace();
  243.             }
  244.         }
  245.         if (User32.INSTANCE.UnhookWindowsHookEx(hHook)) {
  246.             System.out.println("Unhooked");
  247.         }
  248.     }
  249. }


阅读(4592) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~