123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #include "putty.h"
- #if HAVE_DWMAPI_H
- #include <dwmapi.h>
- char *save_screenshot(HWND hwnd, Filename *outfile)
- {
- HDC dcWindow = NULL, dcSave = NULL;
- HBITMAP bmSave = NULL;
- uint8_t *buffer = NULL;
- char *err = NULL;
- static HMODULE dwmapi_module;
- DECL_WINDOWS_FUNCTION(static, HRESULT, DwmGetWindowAttribute,
- (HWND, DWORD, PVOID, DWORD));
- if (!dwmapi_module) {
- dwmapi_module = load_system32_dll("dwmapi.dll");
- GET_WINDOWS_FUNCTION(dwmapi_module, DwmGetWindowAttribute);
- }
- dcWindow = GetDC(NULL);
- if (!dcWindow) {
- err = dupprintf("GetDC(window): %s", win_strerror(GetLastError()));
- goto out;
- }
- int x, y, w, h;
- RECT wr;
- /* Use DwmGetWindowAttribute in place of GetWindowRect to exclude
- * drop shadow, otherwise we get a load of unwanted desktop
- * background under the shadow */
- if (p_DwmGetWindowAttribute &&
- 0 <= p_DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS,
- &wr, sizeof(wr))) {
- x = wr.left;
- y = wr.top;
- w = wr.right - wr.left;
- h = wr.bottom - wr.top;
- } else {
- BITMAP bmhdr;
- memset(&bmhdr, 0, sizeof(bmhdr));
- GetObject(GetCurrentObject(dcWindow, OBJ_BITMAP),
- sizeof(bmhdr), &bmhdr);
- x = y = 0;
- w = bmhdr.bmWidth;
- h = bmhdr.bmHeight;
- }
- dcSave = CreateCompatibleDC(dcWindow);
- if (!dcSave) {
- err = dupprintf("CreateCompatibleDC(desktop window dc): %s",
- win_strerror(GetLastError()));
- goto out;
- }
- bmSave = CreateCompatibleBitmap(dcWindow, w, h);
- if (!bmSave) {
- err = dupprintf("CreateCompatibleBitmap: %s",
- win_strerror(GetLastError()));
- goto out;
- }
- if (!SelectObject(dcSave, bmSave)) {
- err = dupprintf("SelectObject: %s", win_strerror(GetLastError()));
- goto out;
- }
- if (!BitBlt(dcSave, 0, 0, w, h, dcWindow, x, y, SRCCOPY)) {
- err = dupprintf("BitBlt: %s", win_strerror(GetLastError()));
- goto out;
- }
- BITMAPINFO bmInfo;
- memset(&bmInfo, 0, sizeof(bmInfo));
- bmInfo.bmiHeader.biSize = sizeof(bmInfo.bmiHeader);
- bmInfo.bmiHeader.biWidth = w;
- bmInfo.bmiHeader.biHeight = h;
- bmInfo.bmiHeader.biPlanes = 1;
- bmInfo.bmiHeader.biBitCount = 32;
- bmInfo.bmiHeader.biCompression = BI_RGB;
- size_t bmPixels = (size_t)w*h, bmBytes = bmPixels * 4;
- buffer = snewn(bmBytes, uint8_t);
- if (!GetDIBits(dcWindow, bmSave, 0, h, buffer, &bmInfo, DIB_RGB_COLORS))
- err = dupprintf("GetDIBits (get data): %s",
- win_strerror(GetLastError()));
- FILE *fp = f_open(outfile, "wb", false);
- if (!fp) {
- err = dupprintf("'%s': unable to open file", filename_to_str(outfile));
- goto out;
- }
- BITMAPFILEHEADER bmFileHdr;
- bmFileHdr.bfType = 'B' | ('M' << 8);
- bmFileHdr.bfSize = sizeof(bmFileHdr) + sizeof(bmInfo.bmiHeader) + bmBytes;
- bmFileHdr.bfOffBits = sizeof(bmFileHdr) + sizeof(bmInfo.bmiHeader);
- fwrite((void *)&bmFileHdr, 1, sizeof(bmFileHdr), fp);
- fwrite((void *)&bmInfo.bmiHeader, 1, sizeof(bmInfo.bmiHeader), fp);
- fwrite((void *)buffer, 1, bmBytes, fp);
- fclose(fp);
- out:
- if (dcWindow)
- ReleaseDC(NULL, dcWindow);
- if (bmSave)
- DeleteObject(bmSave);
- if (dcSave)
- DeleteObject(dcSave);
- sfree(buffer);
- return err;
- }
- #else /* HAVE_DWMAPI_H */
- /* Without <dwmapi.h> we can't get the right window rectangle */
- char *save_screenshot(HWND hwnd, Filename *outfile)
- {
- return dupstr("Demo screenshots not compiled in to this build");
- }
- #endif /* HAVE_DWMAPI_H */
|