歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java運用JNI調用dll(含源碼)實現屏蔽系統熱鍵和任務欄

由於功能和代碼我是分開去實現的,所以這裡代碼步驟也分開附上。

首先,屏蔽系統熱鍵

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頭文件。
在命令行裡敲指令進入到編譯生成的 classes 文件夾裡,輸入 javah shieldHK.ShieldHotKey生成頭文件。
5、用VC6.0編寫生成dll文件。
  5-1、新建一個dll工程,把剛生成的頭文件 shieldHK.h 引入
  頭文件代碼如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class shieldHK_ShieldHotKey */

#ifndef _Included_shieldHK_ShieldHotKey
#define _Included_shieldHK_ShieldHotKey
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:    shieldHK_ShieldHotKey
* Method:    Attach
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Attach
(JNIEnv *, jclass);

/*
* Class:    shieldHK_ShieldHotKey
* Method:    Detach
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Detach
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif
  5-2、編寫 shieldHK.cpp 文件
  代碼如下:
/* Replace "dll.h" with the name of your header */
#include "shieldHK.h"
#define _WIN32_WINNT 0x0500 //Use WH_KEYBOARD_LL
#include <windows.h>
#include <stdio.h>

//SAS window句柄
HWND hSASWnd = NULL;
//原有SAS window回調函數地址
FARPROC FOldProc = NULL;
//起屏蔽作用的新SAS window回調函數
LRESULT CALLBACK SASWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
//枚舉所有窗體句柄的回調函數
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam);
//Dll所創建線程的句柄
HANDLE hThread = NULL;
//Dll所創建線程的ID
DWORD dwThreadId = 0;
//Dll所創建線程的線程函數
DWORD WINAPI ThreadFunc();
//_H鉤子句柄
HHOOK hHook = NULL;
//_H低級鍵盤鉤子回調函數
LRESULT CALLBACK KeyboardProc(int,WPARAM,LPARAM);
//對外輸出字符串
char szOutput[36];

BOOL APIENTRY Attach()
{
    switch(DLL_PROCESS_ATTACH)
    {
      case DLL_PROCESS_ATTACH:
      sprintf(szOutput,"Dll成功加載於 %d 號進程。",GetCurrentProcessId());
      OutputDebugString(szOutput);
      //創建更替SAS window回調函數的線程
      if(FOldProc == NULL)
                  hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&dwThreadId);
      break;
      case DLL_PROCESS_DETACH:
      sprintf(szOutput,"Dll成功卸載。",GetCurrentProcessId());
      //MessageBox(NULL, szOutput, "ZZ", MB_ICONINFORMATION | MB_OK);
      OutputDebugString(szOutput);
      //恢復原有SAS window的回調函數
      if(FOldProc != NULL)
                SetWindowLong(hSASWnd,GWL_WNDPROC,long(FOldProc));           
      //_H卸載低級鍵盤鉤子
      if(hHook != NULL)
      {
      if(!UnhookWindowsHookEx(hHook))
      {
        OutputDebugString("Unhook failed..");
        //__leave;
        break;
      }
      OutputDebugString("鍵盤鉤子成功取消");
      }
      TerminateThread(hThread,1);
      CloseHandle(hThread);
      break;
      case DLL_THREAD_ATTACH:
      break;
      case DLL_THREAD_DETACH:
      break;
    }
    return TRUE;
}

BOOL APIENTRY Detach()
{
    switch(DLL_PROCESS_DETACH)
    {
      case DLL_PROCESS_ATTACH:
      sprintf(szOutput,"Dll成功加載於 %d 號進程。",GetCurrentProcessId());
      OutputDebugString(szOutput);
      //創建更替SAS window回調函數的線程
      if(FOldProc == NULL)
                  hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&dwThreadId);
      break;
      case DLL_PROCESS_DETACH:
      sprintf(szOutput,"Dll成功卸載。",GetCurrentProcessId());
      //MessageBox(NULL, szOutput, "ZZ", MB_ICONINFORMATION | MB_OK);
      OutputDebugString(szOutput);
      //恢復原有SAS window的回調函數
      if(FOldProc != NULL)
                SetWindowLong(hSASWnd,GWL_WNDPROC,long(FOldProc));           
      //_H卸載低級鍵盤鉤子
      if(hHook != NULL)
      {
      if(!UnhookWindowsHookEx(hHook))
      {
        OutputDebugString("Unhook failed..");
        //__leave;
        break;
      }
      OutputDebugString("鍵盤鉤子成功取消");
      }
      TerminateThread(hThread,1);
      CloseHandle(hThread);
      break;
      case DLL_THREAD_ATTACH:
      break;
      case DLL_THREAD_DETACH:
      break;
    }
    return TRUE;
}

