java鼠标钩子的运用

java鼠标钩子的运用去年寒假回家闲着无事,就在家中敲敲代码。主要是用java语言写一些小的运用:放大镜,屏幕截图简单画图工具、取色器什么的,,最后整合成一个小型的软件。不过在这个过程中,发现java中实现屏幕截图、取色的时候对于鼠标的操作还是显得有些不够,上面的功能一般是事先得到整个屏幕,之后再在该图片上操作。这使得界面软件必须处于激活状态,很不方便。   其实,采用上面的那种操作实现功能也并不

      去年寒假回家闲着无事,就在家中敲敲代码。主要是用java语言写一些小的运用:放大镜,屏幕截图

简单画图工具、取色器什么的,,最后整合成一个小型的软件。不过在这个过程中,发现java中实现屏幕

截图、取色的时候对于鼠标的操作还是显得有些不够,上面的功能一般是事先得到整个屏幕,之后再

在该图片上操作。这使得界面软件必须处于激活状态,很不方便。

      其实,采用上面的那种操作实现功能也并不见得有多不好,不过兴趣使然,想看看java借助一些第

三方jar能否实现与windows底层的交互。因此,上网查了一下,总结如下:

      通过查找,了解到了可以通过”鼠标钩子”实现,何为”钩子”,下面为”扒来的”:

           钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗
      口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之
      前处理它。钩子机制允许应用程序截获处理window消息或特定事件。钩子实际上是一个处理消息的程
      序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达       目的窗口前,钩子程序就
       先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以
       不作处理而继续传递该消息,还可以强制结束消息的传递。
             Hook API是指Windows开放给程序员的编程接口,使得在用户级别下可以对操作系统进行控制,
       也就是一般的应用程序都需要调用API来完成某些功能,Hook API的意思就是在这些应用程序调用
       真正的系统API前可以先被截获,从而进行一些处理再调用真正的API来完成功能。
                 1) 键盘钩子和低级键盘钩子可以监视各种键盘消息。 
              (2) 鼠标钩子和低级鼠标钩子可以监视各种鼠标消息。 
              (3) 外壳钩子可以监视各种Shell事件消息。比如启动和关闭应用程序。 
              (4) 日志钩子可以记录从系统消息队列中取出的各种事件消息。 
              (5) 窗口过程钩子监视所有从系统消息队列发往目标窗口的消息
        说了这么多概念性的东西,但是我们怎样用java实现鼠标钩子呢?
            这就需要借助jna来操作了
                 JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。
 既然知道了实现的方法,那就动手吧,下面是我实现的代码,当然也有借鉴网上这方面的资料.
 MouseLLHook.java
package com.kiritor;

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.*;
import com.sun.jna.platform.win32.WinUser.*;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.KBDLLHOOKSTRUCT;
import com.sun.jna.platform.win32.WinUser.LowLevelKeyboardProc;

public class MouseLLHook {

	
	private boolean flag;
	public ColorFrame getColorFrame() {
		return colorFrame;
	}


	public void setColorFrame(ColorFrame colorFrame) {
		this.colorFrame = colorFrame;
	}

	private static ColorFrame colorFrame = null;
	// 鼠标钩子函数里判断按键类型的常数
	public static Point mousepoint;
	public static MouseInfo mouseInfo = null;
	static Color pixel = new Color(0, 0, 0);
	static Integer R = 0, G = 0, B = 0;
	static Integer X = 0, Y = 0;
	public static final int WM_LBUTTONUP = 514;
	public static final int WM_LBUTTONDOWN = 513;
	public static final int WM_RBUTTONUP = 517;
	public static final int WM_RBUTTONDOWN = 516;
	public static final int WM_MOUSEHWHEEL = 526;
	public static final int WM_MOUSEWHEEL = 522;
	public static final int WM_MOUSEMOVE = 512;

