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