mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
bc7e06c494
Using a new screenshot-taking module I just added in windows/utils, these new options allow me to start up one of the tools with demonstration window contents and automatically save a .BMP screenshot to disk. This will allow me to keep essentially the same set of demo images and update them easily to keep pace with the current appearance of the real tools as PuTTY - and Windows itself - both evolve.
127 lines
3.6 KiB
C
127 lines
3.6 KiB
C
#include "putty.h"
|
|
|
|
#if HAVE_DWMAPI_H
|
|
|
|
#include <dwmapi.h>
|
|
|
|
char *save_screenshot(HWND hwnd, const char *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 = fopen(outfile, "wb");
|
|
if (!fp) {
|
|
err = dupprintf("'%s': unable to open file", 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, const char *outfile)
|
|
{
|
|
return dupstr("Demo screenshots not compiled in to this build");
|
|
}
|
|
|
|
#endif /* HAVE_DWMAPI_H */
|