	static HHOOK mouseHHK, keyboardHHK;// 鼠标、键盘钩子的句柄
	static LowLevelMouseProc mouseHook;// 鼠标钩子函数
	static LowLevelKeyboardProc keyboardHook;// 键盘钩子函数
    public MouseLLHook(ColorFrame colorFrame)
    {
	   this.colorFrame=colorFrame;
    }
	
	
	// 安装钩子
	static void setHook() {
		HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
		mouseHHK = User32.INSTANCE.SetWindowsHookEx(WinUser.WH_MOUSE_LL,
				mouseHook, hMod, 0);
		mouseHHK.nativeType();
		keyboardHHK = User32.INSTANCE.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL,
				keyboardHook, hMod, 0);
	}

	// 卸载钩子
	static void unhook() {
		User32.INSTANCE.UnhookWindowsHookEx(keyboardHHK);
		User32.INSTANCE.UnhookWindowsHookEx(mouseHHK);
	}

	public  void getColor(String[] args) {

		keyboardHook = new LowLevelKeyboardProc() {

			@Override
			// 该函数参数的意思参考:http://msdn.microsoft.com/en-us/library/windows/desktop/ms644985(v=vs.85).aspx
			public LRESULT callback(int nCode, WPARAM wParam,
					KBDLLHOOKSTRUCT lParam) {
				int w = wParam.intValue();
				// 按下alt键时w=.WM_SYSKEYDOWN; 按下其他大部分键时w=WinUser.WM_KEYDOWN
				if (w == WinUser.WM_KEYDOWN || w == WinUser.WM_SYSKEYDOWN)
					System.out.println("key down: vkCode = " + lParam.vkCode);
				else if (w == WinUser.WM_KEYUP || w == WinUser.WM_SYSKEYUP)
					System.out.println("key up: vkCode = " + lParam.vkCode);

				// 如果按下'q'退出程序,'q'的vkCode是81
				if (lParam.vkCode == 81) {
					unhook();
					System.err.println("program terminated.");
					System.exit(0);
				}
				return User32.INSTANCE.CallNextHookEx(keyboardHHK, nCode,
						wParam, lParam.getPointer());
			}
		};

		mouseHook = new LowLevelMouseProc() {

			@Override
			// 该函数参数的意思参考:http://msdn.microsoft.com/en-us/library/windows/desktop/ms644986(v=vs.85).aspx
			public LRESULT callback(int nCode, WPARAM wParam,
					MOUSEHOOKSTRUCT lParam) {
				switch (wParam.intValue()) {
				case WM_MOUSEMOVE:
					//System.out.print("mouse moved:");
					break;
				case WM_LBUTTONDOWN: {
					try {
						
						Robot robot = new Robot();
						mousepoint = mouseInfo.getPointerInfo().getLocation();
						// System.out.println(mousepoint);
						pixel = robot.getPixelColor(mousepoint.x, mousepoint.y);
						X = mousepoint.x;
						Y = mousepoint.y;
						R = pixel.getRed();
						G = pixel.getGreen();
						B = pixel.getBlue();
				
						String s16 = "#" + Integer.toHexString(R)
								+ Integer.toHexString(G)
								+ Integer.toHexString(B);// 得到颜色的十六进制表示。
					
						Color col = new Color(R, G, B);
						
						if(colorFrame.isFlag()==false)
						{
							colorFrame.getRedText().setText(R.toString());
							colorFrame.getGreenText().setText(G.toString());
							colorFrame.getBlueText().setText(B.toString());
							colorFrame.getColor16Text().setText(s16);
							colorFrame.getNewColor().setBackground(col);
						    colorFrame.setFlag(true);
						}
						
						colorFrame.setVisible(true);
					} catch (AWTException ex) {
						ex.printStackTrace();
					}
				}
					break;
				case WM_LBUTTONUP:
					//System.out.print("mouse left button up");
					break;
				case WM_RBUTTONUP:
					//System.out.print("mouse right button up:");
					break;
				case WM_RBUTTONDOWN:
					//System.out.print("mouse right button down:");
					break;
				case WM_MOUSEWHEEL:
					//System.out.print("mouse wheel rotated:");
					break;
				}
				//System.out.println("(" + lParam.pt.x + "," + lParam.pt.y + ")");
				return User32.INSTANCE.CallNextHookEx(mouseHHK, nCode, wParam,
						lParam.getPointer());
			}
		};

		setHook();

		int result;
		MSG msg = new MSG();
		// 消息循环
		// 实际上while循环一次都不执行,这些代码的作用我理解是让程序在GetMessage函数这里阻塞,不然程序就结束了。
		while ((result = User32.INSTANCE.GetMessage(msg, null, 0, 0)) != 0) {
			if (result == -1) {
				System.err.println("error in GetMessage");
				unhook();
				break;
			} else {
				User32.INSTANCE.TranslateMessage(msg);
				User32.INSTANCE.DispatchMessage(msg);
			}
		}
		unhook();
	}

}

