45. Java运用JNI调用dll实现屏蔽系统热键

1. 首先,屏蔽系统热键

1、建一个java shieldHK (把类建在包里,目的是为了其他的类方便的调用)
2、建一个类 ShieldHotKey

代码如下:

package shieldHK;

import java.util.logging.Level; 
import java.util.logging.Logger;

/** 

* @author Administrator 
*/ 
public class ShieldHotKey { 
    static{ 
        System.load("D:/shieldHK.dll"); 
    } 
    public static native void Attach();//
启动屏蔽 
    public static native void Detach();//
关闭屏蔽 
}

3、编译生成 ShieldHotKey.class 文件 
4
、运用.class文件生成.h头文件。 [看例子]

1、首先我们要编译一下这个类,以便得到类对应的*.class

为了偷懒,给这个类直接添上一个main方法,将这类作为运行一下(如下图所示)。这样子我们就得到了jni_test对应的class文件,在路径“D:\我的文档\workspace\PrepareForExam\bin\com\example\myclass”下。

2、我们要开始写javah的命令,以便生成对应的C语言头文件

D:\我的文档\workspace\PrepareForExam\src>javah -classpath D:\我的文档\workspace\PrepareForExam\bin -d d:/ -jni
 com.example.myclass.jni_test

其中java中各个命令的意思是

-classpath <路径用于装入类的路径
-d <目录输出目录
-jni 生成 JNI样式的头文件(默认)

注意到以上我们命令中指定的路径

注意到我们的命令符的执行位置是源代码目录”D:\我的文档\workspace\PrepareForExam\src

-classpath  后面的路径是指包”com.example.myclass”所在的根路径(如下图所示)

-jni 后面的路径是包名+类名

以上方法可以生成C++头文件,

下面还有另一种方法【测试成功】

http://blog.csdn.net/uikoo9/article/details/7454209

【前言】

这几天用Java做个锁屏软件需要屏蔽系统热键,就是Win+DCtrl+Alt+Del等,

网上找了好多,发现这篇文章:

java运用jni调用dll(含源码)实现屏蔽系统热键和任务栏

http://hi.baidu.com/nowgame/blog/item/4530e11f20f289fee1fe0ba1.html

但是对于只懂Java的人无疑是一种折磨,

好不容易跟着文章做下来又报错,总之很是痛苦,

今天又看了篇文章:

http://wenku.baidu.com/view/51bf0d96daef5ef7ba0d3c54.html

结合这两篇文章终于实现了Java屏蔽系统热键了。

 

下面写出来,图文结合,宣泄一下这几天的郁闷。

 

【说明】

1.本文都是在eclipse下开发的,dos下可以自己尝试。

2.以下源码都是上面第一篇文章中的

 

1】编写Java文件,编译出class文件,javah.h文件

——Java源码

[html] view plaincopy

  1. package com.uikoo9.JLocker;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.InputStream;  
  6.   
  7. /**   
  8. *   
  9. * @author Administrator   
  10. */   
  11. public class ShieldHotKey {   
  12.     static{   
  13.         //下面这部分是为了增加灵活性,dll可以放到jar包中  
  14.         try  
  15.         {  
  16.             File file = File.createTempFile("shieldHK", ".dll");  
  17.             FileOutputStream fout = new FileOutputStream(file);  
  18.             InputStream in = ShieldHotKey.class.getResourceAsStream("shieldHK.dll");  
  19.               
  20.             byte[] b = new byte[1024];  
  21.             int len = 0;   
  22.             while((len = in.read(b)) != -1){  
  23.                 fout.write(b, 0, len);  
  24.             }  
  25.               
  26.             fout.flush();  
  27.             in.close();  
  28.             fout.close();  
  29.               
  30.             System.load(file.getAbsolutePath());  
  31.         }   
  32.         catch (Exception e) {}  
  33.           
  34. //        System.load("D:/shieldHK.dll");   
  35.     }   
  36.     public static native void Attach();//启动屏蔽   
  37.     public static native void Detach();//关闭屏蔽   
  38. }   

