2 * Copyright (c) 2009, The Mozilla Foundation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the Mozilla Foundation nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY The Mozilla Foundation ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL The Mozilla Foundation BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Ted Mielczarek <ted.mielczarek@gmail.com>
31 * win32-screenshot.cpp: Save a screenshot of the Windows desktop in .png
32 * format. If a filename is specified as the first argument on the commandline,
33 * then the image will be saved to that filename. Otherwise, the image will
34 * be saved as "screenshot.png" in the current working directory.
37 // VS2015: Platform SDK 8.1's GdiplusTypes.h uses the min macro
39 #undef WIN32_LEAN_AND_MEAN
43 // Link w/ subsystem windows so we don't get a console when executing
46 # pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:wmainCRTStartup")
49 using namespace Gdiplus
;
51 // From http://msdn.microsoft.com/en-us/library/ms533843%28VS.85%29.aspx
52 static int GetEncoderClsid(const WCHAR
* format
, CLSID
* pClsid
) {
53 UINT num
= 0; // number of image encoders
54 UINT size
= 0; // size of the image encoder array in bytes
56 ImageCodecInfo
* pImageCodecInfo
= nullptr;
58 GetImageEncodersSize(&num
, &size
);
59 if (size
== 0) return -1; // Failure
61 pImageCodecInfo
= (ImageCodecInfo
*)(malloc(size
));
62 if (pImageCodecInfo
== nullptr) return -1; // Failure
64 GetImageEncoders(num
, size
, pImageCodecInfo
);
66 for (UINT j
= 0; j
< num
; ++j
) {
67 if (wcscmp(pImageCodecInfo
[j
].MimeType
, format
) == 0) {
68 *pClsid
= pImageCodecInfo
[j
].Clsid
;
69 free(pImageCodecInfo
);
74 free(pImageCodecInfo
);
82 wmain(int argc
, wchar_t** argv
) {
83 GdiplusStartupInput gdiplusStartupInput
;
84 ULONG_PTR gdiplusToken
;
85 GdiplusStartup(&gdiplusToken
, &gdiplusStartupInput
, nullptr);
87 HWND desktop
= GetDesktopWindow();
88 HDC desktopdc
= GetDC(desktop
);
89 HDC mydc
= CreateCompatibleDC(desktopdc
);
90 int width
= GetSystemMetrics(SM_CXSCREEN
);
91 int height
= GetSystemMetrics(SM_CYSCREEN
);
92 HBITMAP mybmp
= CreateCompatibleBitmap(desktopdc
, width
, height
);
93 HBITMAP oldbmp
= (HBITMAP
)SelectObject(mydc
, mybmp
);
94 BitBlt(mydc
, 0, 0, width
, height
, desktopdc
, 0, 0, SRCCOPY
| CAPTUREBLT
);
95 SelectObject(mydc
, oldbmp
);
97 const wchar_t* filename
= (argc
> 1) ? argv
[1] : L
"screenshot.png";
98 Bitmap
* b
= Bitmap::FromHBITMAP(mybmp
, nullptr);
100 Status stat
= GenericError
;
101 if (b
&& GetEncoderClsid(L
"image/png", &encoderClsid
) != -1) {
102 stat
= b
->Save(filename
, &encoderClsid
, nullptr);
107 GdiplusShutdown(gdiplusToken
);
108 ReleaseDC(desktop
, desktopdc
);
111 return stat
== Ok
? 0 : 1;