最近用java GUI的swing实现了一个仿QQ截图小工具,实现了最基本的系统热键启动截图,鼠标拖动画出截图区域,或者直接窗口检测,然后保存或者复制到系统剪切板等功能。效果如图所示:
代码都放在一个.java文件中,这样子post上来方便,接着介绍代码的具体实现细节。
(1)软件所用到的第三方包有:jintellitype-1.3.9.jar(用于注册系统热键包),以及JNA的两个包(用于保存窗体层次关系):jna-4.5.0.jar,jna-platform-4.5.0.jar
用到的dll就 jintellitype.dll放到System32中就可以了,jna两个包直接引入即可。
(2)软件启动后,弹出系统热键设置:
要设置成还没有被其他软件用过的热键,比如没有启动QQ的话,那么我们可以注册ctrl+alt+A,如果QQ启动后再注册ctrl+alt+A就没有效了,点击shot就可以将窗体最小化到托盘
热键注册代码是非常简单的,只需要执行注册函数,然后加入自己的按键监听器就可以了
static final int shotHotKey = 88; //热键号随便,然后将CTRL+ALT+G注册进去 JIntellitype.getInstance().registerHotKey(shotHotKey, JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT, (int)'G')); JIntellitype.getInstance().addHotKeyListener(new GlobalHotKey()); class GlobalHotKey implements HotkeyListener { public void onHotKey(int key) { switch (key) { case shotHotKey: //开始截屏 processScreenShot(); break; default: System.exit(0); } } }
(3)启动截图处理后,要做的事情是保存当前窗体的层次关系,主要是调用User32中的一些API,便于后面的矩形检测,具体代码见文末:
HashMap<Integer, Rectangle> winLayer = null;//这个HashMap用来保存窗体的层次,最顶层的先加进去。 //然后在鼠标Motion事件中遍历这个Map,判断当前鼠标位置是否包含在某个窗体里面,如果是则在点击后就自动点亮这个区域
(4)接着是将当前窗口的全屏图像截取下来,并且标出鼠标位置,代码如下:
rb = new Robot(); rb.createScreenCapture(new Rectangle(screenSize));//得到全屏图像 //调用drawMouse函数将鼠标画到图像上 private void drawMouse(BufferedImage bi){ Graphics2D g2d = (Graphics2D)bi.getGraphics(); g2d.drawImage(bi,0,0,bi.getWidth(),bi.getHeight(),null); ImageIcon img = new ImageIcon(screenShot.class.getResource("whiteCursor.png")); Point mp = MouseInfo.getPointerInfo().getLocation(); g2d.drawImage(img.getImage(),mp.x,mp.y,img.getIconWidth(),img.getIconHeight(),null); g2d.dispose(); }
(5)接着新建一个JFrame,这个JFrame全屏,并且半透明黑色,置顶,半透明只需要在contentPane的paintComponent函数中画个有透明度的矩形黑色区域即可
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); Composite old = ((Graphics2D) g).getComposite(); ((Graphics2D) g).setComposite(ac); g.setColor(Color.BLACK); g.fillRect(0, 0, screenSize.width, screenSize.height); ((Graphics2D) g).setComposite(old);
(6)并且改变鼠标的颜色为彩色光标,彩色光标在 这里找的,下载下来后是cur,转为png即可。
(7)然后就是鼠标事件了,鼠标事件主要是press,drag,release,Motion这四个事件,press用于记录按下时的点,然后drag用于拖拽出要截图的区域,release拖拽完成,motion用来判断当前鼠标位置标亮窗体区域。
这个区域主要用start点和end点表示,start点是矩形左上角,end是矩形右下角。
由于拖拽可以往任意方向,但是drawImage这个函数可以纠正,所以鼠标往任意方向拖都可以用。
public abstract boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer);
拖出区域后,肯定需要可以支持区域修正,也就是区域可拖动,可拉伸并且支持各个方向,效果如下图所示,这些功能的实现也是在鼠标事件中完成的,具体见代码。
拉伸主要是对区域进行判断:
(8)拖动完成后可以回车复制到剪切板上,参考java图片复制到剪切板
或者保存为jpg or png or bmp文件。
(8)其他的功能:在截屏状态下按esc就可以退出。
完整代码如下:
由于用了lambda表达式,所以需要jre1.8。然后托盘图像trayIcon.png,白色光标whiteCursor.png,彩色光标是刚才的cursor.png
这里有编译好的,双击即可运行。
package screenShot; import com.melloware.jintellitype.HotkeyListener; import com.melloware.jintellitype.JIntellitype; import com.sun.jna.platform.win32.User32; import com.sun.jna.platform.win32.WinDef; import static com.sun.jna.platform.win32.WinUser.*; import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.HashMap; /** * 截屏小工具。支持系统热键。 */ public class screenShot { JFrame jf; JButton shotStart; JLabel jl; public static JTextField jtf; public screenShot() { jf = new JFrame("java screenShot"); jf.setSize(500,400); jf.setLocationRelativeTo(null); jf.setLayout(null); jf.setLocationRelativeTo(null); jl = new JLabel("HotKey = CTRL+ALT+"); jl.setBounds(50,200,150,30); jtf = new JTextField("G"); jtf.setBounds(200,200,100,30); shotStart = new JButton("shot"); shotStart.setBounds(50, 300, 100, 30); shotStart.addActionListener(new shotE()); jf.add(shotStart); jf.add(jl); jf.add(jtf); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new screenShot(); } private class shotE implements ActionListener { boolean first = false; @Override public void actionPerformed(ActionEvent e) { jf.setVisible(false); if (!first) { createTray(); setHotKey(); first = true; } } GlobalHotKey key; private void setHotKey() { key = new GlobalHotKey(); key.initHotkey(); } private void createTray() { PopupMenu pm = new PopupMenu(); MenuItem mi = new MenuItem("exit"); mi.addActionListener(e -> {JIntellitype.getInstance().unregisterHotKey(GlobalHotKey.shotHotKey);System.exit(0);}); pm.add(mi); ImageIcon img = new ImageIcon(screenShot.class.getResource("trayIcon.png")); TrayIcon ti = new TrayIcon(img.getImage(), "screenShot", pm); ti.addActionListener(e -> jf.setVisible(true)); try { SystemTray.getSystemTray().add(ti); } catch (AWTException e1) { e1.printStackTrace(); } } } } class GlobalHotKey implements HotkeyListener { HashMap<Integer, Rectangle> winLayer = null; static final int shotHotKey = 88; public volatile boolean enterBusy = false;//防止和全局热键冲突。 private String lastPath = null; public volatile boolean shotBusy = false;//防止重复截图。 public volatile boolean isProcess = false;//第一次拖拽完成后,需要进行处理,这时候需要重新利用click,drag和release函数。 /**拖拽参数**/ private static final int BREADTH = 7;//边界拉伸范围 private static final int BREADTH2 = 14;//边界拉伸范围 private int dragType; private static final int DRAG_NONE = 0; private static final int DRAG_MOVE = 1; private static final int DRAG_UP = 2; private static final int DRAG_UPLEFT = 3; private static final int DRAG_UPRIGHT = 4; private static final int DRAG_LEFT = 5; private static final int DRAG_RIGHT = 6; private static final int DRAG_BOTTOM = 7; private static final int DRAG_BOTTOMLEFT = 8; private static final int DRAG_BOTTOMRIGHT = 9; private Cursor getNewCursor(){ return Toolkit.getDefaultToolkit().createCustomCursor(new ImageIcon(screenShot.class.getResource("cursor.png")).getImage(),new Point(0,0),"myCursor"); } public void onHotKey(int key) { switch (key) { case shotHotKey: if(shotBusy) return; shotBusy = true; saveLayer();//保存窗口层次。 registerESC();//注册窗体全局热键 shotProcess(); break; default: System.exit(0); } } /**屏幕窗体层次保存**/ public void saveLayer() { User32 u32 = User32.INSTANCE; printAllNextWin(u32.GetWindow(u32.GetForegroundWindow(), new WinDef.DWORD(GW_HWNDFIRST))); } public HWND getNextWindow(HWND hWnd) { return User32.INSTANCE.GetWindow(hWnd, new DWORD(GW_HWNDNEXT)); } public boolean CheckLegal(HWND hWnd, Rectangle rt) { WINDOWINFO winInfo = new WINDOWINFO(); User32.INSTANCE.GetWindowInfo(hWnd, winInfo); int style = winInfo.dwStyle; if ((style & WS_VISIBLE) == 0) { return false;//去掉不可视窗口 } if ((style & WS_DISABLED) != 0) { return false;//去掉disable窗口 } if (rt.width < 10 || rt.height < 10) { return false;//去掉小不点窗口 } if ((style & WS_MINIMIZE)!=0) { return false;//去掉最小化状态的窗口 } if((rt.getWidth() == screenSize.getWidth()) && (rt.getHeight() == screenSize.getHeight())){ return false;//去掉底层屏幕窗口 } return true; } /** 遍历桌面所有窗体,如果是合法的就加入到winLayer **/ public void printAllNextWin(HWND h) { HashMap<Integer, Rectangle> layerInfo = new HashMap<>();//0是最高层 HWND hWnd = h; RECT r = new RECT(); int layerPos = 0; Rectangle rect; while ((hWnd = getNextWindow(hWnd)) != null) { User32.INSTANCE.GetWindowRect(hWnd, r); rect = r.toRectangle(); if (!CheckLegal(hWnd, rect)) continue; layerInfo.put(layerPos++, rect); } winLayer = layerInfo; } AWTEventListener al; private void registerESC() { al = event -> { KeyEvent ke = (KeyEvent) event; if (ke.getID() == KeyEvent.KEY_PRESSED) { if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) { //System.out.println("当前AWT事件监听器数量"+ Toolkit.getDefaultToolkit().getAWTEventListeners().length); clean(); unregisterESC(); jp.setDrag(false); } else if (ke.getKeyCode() == KeyEvent.VK_ENTER) { if(enterBusy){ return; } pastePic(); } } }; Toolkit.getDefaultToolkit().addAWTEventListener(al, AWTEvent.KEY_EVENT_MASK); } private void unregisterESC() { Toolkit.getDefaultToolkit().removeAWTEventListener(al); } JFrame jf; Cursor myCursor; myContentPane jp; BufferedImage bi; Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); private void shotProcess() { jf = new JFrame(); jf.setUndecorated(true); jf.setBounds(0, 0, screenSize.width, screenSize.height); jf.setAlwaysOnTop(true); jp = new myContentPane(this); jp.setOpaque(false); jp.setLayout(null); Robot rb = null; try { rb = new Robot(); } catch (AWTException e) { e.printStackTrace(); } bi = rb.createScreenCapture(new Rectangle(screenSize)); drawMouse(bi); img = new ImageIcon(bi); mouseEvent e = new mouseEvent(this); jp.addMouseListener(e); jp.addMouseMotionListener(e); jf.add(jp); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); myCursor = getNewCursor(); jf.setCursor(myCursor);//给系统设置彩色光标。 } /**图像添加鼠标:http://blog.csdn.net/eguid_1/article/details/52973508 **/ private void drawMouse(BufferedImage bi){ Graphics2D g2d = (Graphics2D)bi.getGraphics(); g2d.drawImage(bi,0,0,bi.getWidth(),bi.getHeight(),null); ImageIcon img = new ImageIcon(screenShot.class.getResource("whiteCursor.png")); Point mp = MouseInfo.getPointerInfo().getLocation(); g2d.drawImage(img.getImage(),mp.x,mp.y,img.getIconWidth(),img.getIconHeight(),null); g2d.dispose(); } ImageIcon img; private class myContentPane extends JPanel { GlobalHotKey ek; public myContentPane(GlobalHotKey ek) { this.ek = ek; } public volatile boolean moveFlag = false; public synchronized boolean isMove() { return moveFlag; } public synchronized void setMove(boolean f) { moveFlag = f; } public volatile boolean dragFlag = false; public synchronized boolean isDrag() { return dragFlag; } public synchronized void setDrag(boolean f) { dragFlag = f; } @Override protected void paintComponent(Graphics g) { /** * 设置透明度 https://wenku.baidu.com/view/d90f110d227916888486d7ee.html */ if (img != null) g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this); AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); Composite old = ((Graphics2D) g).getComposite(); ((Graphics2D) g).setComposite(ac); g.setColor(Color.BLACK); g.fillRect(0, 0, screenSize.width, screenSize.height); ((Graphics2D) g).setComposite(old); g.drawImage(img.getImage(), start.x, start.y, end.x, end.y, start.x, start.y, end.x, end.y, this); g.setColor(new Color(2, 169, 255)); if (isMove()) { Stroke oldS = ((Graphics2D) g).getStroke(); ((Graphics2D) g).setStroke(new BasicStroke(4.0f)); g.drawRect(start.x, start.y, end.x - start.x, end.y - start.y); ((Graphics2D) g).setStroke(oldS); setMove(false); } else { drawBound(g); } super.paintComponent(g); } Point myStart = new Point(0, 0); public void correctMyStart() { if ((start.x <= end.x) && (start.y <= end.y)) { myStart.x = start.x; myStart.y = start.y; } else if ((start.x <= end.x) && (start.y > end.y)) { //右上角 myStart.x = start.x; myStart.y = end.y; } else if ((start.x > end.x) && (start.y <= end.y)) { //左下角 myStart.x = end.x; myStart.y = start.y; } else { myStart.x = end.x; myStart.y = end.y; } } int offset = 3; int[][] point; private void drawBound(Graphics g) { myStart = new Point(0, 0); /**纠正反方向错误**/ correctMyStart(); g.drawRect(myStart.x, myStart.y, Math.abs(end.x - start.x), Math.abs(end.y - start.y)); point = new int[][]{{start.x, start.y}, {(start.x + end.x) / 2, start.y}, {end.x, start.y}, {end.x, (start.y + end.y) / 2}, {end.x, end.y}, {(start.x + end.x) / 2, end.y}, {start.x, end.y}, {start.x, (start.y + end.y) / 2}}; for (int i = 0; i < point.length; i++) g.fillRect(point[i][0] - offset, point[i][1] - offset, 2 * offset, 2 * offset); } } Point start = new Point(0, 0), end = new Point(0, 0); Point prePos,startCopy,endCopy; /** * 根据矩形的start和end两点裁剪出要截取的图形。 */ private BufferedImage clipArea(){ BufferedImage shotArea = new BufferedImage(end.x - start.x, end.y - start.y, BufferedImage.TYPE_INT_RGB); Graphics g = shotArea.getGraphics(); g.drawImage(bi, 0, 0, end.x - start.x, end.y - start.y, start.x, start.y, end.x, end.y, null); return shotArea; } /** * 将图像复制到系统剪贴板上 **/ private void pastePic() { /**将图片复制到剪贴板,参考链接:http://blog.csdn.net/u010982856/article/details/44747029**/ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new Images((new ImageIcon(clipArea())).getImage()), null); clean(); } private void clean() { jf.dispose(); shotBusy = false; isProcess = false; start = new Point(0, 0); end = new Point(0, 0); } private class mouseEvent extends MouseAdapter { GlobalHotKey ss; public mouseEvent(GlobalHotKey screenShot) { this.ss = screenShot; } private void typeSel(MouseEvent e){ Point p = e.getPoint(); if(new Rectangle(start.x-BREADTH,start.y-BREADTH,end.x-start.x+BREADTH2,end.y-start.y+BREADTH2).contains(p)){ /**在区域内部**/ }else{ /**如果不在内部,就结束**/ isProcess = false; pressPro(e); } } public void mousePressed(MouseEvent e) { if(isProcess){ /** * 在处理状态下press时,记录press的点,作为起点。 */ prePos = e.getPoint(); startCopy = new Point(start); endCopy = new Point(end); typeSel(e); }else{ pressPro(e); } } private void pressPro(MouseEvent e){ isSelExist(); start = e.getPoint(); end = new Point(start.x,start.y); ss.jp.setDrag(true); ss.jp.updateUI(); } public void mouseReleased(MouseEvent e) { if(isProcess){ jf.setCursor(myCursor); /**修正在反方向拖动时的区域修正及更新面板**/ correctDir(); reLocateSel(); return; }else{ releaseProcess(e); } } private void releaseProcess(MouseEvent e){ /** 如果只有点击没有拖拽,就进行窗体检测。 **/ if (!isDrag) { Rectangle r; for (int i = 0; i < winLayer.size(); i++) { r = winLayer.get(i); if (r.contains(e.getPoint())) { //System.out.println("当前在矩形"+i+"中"); start.x = r.getX() >= 0 ? (int) r.getX() : 0; start.y = r.getY() >= 0 ? (int) r.getY() : 0; end.x = start.x + (int) r.getWidth(); end.y = start.y + (int) r.getHeight(); ss.jp.updateUI();//这个必须要。 break; } } } correctDir(); isSelExist(); createSel(); isDrag = false; isProcess = true; /** * 进入处理状态,如果在指定区域内再次点击,就是拖拽拉伸。 */ } private void reLocateSel(){ Point refP; //判断按钮会不会超出屏幕 if ((end.y + 30) >= screenSize.getHeight()) { refP = new Point(end.x, start.y - 30); } else { refP = new Point(end.x, end.y); } selPanel.setBounds(refP.x-150,refP.y+10,150,20); selPanel.updateUI(); } private void createSel() { Point refP; //判断按钮会不会超出屏幕,上下左右方位都应该判断。 /***还不完善,左下角会挡住。***/ if ((end.y + 30) >= screenSize.getHeight()) { refP = new Point(end.x, start.y - 30); } else { refP = new Point(end.x, end.y); } selPanel = new JPanel(null); selPanel.setBounds(refP.x-150,refP.y+10,150,20); ok = new JButton("Y"); ok.setBounds(100, 0, 50, 20); ok.addActionListener(e -> { pastePic(); ss.jp.setDrag(false); }); cancel = new JButton("N"); cancel.setBounds(50, 0, 50, 20); cancel.addActionListener(e -> { clean(); ss.jp.setDrag(false); }); save = new JButton("S"); save.addActionListener(e->{savePic();}); save.setBounds(0, 0, 50, 20); selPanel.add(ok); selPanel.add(cancel); selPanel.add(save); ss.jp.add(selPanel); ss.jp.updateUI(); } private void savePic(){ enterBusy = true; if(File.separator.equals("\\"))//判断是windows系统 try { UIManager.setLookAndFeel(com.sun.java.swing.plaf.windows.WindowsLookAndFeel.class.getName()); } catch (Exception e1) { e1.printStackTrace(); } JFileChooser jfc = new JFileChooser(lastPath); jfc.setDialogTitle("Save"); jfc.removeChoosableFileFilter(jfc.getAcceptAllFileFilter());//去除"所有文件"项 jfc.addChoosableFileFilter(new FileNameExtensionFilter("PNG (*.png)","png")); jfc.addChoosableFileFilter(new FileNameExtensionFilter("BMP (*.bmp)","bmp")); jfc.addChoosableFileFilter(new FileNameExtensionFilter("JPEG (*.jpg;*.jpeg)","jpg")); int retVal = jfc.showSaveDialog(jf); if(retVal == JFileChooser.APPROVE_OPTION){ File f = jfc.getSelectedFile(); lastPath = jfc.getCurrentDirectory().getAbsolutePath(); //System.out.println("lastPath changes="+lastPath); FileNameExtensionFilter ff = (FileNameExtensionFilter)jfc.getFileFilter();//得到当前的文件过滤器 String[] extendList = ff.getExtensions(); String extendName = null; int i; //System.out.println("list length is "+extendList.length); for(i=0;i<extendList.length;i++){ /**如果f扩展名在扩展名列表中就break,否则自动加上,默认第一个**/ if(f.getName().endsWith(extendList[i])){ extendName = extendList[i]; break; } } if(i == extendList.length){ extendName = extendList[0]; f = new File(f.getAbsolutePath()+"."+extendName); } //System.out.println("save as="+f.getName()+" extension = "+extendName); try { ImageIO.write(clipArea(),extendName,f); } catch (IOException e) { e.printStackTrace(); } } if(File.separator.equals("\\"))//判断是windows系统 try { UIManager.setLookAndFeel(javax.swing.plaf.metal.MetalLookAndFeel.class.getName()); } catch (Exception e1) { e1.printStackTrace(); } clean(); enterBusy = false; } private void isSelExist() { ss.jp.removeAll(); ss.jp.updateUI(); } JPanel selPanel; JButton ok = null, cancel = null, save = null; public volatile boolean isDrag = false; public void mouseDragged(MouseEvent e) { if(isProcess){ /** * 判断拖拽拉伸类型,然后处理。 */ dragPro(e); }else{ /**获取的新的拖拽点必须加工后才能送到绘图板。**/ end = e.getPoint(); ss.jp.updateUI();//这个必须要。 isDrag = true; } } private void dragPro(MouseEvent e){ Point curPos = e.getPoint(); switch(dragType){ case DRAG_MOVE: start.x = startCopy.x+curPos.x- prePos.x; start.y = startCopy.y+curPos.y-prePos.y; end.x = endCopy.x+curPos.x- prePos.x; end.y = endCopy.y+curPos.y-prePos.y; break; case DRAG_UPLEFT: /** start更新为拖动点 **/ start = new Point(curPos); break; case DRAG_UP: /** 只需要更新start.y **/ start.y = curPos.y; break; case DRAG_UPRIGHT: /** 只需要更新start.y和end.x**/ start.y = curPos.y; end.x = curPos.x; break; case DRAG_RIGHT: end.x = curPos.x; break; case DRAG_BOTTOMRIGHT: end = new Point(curPos); break; case DRAG_BOTTOM: end.y = curPos.y; break; case DRAG_BOTTOMLEFT: start.x = curPos.x; end.y = curPos.y; break; case DRAG_LEFT: start.x = curPos.x; break; default: } reLocateSel(); ss.jp.updateUI(); } /** * 纠正方向使得start始终是矩形左上角,stop始终是矩形右下角。 **/ private void correctDir() { Point p; //一共四个方向。 //右下角 if ((start.x <= end.x) && (start.y <= end.y)) { return; } else if ((start.x <= end.x) && (start.y > end.y)) { //右上角 p = new Point(start); start.y = end.y; end.y = p.y; } else if ((start.x > end.x) && (start.y <= end.y)) { //左下角 p = new Point(end); end.y = start.y; start.y = p.y; swap(); } else { swap(); } } private void swap() { Point p = start; start = end; end = p; } @Override public void mouseMoved(MouseEvent e) { /**鼠标移动自动判断当前哪个矩形中**/ if(isProcess){ Point p = e.getPoint(); if(new Rectangle(start.x-BREADTH, start.y-BREADTH,BREADTH2,BREADTH2).contains(p)){ /**stretch upper-left**/ dragType = DRAG_UPLEFT; jf.setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR)); }else if(new Rectangle(start.x+BREADTH, start.y-BREADTH,end.x-start.x-BREADTH2,BREADTH2).contains(p)){ /**stretch upper**/ dragType = DRAG_UP; jf.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR)); }else if(new Rectangle(end.x-BREADTH, start.y-BREADTH,BREADTH2,BREADTH2).contains(p)){ /**stretch upper-right**/ dragType = DRAG_UPRIGHT; jf.setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR)); }else if(new Rectangle(end.x-BREADTH, start.y+BREADTH,BREADTH2,end.y-start.y-BREADTH2).contains(p)){ /**stretch right**/ dragType = DRAG_RIGHT; jf.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR)); }else if(new Rectangle(end.x-BREADTH, end.y-BREADTH,BREADTH2,BREADTH2).contains(p)){ /**stretch bottom-right**/ dragType = DRAG_BOTTOMRIGHT; jf.setCursor(new Cursor(Cursor.SE_RESIZE_CURSOR)); }else if(new Rectangle(start.x+BREADTH, end.y-BREADTH,end.x-start.x-BREADTH2,BREADTH2).contains(p)){ /**stretch bottom**/ dragType = DRAG_BOTTOM; jf.setCursor(new Cursor(Cursor.S_RESIZE_CURSOR)); }else if(new Rectangle(start.x-BREADTH, end.y-BREADTH,BREADTH2,BREADTH2).contains(p)){ /**stretch bottom-left**/ dragType = DRAG_BOTTOMLEFT; jf.setCursor(new Cursor(Cursor.SW_RESIZE_CURSOR)); }else if(new Rectangle(start.x-BREADTH, start.y+BREADTH,BREADTH2,end.y-start.y-BREADTH2).contains(p)){ /**stretch left**/ dragType = DRAG_LEFT; jf.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR)); }else if(new Rectangle(start.x,start.y,end.x-start.x,end.y-start.y).contains(p)){ /**如果在矩形内部,那么就是拖动**/ dragType = DRAG_MOVE; jf.setCursor(new Cursor(Cursor.MOVE_CURSOR)); }else{ dragType = DRAG_NONE; jf.setCursor(myCursor); } return; } if (ss.jp.isDrag()) { return; } Rectangle r; for (int i = 0; i < winLayer.size(); i++) { r = winLayer.get(i); if (r.contains(e.getPoint())) { //System.out.println("当前在矩形"+i+"中"); start.x = r.getX() >= 0 ? (int) r.getX() : 0; start.y = r.getY() >= 0 ? (int) r.getY() : 0; end.x = start.x + (int) r.getWidth(); end.y = start.y + (int) r.getHeight(); ss.jp.setMove(true); ss.jp.updateUI();//这个必须要。 return;//无须往下搜索。 } } } } public class Images implements Transferable { private Image image; //得到图片或者图片流 public Images(Image image) { this.image = image; } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{DataFlavor.imageFlavor}; } public boolean isDataFlavorSupported(DataFlavor flavor) { return DataFlavor.imageFlavor.equals(flavor); } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (!DataFlavor.imageFlavor.equals(flavor)) { throw new UnsupportedFlavorException(flavor); } return image; } } void initHotkey() { JIntellitype.getInstance().registerHotKey(shotHotKey, JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT, (int)(screenShot.jtf.getText().toCharArray()[0])); JIntellitype.getInstance().addHotKeyListener(this); } }