说明:1.ShieldHotKey是建在com.uikoo9.JLocker包下的,

            2.将原来的System.load("D:/shieldHK.dll");改写是为了增加灵活性。

 ——Eclipse自动会生成.class文件,找到它,如图:

 

——cmd下,到这个bin的这一层,输入已下命令生成.h文件:

生成的.h文件:

 

 

2VC下生成dll文件

——VC下新建一个dll工程,具体见下图:

说明:1.选择Win32 Dynamic-Link Library工程,

            2.工程名就是将来生成的dll名称,但是无关紧要可以更改。

            3.点确定之后选一个空的dll工程,完成。

 

——找到这个工程在电脑上的地方:

 

——将以下三个.h文件都复制到上面工程文件夹中

第一个.h文件:com_uikoo9_JLocker_ShieldHotKey.h,就是刚才生成的.h文件;

第二个.h文件:jni.h,在jdkinclude文件夹下;

第三个.h文件:jni_md.h,在jdkinclude文件夹下的win32文件夹中;

 

——VC中导入.h文件

FileView窗口中,右键Header Files文件夹选添加文件到目录,将上面的三个文件都导入。

 

——VC中编写cpp文件

VC中新建——文件——C++ Source File ——文件名随便起

代码如下:

[cpp] view plaincopy

  1. /* Replace "dll.h" with the name of your header */   
  2. #include "shieldHK.h"   
  3. #define _WIN32_WINNT 0x0500 //Use WH_KEYBOARD_LL   
  4. #include <windows.h>   
  5. #include <stdio.h>   
  6.   
  7. //SAS window句柄   
  8. HWND hSASWnd = NULL;   
  9. //原有SAS window回调函数地址   
  10. FARPROC FOldProc = NULL;   
  11. //起屏蔽作用的新SAS window回调函数   
  12. LRESULT CALLBACK SASWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);   
  13. //枚举所有窗体句柄的回调函数   
  14. BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam);   
  15. //Dll所创建线程的句柄   
  16. HANDLE hThread = NULL;   
  17. //Dll所创建线程的ID   
  18. DWORD dwThreadId = 0;   
  19. //Dll所创建线程的线程函数   
  20. DWORD WINAPI ThreadFunc();   
  21. //_H钩子句柄   
  22. HHOOK hHook = NULL;   
  23. //_H低级键盘钩子回调函数   
  24. LRESULT CALLBACK KeyboardProc(int,WPARAM,LPARAM);   
  25. //对外输出字符串   
  26. char szOutput[36];   
  27.   
  28. BOOL APIENTRY Attach()   
  29. {   
  30.      switch(DLL_PROCESS_ATTACH)   
  31.      {   
  32.       case DLL_PROCESS_ATTACH:   
  33.       sprintf(szOutput,"Dll成功加载于 %d 号进程。",GetCurrentProcessId());   
  34.       OutputDebugString(szOutput);   
  35.       //创建更替SAS window回调函数的线程   
  36.       if(FOldProc == NULL)   
  37.                   hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&dwThreadId);   
  38.       break;   
  39.       case DLL_PROCESS_DETACH:   
  40.       sprintf(szOutput,"Dll成功卸载。",GetCurrentProcessId());   
  41.       //MessageBox(NULL, szOutput, "ZZ", MB_ICONINFORMATION | MB_OK);   
  42.       OutputDebugString(szOutput);   
  43.       //恢复原有SAS window的回调函数   
  44.       if(FOldProc != NULL)   
  45.                 SetWindowLong(hSASWnd,GWL_WNDPROC,long(FOldProc));              
  46.       //_H卸载低级键盘钩子   
  47.       if(hHook != NULL)   
  48.       {   
  49.        if(!UnhookWindowsHookEx(hHook))   
  50.        {   
  51.         OutputDebugString("Unhook failed..");   
  52.         //__leave;   
  53.         break;   
  54.        }   
  55.        OutputDebugString("键盘钩子成功取消");   
  56.       }   
  57.       TerminateThread(hThread,1);   
  58.       CloseHandle(hThread);   
  59.       break;   
  60.       case DLL_THREAD_ATTACH:   
  61.       break;   
  62.       case DLL_THREAD_DETACH:   
  63.       break;   
  64.      }   
  65.      return TRUE;   
  66. }   
  67.   
  68. BOOL APIENTRY Detach()   
  69. {   
  70.      switch(DLL_PROCESS_DETACH)   
  71.      {   
  72.       case DLL_PROCESS_ATTACH:   
  73.       sprintf(szOutput,"Dll成功加载于 %d 号进程。",GetCurrentProcessId());   
  74.       OutputDebugString(szOutput);   
  75.       //创建更替SAS window回调函数的线程   
  76.       if(FOldProc == NULL)   
  77.                   hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&dwThreadId);   
  78.       break;   
  79.       case DLL_PROCESS_DETACH:   
  80.       sprintf(szOutput,"Dll成功卸载。",GetCurrentProcessId());   
  81.       //MessageBox(NULL, szOutput, "ZZ", MB_ICONINFORMATION | MB_OK);   
  82.       OutputDebugString(szOutput);   
  83.       //恢复原有SAS window的回调函数   
  84.       if(FOldProc != NULL)   
  85.                 SetWindowLong(hSASWnd,GWL_WNDPROC,long(FOldProc));              
  86.       //_H卸载低级键盘钩子   
  87.       if(hHook != NULL)   
  88.       {   
  89.        if(!UnhookWindowsHookEx(hHook))   
  90.        {   
  91.         OutputDebugString("Unhook failed..");   
  92.         //__leave;   
  93.         break;   
  94.        }   
  95.        OutputDebugString("键盘钩子成功取消");   
  96.       }   
  97.       TerminateThread(hThread,1);   
  98.       CloseHandle(hThread);   
  99.       break;   
  100.       case DLL_THREAD_ATTACH:   
  101.       break;   
  102.       case DLL_THREAD_DETACH:   
  103.       break;   
  104.      }   
  105.      return TRUE;   
  106. }   
  107.   
  108. //Dll所创建线程的线程函数   
  109. DWORD WINAPI ThreadFunc()   
  110. {   
  111.       //打开Winlogon桌面   
  112.       HDESK hDesk = OpenDesktop("Winlogon",0,FALSE,MAXIMUM_ALLOWED);   
  113.       //枚举桌面所有窗体   
  114.       EnumDesktopWindows(hDesk,(WNDENUMPROC)EnumWindowsProc,0);   
  115.       //修改SAS window的回调函数   
  116.       if(hSASWnd != NULL)   
  117.       {   
  118.        FOldProc = (FARPROC)SetWindowLong(hSASWnd,GWL_WNDPROC,long(SASWindowProc));   
  119.       }   
  120.       CloseHandle(hDesk);   
  121.       //_H同一桌面上进程之间只能发送窗口消息。无法跨进程与其他桌面发送它们。   
  122.       //_H同样,Windows消息是限制应用程序定义挂钩。   
  123.       //_H特定桌面中运行的进程挂钩过程将〈〈只获得针对同一桌面上创建窗口消息。〉〉   
  124.       //_H详见http://support.microsoft.com/kb/171890/zh-cn   
  125.       //_H所以,这里必须设置钩子所在线程的桌面为Default桌面   
  126.       //_H才能使得钩子所在线程能接收到Default桌面的消息   
  127.       hDesk = OpenDesktop("Default",0,FALSE,MAXIMUM_ALLOWED);   
  128.       SetThreadDesktop(hDesk);   
  129.       CloseHandle(hDesk);   
  130.       //_H设置低级键盘钩子,屏蔽非SAS window的热键   
  131.       //_H需要#define _WIN32_WINNT 0x0500   
  132.       hHook = SetWindowsHookEx(WH_KEYBOARD_LL,KeyboardProc,GetModuleHandle(NULL),0);   
  133.       if (hHook == NULL)   
  134.       {   
  135.        OutputDebugString("Set hook failed..");   
  136.        //__leave;   
  137.        return 1;   
  138.       }   
  139.       OutputDebugString("键盘钩子成功设置");   
  140.       //_H在非GUI线程中使用消息钩子必须主动接收并分发收到的消息   
  141.       MSG msg;   
  142.       while(GetMessage(&msg, NULL, 0, 0))   
  143.       {   
  144.        TranslateMessage(&msg);   
  145.        DispatchMessage(&msg);   
  146.       }   
  147.       return 1;   
  148. }   
  149.   
  150.   
  151. //枚举所有窗体句柄的回调函数   
  152. BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)   
  153. {   
  154.      char ClassBuf[128];   
  155.      //获得当前窗体的显示文本   
  156.      GetWindowText(hwnd,ClassBuf,sizeof(ClassBuf));   
  157.      //"Winlogon"桌面中查询窗口"SAS window"   
  158.      if(strstr(ClassBuf,"SAS window")!=NULL)   
  159.      {   
  160.       //返回SAS window句柄   
  161.       hSASWnd = hwnd;   
  162.       return FALSE;   
  163.      }   
  164.      return TRUE;   
  165. }   
  166.   
  167.   
  168. //起屏蔽作用的新SAS window回调函数   
  169. LRESULT CALLBACK SASWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)   
  170. {   
  171.         if(uMsg == WM_HOTKEY)   
  172.         {   
  173.          //屏蔽所有WM_HOTKEY消息   
  174.          OutputDebugString("All SAS window's hotkeys are disabled");   
  175.          return 1;   
  176.          WORD wKey = HIWORD(lParam);   
  177.          WORD wModifier = LOWORD(lParam);   
  178.          bool IsCtrlDown = ((wModifier & VK_CONTROL) != 0);   
  179.          bool IsAltDown = ((wModifier & VK_MENU) != 0);   
  180.          bool IsShiftDown = ((wModifier & VK_SHIFT) != 0);   
  181.          //Ctrl + Alt + Del组合键   
  182.          if(IsCtrlDown && IsAltDown && wKey == VK_DELETE)   
  183.          {   
  184.           return 1; //屏蔽   
  185.          }   
  186.          //Ctrl + Shift + Esc组合键,这个组合键将显示任务管理器,可根据需要是否屏蔽。   
  187.          else if(IsCtrlDown && IsShiftDown && wKey == VK_ESCAPE)   
  188.          {   
  189.           // Do nothing   
  190.          }   
  191.         }   
  192.         return CallWindowProc((WNDPROC)FOldProc,hwnd,uMsg,wParam,lParam);   
  193. }   
  194.   
  195.   
  196. //_H低级键盘钩子回调函数   
  197. LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)   
  198. {   
  199.         if (nCode == HC_ACTION)   
  200.         {   
  201.          switch (wParam)   
  202.          {   
  203.           case WM_KEYDOWN: case WM_SYSKEYDOWN:   
  204.           //case WM_KEYUP:    case WM_SYSKEYUP:   
  205.           PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;   
  206.           if (p->vkCode == VK_F12)   
  207.           {   
  208.            //实现模拟按键代码   
  209.            MessageBox(GetForegroundWindow(),"I'm in position..","ZZ",MB_OK);   
  210.           }   
  211.           //屏蔽ALT+TAB   
  212.           else if ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0))   
  213.           {   
  214.            OutputDebugString("ALT+TAB is disabled");   
  215.            return 1;   
  216.           }   
  217.           //屏蔽ALT+ESC   
  218.           else if ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0))   
  219.           {   
  220.            OutputDebugString("ALT+ESC is disabled");   
  221.            return 1;   
  222.           }   
  223.           //屏蔽CTRL+ESC   
  224.           else if ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0))   
  225.           {   
  226.            OutputDebugString("CTRL+ESC is disabled");   
  227.            return 1;   
  228.           }   
  229.           //屏蔽CTRL+SHIFT+ESC,(SAS window中也已屏蔽)   
  230.           else if ((p->vkCode == VK_ESCAPE) &&   
  231.           ((GetKeyState(VK_CONTROL) & 0x8000) != 0) &&   
  232.           ((GetKeyState(VK_SHIFT) & 0x8000) != 0))   
  233.           {   
  234.            OutputDebugString("CTRL+SHIFT+ESC is disabled");   
  235.            return 1;   
  236.           }   
  237.           //屏蔽ALT+F4   
  238.           else if ((p->vkCode == VK_F4) && ((p->flags & LLKHF_ALTDOWN) != 0))   
  239.           {   
  240.            OutputDebugString("ALT+F4 is disabled");   
  241.            return 1;   
  242.           }   
  243.           //屏蔽左右windows   
  244.           else if (p->vkCode == VK_LWIN || p->vkCode == VK_RWIN)   
  245.           {   
  246.            OutputDebugString("windows key is disabled");   
  247.            return 1;   
  248.           }   
  249.           //此处无法屏蔽CTRL+ALT+DEL,已在SAS window中屏蔽   
  250.           else if ((p->vkCode == VK_DELETE) &&   
  251.           ((GetKeyState(VK_CONTROL) & 0x8000) != 0) &&   
  252.           ((GetKeyState(VK_MENU) & 0x8000) != 0 ))   
  253.                                  return 1;   
  254.           break;   
  255.          }   
  256.         }   
  257.         return CallNextHookEx(hHook,nCode,wParam,lParam);   
  258. }   
  259.   
  260. JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Attach   
  261. (JNIEnv *env, jclass obj){   
  262. Attach();   
  263. }   
  264.   
  265. JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Detach   
  266. (JNIEnv *env, jclass obj){   
  267. Detach();   
  268. }   


 

