Skip to content

Commit c305345

Browse files
committed
Added source file and executable file
1 parent 84d9abe commit c305345

File tree

3 files changed

+221
-1
lines changed

3 files changed

+221
-1
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,16 @@
11
# screenshot-cmd
2-
Simple command-line tool for making screenshots
2+
Simple command-line tool for making screenshots (for Windows Vista or later)
3+
4+
Fork from https://code.google.com/archive/p/screenshot-cmd/
5+
-----------------------------------------------------------
6+
Fixed so that the drop shadow of the window frame does not appear.
7+
(ウィンドウフレームのドロップシャドウが映らないように修正した)
8+
9+
To build:
10+
> g++ -Wall -Os -mwindows -municode screenshot.cpp -lgdiplus -lDwmapi -o screenshot -static
11+
12+
To reduce the size:
13+
> strip screenshot.exe
14+
15+
To run:
16+
> screenshot.exe -wh 1e9060a -o screenshot.png

screenshot.cpp

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* Copyright (c) 2009, The Mozilla Foundation
3+
* All rights reserved.
4+
*
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.
15+
*
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.
26+
*
27+
* Contributors:
28+
* Ted Mielczarek <[email protected]>
29+
* Bartosz Wiklak <[email protected]>
30+
*/
31+
/*
32+
* NAME:
33+
* screenshot - Save a screenshot of the Windows desktop or window in .png format.
34+
*
35+
* SYNOPSIS:
36+
* screenshot [-wt WINDOW_TITLE | -rc LEFT TOP RIGHT BOTTOM | -o FILENAME | -h]
37+
*
38+
* OPTIONS:
39+
* -wt WINDOW_TITLE
40+
* Select window with this title. Title must not contain space (" ").
41+
* -rc LEFT TOP RIGHT BOTTOM
42+
* Crop source. If no WINDOW_TITLE is provided
43+
* (0,0) is left top corner of desktop,
44+
* else if WINDOW_TITLE maches a desktop window
45+
* (0,0) is it's top left corner.
46+
* -o FILENAME
47+
* Output file name, if none, the image will be saved
48+
* as "screenshot.png" in the current working directory.
49+
* -h
50+
* Shows this help info.
51+
*
52+
*
53+
*
54+
* Requires GDI+. All linker dependencies are specified explicitly in this
55+
* file, so you can compile screenshot.exe by simply running:
56+
* cl screenshot.cpp
57+
*
58+
* http://blog.mozilla.com/ted/2009/02/05/command-line-screenshot-tool-for-windows/
59+
*/
60+
61+
#include <windows.h>
62+
#include <gdiplus.h>
63+
#include <Dwmapi.h>
64+
#include <string.h>
65+
#include <stdio.h>
66+
67+
#pragma comment(lib, "user32.lib")
68+
#pragma comment(lib, "gdi32.lib")
69+
#pragma comment(lib, "gdiplus.lib")
70+
71+
using namespace Gdiplus;
72+
73+
// From http://msdn.microsoft.com/en-us/library/ms533843%28VS.85%29.aspx
74+
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
75+
{
76+
UINT num = 0; // number of image encoders
77+
UINT size = 0; // size of the image encoder array in bytes
78+
79+
ImageCodecInfo* pImageCodecInfo = NULL;
80+
81+
GetImageEncodersSize(&num, &size);
82+
if(size == 0)
83+
return -1; // Failure
84+
85+
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
86+
if(pImageCodecInfo == NULL)
87+
return -1; // Failure
88+
89+
GetImageEncoders(num, size, pImageCodecInfo);
90+
91+
for(UINT j = 0; j < num; ++j)
92+
{
93+
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
94+
{
95+
*pClsid = pImageCodecInfo[j].Clsid;
96+
free(pImageCodecInfo);
97+
return j; // Success
98+
}
99+
}
100+
101+
free(pImageCodecInfo);
102+
return -1; // Failure
103+
}
104+
105+
int wmain(int argc, wchar_t** argv)
106+
{
107+
HWND windowSearched = NULL;
108+
RECT rect = {0};
109+
wchar_t filename[MAX_PATH] = {0};
110+
111+
bool rectProvided = false;
112+
113+
if( argc>1 && wcscmp( argv[1], L"-h" )==0 ){
114+
printf( "\nNAME:\n"
115+
"\tscreenshot -\tSave a screenshot of the Windows desktop\n\t\t\tor window in .png format.\n\n"
116+
"SYNOPSIS:\n"
117+
"\tscreenshot [ -wt WINDOW_TITLE |\n\t\t -wh WINDOW_HANDLE |\n\t\t -rc LEFT TOP RIGHT BOTTOM |\n\t\t -o FILENAME |\n\t\t -h ]\n\n"
118+
"OPTIONS:\n"
119+
"\t-wt WINDOW_TITLE\n"
120+
"\t\t\tSelect window with this title.\n\t\t\tTitle must not contain space (\" \").\n"
121+
"\t-wh WINDOW_HANDLE\n"
122+
"\t\t\tSelect window by it's handle\n\t\t\t(representad as hex string - f.e. \"0012079E\") \n"
123+
"\t-rc LEFT TOP RIGHT BOTTOM\n"
124+
"\t\t\tCrop source. If no WINDOW_TITLE is provided\n"
125+
"\t\t\t(0,0) is left top corner of desktop,\n"
126+
"\t\t\telse if WINDOW_TITLE maches a desktop window\n"
127+
"\t\t\t(0,0) is it's top left corner.\n"
128+
"\t-o FILENAME\n"
129+
"\t\t\tOutput file name, if none, the image will be saved\n"
130+
"\t\t\tas \"screenshot.png\" in the current working directory.\n"
131+
"\t-h\n"
132+
"\t\t\tShows this help info.\n" );
133+
return 1;
134+
}
135+
136+
for(short i=1; i < argc; i++ ) {
137+
if( wcscmp( argv[i], L"-wt" )==0 && i+1<argc ){
138+
windowSearched = FindWindowW( NULL, argv[i+1] );
139+
if(windowSearched){
140+
SetWindowPos( windowSearched, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
141+
Sleep(200); //TODO: Arbitrary waiting time for window to become topmost
142+
if(!rectProvided) DwmGetWindowAttribute(windowSearched, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(rect));
143+
}
144+
}else if( wcscmp( argv[i], L"-wh" )==0 && i+1<argc ){
145+
windowSearched = (HWND)wcstoul( argv[i+1],NULL,16); //TODO: How does it work on 64bit enviroment?
146+
if(windowSearched){
147+
SetWindowPos( windowSearched, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
148+
Sleep(200); //TODO: Arbitrary waiting time for window to become topmost
149+
if(!rectProvided) DwmGetWindowAttribute(windowSearched, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(rect));
150+
}
151+
}else if( wcscmp( argv[i], L"-rc" )==0 && i+4<argc ){
152+
rect.left = _wtoi( argv[i+1] );
153+
rect.top = _wtoi( argv[i+2] );
154+
rect.right = _wtoi( argv[i+3] );
155+
rect.bottom = _wtoi( argv[i+4] );
156+
157+
rectProvided = true;
158+
}else if( wcscmp( argv[i], L"-o" )==0 && i+1<argc ){
159+
wcscpy( filename, argv[i+1] );
160+
}
161+
}
162+
163+
GdiplusStartupInput gdiplusStartupInput;
164+
ULONG_PTR gdiplusToken;
165+
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
166+
167+
/* If windowSearched and rectangle was provided we should recalculate rectangle to the windowSearched coordinates */
168+
if(windowSearched && rectProvided){
169+
RECT wrect;
170+
DwmGetWindowAttribute(windowSearched, DWMWA_EXTENDED_FRAME_BOUNDS, &wrect, sizeof(wrect));
171+
OffsetRect( &rect, wrect.left, wrect.top );
172+
}
173+
174+
if( wcslen(filename)==0 ) wcscpy( filename, L"screenshot.png" );
175+
176+
HWND desktop = GetDesktopWindow();
177+
HDC desktopdc = GetDC(desktop);
178+
HDC mydc = CreateCompatibleDC(desktopdc);
179+
180+
int width = (rect.right-rect.left==0) ? GetSystemMetrics(SM_CXSCREEN) : rect.right-rect.left;
181+
int height = (rect.bottom-rect.top==0) ? GetSystemMetrics(SM_CYSCREEN) : rect.bottom-rect.top;
182+
183+
HBITMAP mybmp = CreateCompatibleBitmap(desktopdc, width, height);
184+
HBITMAP oldbmp = (HBITMAP)SelectObject(mydc, mybmp);
185+
BitBlt(mydc,0,0,width,height,desktopdc,rect.left,rect.top, SRCCOPY|CAPTUREBLT);
186+
SelectObject(mydc, oldbmp);
187+
188+
if(windowSearched) SetWindowPos( windowSearched, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
189+
190+
Bitmap* b = Bitmap::FromHBITMAP(mybmp, NULL);
191+
CLSID encoderClsid;
192+
Status stat = GenericError;
193+
if (b && GetEncoderClsid(L"image/png", &encoderClsid) != -1) {
194+
stat = b->Save(filename, &encoderClsid, NULL);
195+
}
196+
if (b)
197+
delete b;
198+
199+
// cleanup
200+
GdiplusShutdown(gdiplusToken);
201+
ReleaseDC(desktop, desktopdc);
202+
DeleteObject(mybmp);
203+
DeleteDC(mydc);
204+
return stat != Ok; // return 0 on success, (Issue 2)
205+
// thanks to [email protected] for reporting this bug.
206+
}

screenshot.exe

158 KB
Binary file not shown.

0 commit comments

Comments
 (0)