Java JNA-Jar应用程序在32位Windows系统中挂起

时间:2015-10-19 06:23:00

标签: java jframe 32bit-64bit jna keyhook

这是一个屏幕截图应用程序。使用 1.8 JDK 编译,在64位系统中运行良好,但在32位系统中的两次迭代中滞后和挂起。

基本上这个应用程序使用机器人类获取屏幕截图,从用户获取文件名,这是一个URL。截断并删除所有非法字符,并使用带有时间戳作为前缀的另存为对话框进行保存。

我正在使用 Windows低级KeyHook PrtSc 键启动屏幕截图。

32位系统出错: 它只需要2个屏幕截图,然后在第3次按 PrtSc 时没有响应。 JFrame可以导致任何问题,它肯定加载缓慢。我应该使用除JFrame之外的任何备用文本框,还是因为我已经在java 1.8 jdk 64位环境中编写,这在jdk或32位系统的低版本中无法使用。

public class KeyHook {
private static HHOOK hhk;
private static LowLevelKeyboardProc keyboardHook;
static JFileChooser fileChooser = new JFileChooser();
public static void main(String[] args) {
    final User32 lib = User32.INSTANCE;
    HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
    keyboardHook = new LowLevelKeyboardProc() {
        public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
            if (nCode >= 0) {
                switch(wParam.intValue()) {
                case WinUser.WM_KEYUP:
                case WinUser.WM_KEYDOWN:
                case WinUser.WM_SYSKEYUP:
                case WinUser.WM_SYSKEYDOWN:

                 if (info.vkCode == 44) { 


                        try {

                            Robot robot = new Robot();
                            // Capture the screen shot of the area of the screen defined by the rectangle
                             BufferedImage bi=robot.createScreenCapture(new Rectangle(0,25,1366,744));

                             JFrame frame = new JFrame();
                             JFrame.setDefaultLookAndFeelDecorated(true);
                             frame.toFront();
                             frame.requestFocus();
                             frame.setAlwaysOnTop(true);
                             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                             // prompt the user to enter their name
                             String name = JOptionPane.showInputDialog(frame, "Enter file name");
                            // frame.pack();

                             frame.dispose();
                             String fileName= dovalidateFile(name);

                             FileNameExtensionFilter filter = new FileNameExtensionFilter("PNG", ".png");
                               fileChooser.setFileFilter(filter);
                             fileChooser.setSelectedFile(new File (fileName));


                             int returnVal = fileChooser.showSaveDialog(null);
                             if ( returnVal == JFileChooser.APPROVE_OPTION ){

                                File file = fileChooser.getSelectedFile();


                                 file = validateFile(file);
                                 System.out.println(file);
                                 ImageIO.write(bi, "png", file);

                             }



                      }
                        catch (NullPointerException e1)
                        {e1.printStackTrace(); }
                        catch (AWTException e1) {
                            e1.printStackTrace();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    }
                    }
                }

            return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
        }

        private File validateFile(File file) {
            DateFormat dateFormat = new SimpleDateFormat("HH.mm.ss.ddMMMMMyyyy");
               //get current date time with Calendar()
               Calendar cal = Calendar.getInstance();
              // System.out.println(dateFormat.format(cal.getTime()));
            String filePath = file.getAbsolutePath();

            if (filePath.indexOf(".png") == -1) {
                filePath += "." + dateFormat.format(cal.getTime()) + ".png";
            }
            //System.out.println("File Path :" + filePath);
            file = new File(filePath);
            if (file.exists()) {
                file.delete();
            }
            try {
                file.createNewFile();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return file;

                    }

        private String dovalidateFile(String name) {

            String input = name.replace("https://www.","");  
            input = input.replaceAll("http://www.","");   
            input = input.replaceAll("https://","");    
            input = input.replace("http://","");
            input = input.replace("/?",".");
            input = input.replace("/",".");
            input = input.replace("|",".") ;
            input = input.replace("%",".");
            input = input.replace("<",".");
            input = input.replace(">",".");
            input = input.replaceAll("\\?",".");
            input = input.replaceAll("\\*",".");
            input = input.replace(":",".");
            input = input.replace("\\",".");
            input = Character.toUpperCase(input.charAt(0)) + input.substring(1);
            return input;
        } 
    };
    hhk = lib.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL, keyboardHook, hMod, 0);

    if(!SystemTray.isSupported()){
        return ;
    }
    SystemTray systemTray = SystemTray.getSystemTray();
    Image image = Toolkit.getDefaultToolkit().getImage(KeyHook.class.getResource("/images/icon.png"));

    //popupmenu
    PopupMenu trayPopupMenu = new PopupMenu();

    MenuItem close = new MenuItem("Exit");
    close.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.err.println("unhook and exit");
            lib.UnhookWindowsHookEx(hhk);
            System.exit(0);

        }
    });
    trayPopupMenu.add(close);

    //setting tray icon
    TrayIcon trayIcon = new TrayIcon(image, "captur", trayPopupMenu);
    //adjust to default size as per system recommendation 
    trayIcon.setImageAutoSize(true);

    try{
        systemTray.add(trayIcon);
    }catch(AWTException awtException){
        awtException.printStackTrace();
    }

    int result;
    MSG msg = new MSG();
    while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
        if (result == -1) {
            System.err.println("error in get message");
            break;
        }
        else {
            System.err.println("got message");
            lib.TranslateMessage(msg);
            lib.DispatchMessage(msg);
        }
      }
         lib.UnhookWindowsHookEx(hhk);

    }
 }

1 个答案:

答案 0 :(得分:1)

我没有JNA的任何经验,但是你的代码有几个问题 - 我不认为我得到了所有这些,但是这里有一些:

  1. close.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
    
        System.exit(0);   
        quit=true;
    }
    });
    

    quit=true将永远无法联系到exit(),因为您的计划 new Thread() { public void run() { while (!quit) { try { Thread.sleep(10); } catch(Exception e) { } } System.err.println("unhook and exit"); lib.UnhookWindowsHookEx(hhk); System.exit(0); } }.start(); 才会到达那里。

  2. 2。
    quit

    没有任何意义,因为true永远不会是ActionListener。同时旋转变量以检测变化将严重降低应用程序的速度(特别是睡眠时间为10毫秒)。为什么不在 while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) { 中取消挂钩?

      3。
      null

      我不太确定,因为我没有JNA和Windows事件系统的经验。该方法等待发送到指定窗口的消息,但由于您没有指定任何消息(第二个参数是JFrame),我认为您永远不会得到消息。

      1. 对于每个回调,您创建一个新的frame.setVisible(false);,但在方法结束时,您只能使用frame.dispose()隐藏它。由于它仍然是从各种Swing类引用的,因此它永远不会被垃圾收集。这会造成内存泄漏,从而降低应用程序的速度。您必须致电toDateString()才能摆脱它。