——对几个文件的修改

com_uikoo9_JLocker_ShieldHotKey.h中的#include <jni.h>改为#include "jni.h"

test.cpp中的#include "shieldHK.h"改为#include "com_uikoo9_JLocker_ShieldHotKey.h",也就是上面的.h文件

test.cpp的末尾两个方法的代码如下:

[cpp] view plaincopy

  1. JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Attach   
  2. (JNIEnv *env, jclass obj){   
  3. Attach();   
  4. }   
  5.   
  6. JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Detach   
  7. (JNIEnv *env, jclass obj){   
  8. Detach();   
  9. }   

 

com_uikoo9_JLocker_ShieldHotKey.h中的两个方法代码如下:

[cpp] view plaincopy

  1. JNIEXPORT void JNICALL Java_com_uikoo9_JLocker_ShieldHotKey_Attach  
  2.   (JNIEnv *, jclass);  
  3.   
  4. /* 
  5.  * Class:     com_uikoo9_JLocker_ShieldHotKey 
  6.  * Method:    Detach 
  7.  * Signature: ()V 
  8.  */  
  9. JNIEXPORT void JNICALL Java_com_uikoo9_JLocker_ShieldHotKey_Detach  
  10.   (JNIEnv *, jclass);  


test.cpp中的两个方法名改为com_uikoo9_JLocker_ShieldHotKey.h中两个对应的方法名,

否则在eclipse中会报错。

 

——VC中编译cpp文件生成dll文件

test.cppCompileBuild,生成dll文件

生成的dll文件在vc项目的debug文件夹中

 

3Eclipse中使用

——testdll.dll文件改名为shieldHK.dll,复制到eclipsejava代码处,如图:

 

——编写test.java测验一下能行不,代码:

[java] view plaincopy

  1. package com.uikoo9.JLocker;  
  2.   
  3. public class Test  
  4. {  
  5.     public static void main(String[] args)  
  6.     {  
  7.         try  
  8.         {  
  9.             ShieldHotKey.Attach();  
  10.             Thread.sleep(5000);//5秒内键盘热键都被屏蔽了。  
  11.         }   
  12.         catch (Exception e) {}  
  13.     }  
  14. }  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值