//Dll所創建線程的線程函數
DWORD WINAPI ThreadFunc()
{
      //打開Winlogon桌面
      HDESK hDesk = OpenDesktop("Winlogon",0,FALSE,MAXIMUM_ALLOWED);
      //枚舉桌面所有窗體
      EnumDesktopWindows(hDesk,(WNDENUMPROC)EnumWindowsProc,0);
      //修改SAS window的回調函數
      if(hSASWnd != NULL)
      {
      FOldProc = (FARPROC)SetWindowLong(hSASWnd,GWL_WNDPROC,long(SASWindowProc));
      }
      CloseHandle(hDesk);
      //_H同一桌面上進程之間只能發送窗口消息。無法跨進程與其他桌面發送它們。
      //_H同樣,Windows消息是限制應用程序定義掛鉤。
      //_H特定桌面中運行的進程掛鉤過程將〈〈只獲得針對同一桌面上創建窗口消息。〉〉
      //_H詳見http://support.microsoft.com/kb/171890/zh-cn
      //_H所以,這裡必須設置鉤子所在線程的桌面為Default桌面
      //_H才能使得鉤子所在線程能接收到Default桌面的消息
      hDesk = OpenDesktop("Default",0,FALSE,MAXIMUM_ALLOWED);
      SetThreadDesktop(hDesk);
      CloseHandle(hDesk);
      //_H設置低級鍵盤鉤子,屏蔽非SAS window的熱鍵
      //_H需要#define _WIN32_WINNT 0x0500
      hHook = SetWindowsHookEx(WH_KEYBOARD_LL,KeyboardProc,GetModuleHandle(NULL),0);
      if (hHook == NULL)
      {
      OutputDebugString("Set hook failed..");
      //__leave;
      return 1;
      }
      OutputDebugString("鍵盤鉤子成功設置");
      //_H在非GUI線程中使用消息鉤子必須主動接收並分發收到的消息
      MSG msg;
      while(GetMessage(&msg, NULL, 0, 0))
      {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      }
      return 1;
}


//枚舉所有窗體句柄的回調函數
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
    char ClassBuf[128];
    //獲得當前窗體的顯示文本
    GetWindowText(hwnd,ClassBuf,sizeof(ClassBuf));
    //在"Winlogon"桌面中查詢窗口"SAS window"。
    if(strstr(ClassBuf,"SAS window")!=NULL)
    {
      //返回SAS window句柄
      hSASWnd = hwnd;
      return FALSE;
    }
    return TRUE;
}


//起屏蔽作用的新SAS window回調函數
LRESULT CALLBACK SASWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
        if(uMsg == WM_HOTKEY)
        {
        //屏蔽所有WM_HOTKEY消息
        OutputDebugString("All SAS window's hotkeys are disabled");
        return 1;
        WORD wKey = HIWORD(lParam);
        WORD wModifier = LOWORD(lParam);
        bool IsCtrlDown = ((wModifier & VK_CONTROL) != 0);
        bool IsAltDown = ((wModifier & VK_MENU) != 0);
        bool IsShiftDown = ((wModifier & VK_SHIFT) != 0);
        //Ctrl + Alt + Del組合鍵
        if(IsCtrlDown && IsAltDown && wKey == VK_DELETE)
        {
          return 1; //屏蔽
        }
        //Ctrl + Shift + Esc組合鍵,這個組合鍵將顯示任務管���器,可根據需要是否屏蔽。
        else if(IsCtrlDown && IsShiftDown && wKey == VK_ESCAPE)
        {
          // Do nothing
        }
        }
        return CallWindowProc((WNDPROC)FOldProc,hwnd,uMsg,wParam,lParam);
}