package com.kiritor;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HOOKPROC;
import com.sun.jna.platform.win32.WinUser.POINT;

interface LowLevelMouseProc extends HOOKPROC {
    LRESULT callback(int nCode, WPARAM wParam, MOUSEHOOKSTRUCT lParam);
}

public class MOUSEHOOKSTRUCT extends Structure {
    public class ByReference extends MOUSEHOOKSTRUCT implements
            Structure.ByReference {
    };

    public POINT pt;
    public HWND hwnd;
    public int wHitTestCode;
    public ULONG_PTR dwExtraInfo;
}  

ColorFrame.java

package com.kiritor;

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;

public class ColorFrame extends JWindow {
	
	private boolean flag= false;
	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	private JLabel color16 = null;
	private JLabel color16Text = null;
	private JLabel red = null;
	private JLabel redText = null;
	private JLabel green = null;
	private JLabel greenText = null;
	private JLabel blue = null;
	private JLabel blueText = null;
	private JPanel newColor = null;
	private JLabel newLabel = null;
	private int xx;
	private int yy;
	private boolean isDraging;
	private TrayIcon trayIcon;
	private JPanel bgJPanel = null;
	private ImageIcon bg = new ImageIcon(getClass().getClassLoader()
			.getResource("images/bg.png"));

	/**
	 * 剪贴板工作区
	 */
	// 复制到剪贴板的按钮
	private JLabel jiantieban = null;
	private ImageIcon jiantiebanIcon = new ImageIcon(getClass()
			.getClassLoader().getResource("images/jiantieban.png"));

	private ImageIcon jiantiebanIcon_entered = new ImageIcon(getClass()
			.getClassLoader().getResource("images/jiantieban_entered.png"));
	// 重新取色的按钮

	private JLabel getAgain = null;
	private ImageIcon getAgainIcon = new ImageIcon(getClass().getClassLoader()
			.getResource("images/getagain.png"));
	private ImageIcon getAgainIcon_entered = new ImageIcon(getClass()
			.getClassLoader().getResource("images/getagain_entered.png"));

	// 取消操作的按钮

	private JLabel cancel = null;

	private ImageIcon cancelIcon = new ImageIcon(getClass().getClassLoader()
			.getResource("images/cancel.png"));
	private ImageIcon cancel_entered = new ImageIcon(getClass()
			.getClassLoader().getResource("images/cancel_entered.png"));

	public ColorFrame(){}
	
	public ColorFrame(int x,int y) {
		setLocation(x, y);
	}

	public void showUI() {
		init();

		setSize(150, 150);
		setLayout(null);
		setAlwaysOnTop(true);
		addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				requestFocus();
				isDraging = true;
				xx = e.getX();
				yy = e.getY();
			}

