/* * Copyright (c) 2009, The Mozilla Foundation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Mozilla Foundation nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY The Mozilla Foundation ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL The Mozilla Foundation BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contributors: * Ted Mielczarek */ /* * win32-screenshot.cpp: Save a screenshot of the Windows desktop in .png * format. If a filename is specified as the first argument on the commandline, * then the image will be saved to that filename. Otherwise, the image will * be saved as "screenshot.png" in the current working directory. */ // VS2015: Platform SDK 8.1's GdiplusTypes.h uses the min macro #undef NOMINMAX #undef WIN32_LEAN_AND_MEAN #include #include // Link w/ subsystem windows so we don't get a console when executing // this binary. #ifndef __MINGW32__ # pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:wmainCRTStartup") #endif using namespace Gdiplus; // From http://msdn.microsoft.com/en-us/library/ms533843%28VS.85%29.aspx static int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0; // number of image encoders UINT size = 0; // size of the image encoder array in bytes ImageCodecInfo* pImageCodecInfo = nullptr; GetImageEncodersSize(&num, &size); if (size == 0) return -1; // Failure pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if (pImageCodecInfo == nullptr) return -1; // Failure GetImageEncoders(num, size, pImageCodecInfo); for (UINT j = 0; j < num; ++j) { if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; // Success } } free(pImageCodecInfo); return -1; // Failure } #ifdef __MINGW32__ extern "C" #endif int wmain(int argc, wchar_t** argv) { GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); HWND desktop = GetDesktopWindow(); HDC desktopdc = GetDC(desktop); HDC mydc = CreateCompatibleDC(desktopdc); int width = GetSystemMetrics(SM_CXSCREEN); int height = GetSystemMetrics(SM_CYSCREEN); HBITMAP mybmp = CreateCompatibleBitmap(desktopdc, width, height); HBITMAP oldbmp = (HBITMAP)SelectObject(mydc, mybmp); BitBlt(mydc, 0, 0, width, height, desktopdc, 0, 0, SRCCOPY | CAPTUREBLT); SelectObject(mydc, oldbmp); const wchar_t* filename = (argc > 1) ? argv[1] : L"screenshot.png"; Bitmap* b = Bitmap::FromHBITMAP(mybmp, nullptr); CLSID encoderClsid; Status stat = GenericError; if (b && GetEncoderClsid(L"image/png", &encoderClsid) != -1) { stat = b->Save(filename, &encoderClsid, nullptr); } if (b) delete b; // cleanup GdiplusShutdown(gdiplusToken); ReleaseDC(desktop, desktopdc); DeleteObject(mybmp); DeleteDC(mydc); return stat == Ok ? 0 : 1; }