去年寒假回家闲着无事,就在家中敲敲代码。主要是用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包

转载于:https://blog.51cto.com/kiritor/1226759