//_H低級鍵盤鉤子回調函數
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
        if (nCode == HC_ACTION)
        {
        switch (wParam)
        {
          case WM_KEYDOWN: case WM_SYSKEYDOWN:
          //case WM_KEYUP:    case WM_SYSKEYUP:
          PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
          if (p->vkCode == VK_F12)
          {
          //實現模擬按鍵代碼
          MessageBox(GetForegroundWindow(),"I'm in position..","ZZ",MB_OK);
          }
          //屏蔽ALT+TAB
          else if ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0))
          {
          OutputDebugString("ALT+TAB is disabled");
          return 1;
          }
          //屏蔽ALT+ESC
          else if ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0))
          {
          OutputDebugString("ALT+ESC is disabled");
          return 1;
          }
          //屏蔽CTRL+ESC
          else if ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0))
          {
          OutputDebugString("CTRL+ESC is disabled");
          return 1;
          }
          //屏蔽CTRL+SHIFT+ESC,(SAS window中也已屏蔽)
          else if ((p->vkCode == VK_ESCAPE) &&
          ((GetKeyState(VK_CONTROL) & 0x8000) != 0) &&
          ((GetKeyState(VK_SHIFT) & 0x8000) != 0))
          {
          OutputDebugString("CTRL+SHIFT+ESC is disabled");
          return 1;
          }
          //屏蔽ALT+F4
          else if ((p->vkCode == VK_F4) && ((p->flags & LLKHF_ALTDOWN) != 0))
          {
          OutputDebugString("ALT+F4 is disabled");
          return 1;
          }
          //屏蔽左右windows鍵
          else if (p->vkCode == VK_LWIN || p->vkCode == VK_RWIN)
          {
          OutputDebugString("windows key is disabled");
          return 1;
          }
          //此處無法屏蔽CTRL+ALT+DEL,已在SAS window中屏蔽
          else if ((p->vkCode == VK_DELETE) &&
          ((GetKeyState(VK_CONTROL) & 0x8000) != 0) &&
          ((GetKeyState(VK_MENU) & 0x8000) != 0 ))
                                return 1;
          break;
        }
        }
        return CallNextHookEx(hHook,nCode,wParam,lParam);
}

JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Attach
(JNIEnv *env, jclass obj){
Attach();
}

JNIEXPORT void JNICALL Java_shieldHK_ShieldHotKey_Detach
(JNIEnv *env, jclass obj){
Detach();
}
  5-3、編譯生成 shieldHK.dll 文件
最後 shieldHK.dll 就可以在 ShieldHotKey 類裡調用了。比如Attach()跟Detach();

至於去掉任務欄與上面的步驟是一樣的
在這裡附上C++代碼:
/* Replace "dll.h" with the name of your header */
#include "registerHK.h"
#include <windows.h>
#include <cstdlib>
#include <iostream>

using namespace std;

void HideTaskBar(BOOL bHide);

void HideTaskBar(BOOL bHide)
{
int nCmdShow;
HWND hWnd;
LPARAM lParam;

hWnd = FindWindow("Shell_TrayWnd",NULL);
if(bHide == TRUE)
{
nCmdShow = SW_HIDE;
lParam = ABS_AUTOHIDE | ABS_ALWAYSONTOP;
}
else
{
nCmdShow = SW_SHOW;
lParam = ABS_ALWAYSONTOP;
}

ShowWindow(hWnd,nCmdShow);//隱藏任務欄

#ifndef ABM_SETSTATE
#define ABM_SETSTATE 0x0000000a
#endif


APPBARDATA apBar;
memset(&apBar, 0, sizeof(apBar));
apBar.cbSize = sizeof(apBar);
apBar.hWnd = hWnd;
if(apBar.hWnd != NULL)
{
apBar.lParam = lParam;
SHAppBarMessage(ABM_SETSTATE, &apBar); //設置任務欄自動隱藏
}
}

JNIEXPORT void JNICALL Java_shieldHK_RegisterHotKey_HideTaskBar
(JNIEnv *env, jclass obj, jboolean b){
HideTaskBar(b);
}

OK,全部搞定。

編寫高質量代碼 改善Java程序的151個建議 PDF高清完整版 http://www.linuxidc.com/Linux/2014-06/103388.htm

Java 8簡明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm

Java對象初始化順序的簡單驗證 http://www.linuxidc.com/Linux/2014-02/96220.htm

Java對象值傳遞和對象傳遞的總結 http://www.linuxidc.com/Linux/2012-12/76692.htm

Java對象序列化ObjectOutputStream和ObjectInputStream示例 http://www.linuxidc.com/Linux/2012-08/68360.htm

Copyright © Linux教程網 All Rights Reserved