没有人知道如何捕捉到Java中的屏幕截图(不是它自己的屏幕,但任何其他窗口在桌面上,他们 并不 一定是 积极的
窗口)在Windows?关于这个相似的主题,这里有很多话题,但是我还没有找到答案。
我曾尝试使用JNA,但经过几次尝试却陷入困境。例如…
public class Main {
public static void main(String[] args) {
Main m = new Main();
List<WindowInfo> list = m.getWindows();
for (int i=0;i<list.size();i++)
{
WindowInfo info = list.get(i);
System.out.println(info.getTitle());
}
WindowInfo wi = list.get(0);
W32API.HDC hdcSrc = User32.instance.GetWindowDC(wi.getHwnd());
W32API.HDC hdcMemory = Gdi32.instance.CreateCompatibleDC(hdcSrc);
//W32API.HBITMAP hBitmapMemory = Gdi32.instance.CreateCompatibleBitmap(hdcSrc, int width, int height);
int width = wi.getRect().right - wi.getRect().left;
int height = wi.getRect().bottom - wi.getRect().top;
W32API.HBITMAP hBitmapMemory = Gdi32.instance.CreateCompatibleBitmap(hdcSrc, width, height);
W32API.HANDLE hOld = Gdi32.instance.SelectObject(hdcMemory, hBitmapMemory);
Gdi32.instance.BitBlt(hdcMemory, 0, 0, width, height, hdcSrc, width+2, height+2, 0x00CC0020);
/* # now how do we convert to a BufferedImage??? */
// clean up
Gdi32.instance.SelectObject(hdcMemory, hOld);
Gdi32.instance.DeleteDC(hdcMemory);
Gdi32.instance.DeleteObject(hBitmapMemory);
User32.instance.ReleaseDC(wi.getHwnd(), hdcSrc);
}
/**
*
* @return
*/
private List<WindowInfo> getWindows() {
final List<WindowInfo> list = new ArrayList<WindowInfo>();
User32.instance.EnumWindows(new WndEnumProc() {
public boolean callback(int hWnd, int lParam) {
if (User32.instance.IsWindowVisible(hWnd)) {
RECT r = new RECT();
User32.instance.GetWindowRect(hWnd, r);
byte[] buffer = new byte[1024];
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
String title = Native.toString(buffer);
if (title!=null&&title.length()>0) {
list.add(new WindowInfo(hWnd, r, title));
}
}
return true;
}
}, 0);
Collections.sort(list, new Comparator<WindowInfo>() {
public int compare(WindowInfo o1, WindowInfo o2) {
int i1 = (o1.getTitle()!=null&&o1.getTitle().length()>0?o1.getTitle():" ").charAt(0);
int i2 = (o2.getTitle()!=null&&o2.getTitle().length()>0?o2.getTitle():" ").charAt(0);
return i1 - i2;
}
});
return list;
}
}
我也尝试过使用等效于“ PrintWindow()” API的方法…
Graphics g = form.CreateGraphics();
Bitmap bmp = new Bitmap(form.Size.Width, form.Size.Height, g);
Graphics memoryGraphics = Graphics.FromImage(bmp);
IntPtr dc = memoryGraphics.GetHdc();
bool success = PrintWindow(form.Handle, dc, 0);
memoryGraphics.ReleaseHdc(dc);
// bmp now contains the screenshot
还是我必须使用JNI或任何其他工具?
这是一个工作示例。
无法将捕获到的应用程序最小化,但不需要集中精力或放在顶部(即可见)。
相关C#线程,MSDN文章“ 捕获映像”和jmemoryeditorw中提供的代码提供了必要的部分。
该代码使用GetDC和GetClientRect捕获窗口的客户区。如果要捕获包括窗口装饰在内的整个窗口,可以将它们替换为GetWindowDC和GetWindowRect。
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import jna.extra.GDI32Extra;
import jna.extra.User32Extra;
import jna.extra.WinGDIExtra;
import com.sun.jna.Memory;
import com.sun.jna.platform.win32.GDI32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HBITMAP;
import com.sun.jna.platform.win32.WinDef.HDC;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.platform.win32.WinGDI;
import com.sun.jna.platform.win32.WinGDI.BITMAPINFO;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public class Paint extends JFrame {
public BufferedImage capture(HWND hWnd) {
HDC hdcWindow = User32.INSTANCE.GetDC(hWnd);
HDC hdcMemDC = GDI32.INSTANCE.CreateCompatibleDC(hdcWindow);
RECT bounds = new RECT();
User32Extra.INSTANCE.GetClientRect(hWnd, bounds);
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
HBITMAP hBitmap = GDI32.INSTANCE.CreateCompatibleBitmap(hdcWindow, width, height);
HANDLE hOld = GDI32.INSTANCE.SelectObject(hdcMemDC, hBitmap);
GDI32Extra.INSTANCE.BitBlt(hdcMemDC, 0, 0, width, height, hdcWindow, 0, 0, WinGDIExtra.SRCCOPY);
GDI32.INSTANCE.SelectObject(hdcMemDC, hOld);
GDI32.INSTANCE.DeleteDC(hdcMemDC);
BITMAPINFO bmi = new BITMAPINFO();
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
Memory buffer = new Memory(width * height * 4);
GDI32.INSTANCE.GetDIBits(hdcWindow, hBitmap, 0, height, buffer, bmi, WinGDI.DIB_RGB_COLORS);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
image.setRGB(0, 0, width, height, buffer.getIntArray(0, width * height), 0, width);
GDI32.INSTANCE.DeleteObject(hBitmap);
User32.INSTANCE.ReleaseDC(hWnd, hdcWindow);
return image;
}
public static void main(String[] args) {
new Paint();
}
BufferedImage image;
public Paint() {
HWND hWnd = User32.INSTANCE.FindWindow(null, "Untitled - Notepad");
this.image = capture(hWnd);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setExtendedState(MAXIMIZED_BOTH);
setVisible(true);
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(image, 20, 40, null);
}
}
我必须定义一些不包含在platform.jar中的额外功能(可以在JNA网站上找到)。
package jna.extra;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.GDI32;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HDC;
import com.sun.jna.win32.W32APIOptions;
public interface GDI32Extra extends GDI32 {
GDI32Extra INSTANCE = (GDI32Extra) Native.loadLibrary("gdi32", GDI32Extra.class, W32APIOptions.DEFAULT_OPTIONS);
public boolean BitBlt(HDC hObject, int nXDest, int nYDest, int nWidth, int nHeight, HDC hObjectSource, int nXSrc, int nYSrc, DWORD dwRop);
}
package jna.extra;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HDC;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.win32.W32APIOptions;
public interface User32Extra extends User32 {
User32Extra INSTANCE = (User32Extra) Native.loadLibrary("user32", User32Extra.class, W32APIOptions.DEFAULT_OPTIONS);
public HDC GetWindowDC(HWND hWnd);
public boolean GetClientRect(HWND hWnd, RECT rect);
}
package jna.extra;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinGDI;
public interface WinGDIExtra extends WinGDI {
public DWORD SRCCOPY = new DWORD(0x00CC0020);
}
提前谢了。
问题内容: 我正在Mac OS X上使用python和matplotlib。当我在许多不同的窗口上工作时,必须运行生成绘图的脚本,绘图窗口始终在活动窗口后面打开,并且非常沮丧,不得不在两个窗口之间切换以查看图像。为什么要确定绘图窗口的位置和/或将其弹出为前景窗口? 谢谢 问题答案: 完全相同的问题困扰着我。我终于找到了解决方案(在pylab模式下,带有qt4agg后端): 要么 问候,马库斯
问题内容: 我是GUI编程的新手,但需要创建一个多窗口GUI。有谁知道在线上有什么好的教程,或者您能显示一个可以启动2个窗口的简单代码吗? 问题答案: 只需创建两个JFrame对象,如下所示:
问题内容: 我刚刚使用突触软件包系统在Ubuntu 9.10中安装了matplotlib。但是,当我尝试以下简单示例时 我没有绘图窗口。关于如何显示绘图窗口的任何想法? 问题答案: 您可以输入 或更好,请使用。 由于 不再建议使用,因此如今的解决方案是
我在这里遵循GLUT教程。我将第一个示例“YAT”复制并粘贴到xcode中,稍微修改了包含,发现出现了一个空白窗口。未修改的代码设置为显示线框茶壶。对我来说,这不会发生。 但是,如果我取消对创建金牛座的注释,则金牛座和茶壶的一部分会出现在窗口中。在//draw下,似乎还有一些随机的非注释行和注释行的组合,它们实际上会导致对象出现……或者只是一个空白屏幕。 P、 我知道每个人都说不要使用GLUT,但
窗口的创建与控制 进程:主进程 1 //在主进程中. 2 const {BrowserWindow} = require('electron') 3 4 //或者从渲染器进程中使用 `remote`. 5 // const {BrowserWindow} = require('electron').remote 6 7 let win = new BrowserWindow({width