火狐浏览器没有这个功能。您能做的最好的事情就是通过以下方式使用操作系统功能js-ctypes https://developer.mozilla.org/en/js-ctypes。然而,事情并不那么简单。无论如何,我需要这段用于 Windows API 的代码,所以它来了。首先,您需要设置库、函数和数据类型:
Components.utils.import("resource://gre/modules/ctypes.jsm");
var userlib = ctypes.open("user32");
var gdilib = ctypes.open("gdi32");
var HWND = ctypes.voidptr_t;
var HGDIOBJ = ctypes.voidptr_t;
var HDC = HGDIOBJ;
var HBITMAP = HGDIOBJ;
var LPCTSTR = ctypes.unsigned_char.ptr;
var WORD = ctypes.uint16_t;
var DWORD = ctypes.uint32_t;
var SRCCOPY = 0xCC0020;
var BITMAPCOREHEADER = ctypes.StructType("BITMAPCOREHEADER", [
{bcSize: DWORD},
{bcWidth: WORD},
{bcHeight: WORD},
{bcPlanes: WORD},
{bcBitCount: WORD}
]);
var GetDC = userlib.declare(
"GetDC", ctypes.winapi_abi,
HDC,
HWND
);
var ReleaseDC = userlib.declare(
"ReleaseDC", ctypes.winapi_abi,
ctypes.int,
HWND, HDC
);
var CreateCompatibleDC = gdilib.declare(
"CreateCompatibleDC", ctypes.winapi_abi,
HDC,
HDC
);
var CreateCompatibleBitmap = gdilib.declare(
"CreateCompatibleBitmap", ctypes.winapi_abi,
HBITMAP,
HDC, ctypes.int, ctypes.int
);
var DeleteObject = gdilib.declare(
"DeleteObject", ctypes.winapi_abi,
ctypes.bool,
HGDIOBJ
);
var SelectObject = gdilib.declare(
"SelectObject", ctypes.winapi_abi,
HGDIOBJ,
HDC, HGDIOBJ
);
var BitBlt = gdilib.declare(
"BitBlt", ctypes.winapi_abi,
ctypes.bool,
HDC, ctypes.int, ctypes.int, ctypes.int, ctypes.int,
HDC, ctypes.int, ctypes.int, DWORD
);
var GetDIBits = gdilib.declare(
"GetDIBits", ctypes.winapi_abi,
ctypes.int,
HDC, HBITMAP, ctypes.unsigned_int, ctypes.unsigned_int,
ctypes.unsigned_char.ptr, BITMAPCOREHEADER.ptr, ctypes.unsigned_int
);
现在有趣的部分是:
// The screen part we want to copy
var x = 0;
var y = 0;
var width = screen.width;
var height = screen.height;
// Create a bitmap/device context for the data
var screenDC = GetDC(null);
var dc = CreateCompatibleDC(screenDC);
var bitmap = CreateCompatibleBitmap(screenDC, width, height);
// Copy screen contents to bitmap
SelectObject(dc, bitmap);
BitBlt(dc, 0, 0, width, height, screenDC, x, y, SRCCOPY);
// Extract bitmap data
var bitmapHeader = new BITMAPCOREHEADER();
bitmapHeader.bcSize = BITMAPCOREHEADER.size;
bitmapHeader.bcWidth = width;
bitmapHeader.bcHeight = height;
bitmapHeader.bcPlanes = 1;
bitmapHeader.bcBitCount = 32;
var dataSize = width * height * 4;
var buffer = new ctypes.ArrayType(ctypes.unsigned_char, dataSize)();
GetDIBits(dc, bitmap, 0, height, buffer, bitmapHeader.address(), 0);
// Clean up
ReleaseDC(null, screenDC);
DeleteObject(dc);
DeleteObject(bitmap);
userlib.close();
gdilib.close();
// Draw data to the canvas
var canvas = document.getElementById("canvas");
canvas.setAttribute("width", width);
canvas.setAttribute("height", height);
var context = canvas.getContext("2d");
var imageData = context.createImageData(width, height);
for (var i = 0; i < height; i++)
{
// Windows bitmaps are stored bottom-to-top, they are also using BGR0
// byte order instead of RGBA. The data needs to be corrected here.
var offset1 = i * width * 4;
var offset2 = (height - 1 - i) * width * 4;
for (var j = 0; j < width; j++)
{
imageData.data[offset1 + j * 4 + 0] = buffer[offset2 + j * 4 + 2];
imageData.data[offset1 + j * 4 + 1] = buffer[offset2 + j * 4 + 1];
imageData.data[offset1 + j * 4 + 2] = buffer[offset2 + j * 4 + 0];
imageData.data[offset1 + j * 4 + 3] = 255;
}
}
context.putImageData(imageData, 0, 0);
对于其他操作系统,您当然需要完全不同的代码。另一种方法是用你的扩展打包一个专门的 DLL,并通过 js-ctypes 使用它 - 这将允许用 C++ 编写相同的东西,这会稍微简单一些。