			public void mouseReleased(MouseEvent e) {
				isDraging = false;
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
				// TODO Auto-generated method stub
				setFlag(true);//窗体内部暂时设置为不能取色
			}
		});
		addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseDragged(MouseEvent e) {
				if (isDraging) {
					int left = getLocation().x;
					int top = getLocation().y;
					setLocation(left + e.getX() - xx, top + e.getY() - yy);
				}
			}
		});

		setVisible(true);
		//
		// TestEvent t = new TestEvent(this);
		// t.setLayout(null);
		// t.add(bgJPanel);
		// this.getContentPane().add( t);
		add(bgJPanel);
		//setLocationRelativeTo(null);

	}

	public void init() {

		bgJPanel = new JPanel() {
			public void paintComponent(Graphics g) {
				super.paintComponent(g);
				g.drawImage(bg.getImage(), 0, 0, null);
				this.setOpaque(false);
			}
		};
		bgJPanel.setOpaque(false);
		bgJPanel.setLayout(null);
		bgJPanel.setBounds(0, 0, 150, 150);

		newColor = new JPanel();
		newLabel = new JLabel("颜色");
		newLabel.setFont(new Font("华文楷体", 0, 12));
		newLabel.setBounds(30, 10, 30, 20);
		newColor.setBounds(20, 35, 50, 50);
		newColor.setBackground(Color.gray);

		red = new JLabel("Red:");
		red.setFont(new Font("华文楷体", 0, 12));
		red.setBounds(80, 35, 30, 10);

		redText = new JLabel("sdf");
		redText.setFont(new Font("华文楷体", 0, 12));
		redText.setBounds(115, 35, 30, 10);
		green = new JLabel("Green:");
		green.setFont(new Font("华文楷体", 0, 12));
		green.setBounds(80, 53, 40, 10);
		greenText = new JLabel("sdf");
		greenText.setFont(new Font("华文楷体", 0, 12));
		greenText.setBounds(115, 53, 30, 10);
		blue = new JLabel("Blue:");
		blue.setFont(new Font("华文楷体", 0, 12));
		blue.setBounds(80, 71, 30, 10);
		blueText = new JLabel("sdf");
		blueText.setFont(new Font("华文楷体", 0, 12));
		blueText.setBounds(115, 71, 30, 10);

		color16 = new JLabel("十六进制:");
		color16.setBounds(20, 95, 45, 10);
		color16.setFont(new Font("华文楷体", 0, 10));
		color16Text = new JLabel("#aaaa");
		color16Text.setBounds(70, 95, 60, 10);
		color16Text.setFont(new Font("华文楷体", 0, 12));
		color16Text.setForeground(Color.red);

		/** 工作区按钮初始化的地方 */
        //剪贴板操作
		jiantieban = new JLabel(jiantiebanIcon_entered);
		jiantieban.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
				
				setClipboard(color16Text.getText());
			   
			}
		
			@Override
			public void mouseEntered(MouseEvent e) {
				// TODO Auto-generated method stub
				jiantieban.setIcon(jiantiebanIcon);
				setFlag(true);
			}
		
			@Override
			public void mouseExited(MouseEvent e) {
				// TODO Auto-generated method stub
				jiantieban.setIcon(jiantiebanIcon_entered);
			  
			}
		});
		jiantieban.setBounds(10, 115, 40, 20);

		//重新拾取操作
		getAgain = new JLabel(getAgainIcon_entered);
		getAgain.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
				setFlag(false);

	            setVisible(false);
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				// TODO Auto-generated method stub
				getAgain.setIcon(getAgainIcon);
				
			}

			@Override
			public void mouseExited(MouseEvent e) {
				// TODO Auto-generated method stub
				getAgain.setIcon(getAgainIcon_entered);
			}
		});
		getAgain.setBounds(55, 115, 40, 20);
		
		//取消操作按钮的操作
		cancel = new JLabel(cancel_entered);
		cancel.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				setVisible(false);
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				// TODO Auto-generated method stub
				cancel.setIcon(cancelIcon);
				
			}

			@Override
			public void mouseExited(MouseEvent e) {
				// TODO Auto-generated method stub
				cancel.setIcon(cancel_entered);
			}
		});
		cancel.setBounds(100, 115, 40, 20);
		
		
		bgJPanel.add(newLabel);
		bgJPanel.add(newColor);
		bgJPanel.add(red);
		bgJPanel.add(redText);
		bgJPanel.add(green);
		bgJPanel.add(greenText);
		bgJPanel.add(blue);
		bgJPanel.add(blueText);
		bgJPanel.add(color16);
		bgJPanel.add(color16Text);
		bgJPanel.add(jiantieban);
		bgJPanel.add(getAgain);
		bgJPanel.add(cancel);
		
	}

	public JPanel getNewColor() {
		return newColor;
	}

	public void setNewColor(JPanel newColor) {
		this.newColor = newColor;
	}

	public JLabel getColor16Text() {
		return color16Text;
	}

	public void setColor16Text(JLabel color16Text) {
		this.color16Text = color16Text;
	}

	public JLabel getRedText() {
		return redText;
	}

	public void setRedText(JLabel redText) {
		this.redText = redText;
	}

	public JLabel getGreenText() {
		return greenText;
	}

	public void setGreenText(JLabel greenText) {
		this.greenText = greenText;
	}

	public JLabel getBlueText() {
		return blueText;
	}

	public void setBlueText(JLabel blueText) {
		this.blueText = blueText;
	}

	public  void getColor(String[] args) {
		
		
		new MouseLLHook(this).getColor(null);
	}
	public static void main(String[] args) {
		ColorFrame colorFrame = new ColorFrame();
		colorFrame.showUI();
		MouseLLHook hook = new MouseLLHook(colorFrame);
		hook.getColor(null);
	}
	/*复制到剪贴板中去*/
	public  void setClipboard(String str) 
	{  
  	StringSelection ss = new StringSelection(str);  
  	Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);  
  } 
}

由于一些图片文件丢失,界面效果图就不贴了!
该程序要用到的jar包

  http://download.csdn.net/detail/kiritor/5115277
 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/35427.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注