void GetVirtualDesktopRect(RECT &rect) { // 获取虚拟桌面的尺寸和位置 rect.left = GetSystemMetrics(SM_XVIRTUALSCREEN); rect.top = GetSystemMetrics(SM_YVIRTUALSCREEN); rect.right = rect.left + GetSystemMetrics(SM_CXVIRTUALSCREEN); rect.bottom = rect.top + GetSystemMetrics(SM_CYVIRTUALSCREEN); } HBITMAP GetBitmap(RECT &rect, HDC hDC) { HDC hMemDC; int x, y; int nWidth, nHeight; HBITMAP hBitmap, hOldBitmap; hMemDC = CreateCompatibleDC(hDC); // RECT rect; // GetVirtualDesktopRect(rect); hBitmap = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top); hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hDC, rect.left, rect.top, SRCCOPY); hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); return hBitmap; } std::vector SaveBitmapToBuffer(HBITMAP hBitmap) { WORD wBitCount; // 位图中每个像素所占字节数 // 定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数 DWORD dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten; BITMAP Bitmap; // 位图属性结构 BITMAPFILEHEADER bmfHdr; // 位图文件头结构 BITMAPINFOHEADER bi; // 位图信息头结构 LPSTR lpbk, lpmem; wBitCount = 32; // 设置位图信息头结构 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = Bitmap.bmWidth; bi.biHeight = -Bitmap.bmHeight; // 为负,正向的位图;为正,倒向的位图 bi.biPlanes = 1; bi.biBitCount = wBitCount; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; // 设置位图文件头 bmfHdr.bfType = 0x4D42; // "BM" dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize; bmfHdr.bfSize = dwDIBSize; bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); std::vector data; data.resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize); auto buffer = data.data(); // 写入位图文件头 // WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); // 写入位图信息头 // WriteFile(fh, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwWritten, NULL); memcpy(buffer, &bmfHdr, sizeof(BITMAPFILEHEADER)); buffer += sizeof(BITMAPFILEHEADER); memcpy(buffer, &bi, sizeof(BITMAPINFOHEADER)); buffer += sizeof(BITMAPINFOHEADER); // 获取位图阵列 if (!GetBitmapBits(hBitmap, dwBmBitsSize, buffer)) return {}; // 正向的内存图象数据 if (std::all_of(buffer, buffer + dwBmBitsSize, std::bind(std::equal_to(), std::placeholders::_1, 0))) return {}; // for (int i = 0; i < Bitmap.bmHeight; i++) // { // memcpy(buffer + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + Bitmap.bmWidth * i * 4, lpmem + Bitmap.bmWidth * (Bitmap.bmHeight - i - 1) * 4, Bitmap.bmWidth * 4); // } // 写位图数据 // WriteFile(fh, lpbk, dwBmBitsSize, &dwWritten, NULL); return data; } DECLARE_API void gdi_screenshot(HWND hwnd, RECT rect, void (*cb)(byte *, size_t)) { if (rect.bottom == rect.top || rect.left == rect.right) return; if (!hwnd) hwnd = GetDesktopWindow(); auto hdc = GetDC(hwnd); if (!hdc) return; auto bm = GetBitmap(rect, hdc); auto bf = std::move(SaveBitmapToBuffer(bm)); if (bf.size()) cb(bf.data(), bf.size()); DeleteObject(bm); ReleaseDC(hwnd, hdc); } DECLARE_API void maximum_window(HWND hwnd) { RECT rect; GetVirtualDesktopRect(rect); MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); }