ReactOS  0.4.14-dev-828-g8dc90a4
screenshot.c
Go to the documentation of this file.
1 #include "screenshot.h"
2 
3 /*
4  * Save a screenshot to file until the clipboard
5  * is ready to accept images.
6  */
7 
8 
9 static VOID
11 {
12  LPVOID lpMsgBuf;
13 
17  NULL,
18  GetLastError(),
20  (LPTSTR) &lpMsgBuf,
21  0,
22  NULL );
23 
25  lpMsgBuf,
26  _T("Error!"),
28 
29  LocalFree(lpMsgBuf);
30 }
31 
32 
33 static BOOL
35  LPTSTR pstrFileName)
36 {
37  BITMAPFILEHEADER bmfh;
38  BOOL bSuccess;
39  DWORD dwBytesWritten;
40  HANDLE hFile;
41  //INT PalEntries;
42 
43  hFile = CreateFile(pstrFileName,
45  0,
46  NULL,
49  NULL);
50 
52  return FALSE;
53 
54  /* write the BITMAPFILEHEADER to file */
55  bmfh.bfType = *(WORD *)"BM"; // 0x4D 0x42
56  bmfh.bfReserved1 = 0;
57  bmfh.bfReserved2 = 0;
59  &bmfh,
60  sizeof(bmfh),
61  &dwBytesWritten,
62  NULL);
63  if ((!bSuccess) || (dwBytesWritten < sizeof(bmfh)))
64  goto fail;
65 
66  /* write the BITMAPINFOHEADER to file */
68  &pScrSht->lpbi->bmiHeader,
69  sizeof(BITMAPINFOHEADER),
70  &dwBytesWritten,
71  NULL);
72  if ((!bSuccess) || (dwBytesWritten < sizeof(BITMAPINFOHEADER)))
73  goto fail;
74 
75  /* calculate the size of the pallete * /
76  if (pScrSht->lpbi->bmiHeader.biCompression == BI_BITFIELDS)
77  PalEntries = 3;
78  else
79  {
80  if (pScrSht->lpbi->bmiHeader.biBitCount <= 8)
81  PalEntries = (INT)(1 << pScrSht->lpbi->bmiHeader.biBitCount);
82  else
83  PalEntries = 0;
84  }
85  if (pScrSht->lpbi->bmiHeader.biClrUsed)
86  PalEntries = pScrSht->lpbi->bmiHeader.biClrUsed;
87 
88  / * write pallete to file * /
89  if (PalEntries != 0)
90  {
91  bSuccess = WriteFile(hFile,
92  &pScrSht->lpbi->bmiColors,
93  PalEntries * sizeof(RGBQUAD),
94  &dwBytesWritten,
95  NULL);
96  if ((!bSuccess) || (dwBytesWritten < PalEntries * sizeof(RGBQUAD)))
97  goto fail;
98  }
99 */
100  /* save the current file position at the bginning of the bitmap bits */
102 
103  /* write the bitmap bits to file */
105  pScrSht->lpvBits,
106  pScrSht->lpbi->bmiHeader.biSizeImage,
107  &dwBytesWritten,
108  NULL);
109  if ((!bSuccess) || (dwBytesWritten < pScrSht->lpbi->bmiHeader.biSizeImage))
110  goto fail;
111 
112  /* save the current file position at the final file size */
113  bmfh.bfSize = SetFilePointer(hFile, 0, 0, FILE_CURRENT);
114 
115  /* rewrite the updated file headers */
118  &bmfh,
119  sizeof(bmfh),
120  &dwBytesWritten,
121  NULL);
122  if ((!bSuccess) || (dwBytesWritten < sizeof(bmfh)))
123  goto fail;
124 
125  return TRUE;
126 
127 fail:
128  GetError();
129  if (hFile) CloseHandle(hFile);
130  DeleteFile(pstrFileName);
131  return FALSE;
132 
133 }
134 
135 
136 static BOOL
138 {
140 
141  static TCHAR Filter[] = _T("24 bit Bitmap (*.bmp,*.dib)\0*.bmp\0");
142 
143  ZeroMemory(&ofn, sizeof(ofn));
144  ofn.lStructSize = sizeof(OPENFILENAME);
145  ofn.hwndOwner = hwnd;
148  ofn.lpstrDefExt = _T("bmp");
150  ofn.lpstrFile = szFileName;
152 
153  if (GetSaveFileName(&ofn))
154  return TRUE;
155 
157  MessageBox(NULL, _T("Save to file failed"), NULL, 0);
158 
159  return FALSE;
160 }
161 
162 
163 static BOOL
165 {
166  HDC ScreenDC;
167  RECT rect;
168 
169  /* get window resolution */
170  //pScrSht->Width = GetSystemMetrics(SM_CXSCREEN);
171  //pScrSht->Height = GetSystemMetrics(SM_CYSCREEN);
172 
173  GetWindowRect(pScrSht->hSelf, &rect);
174  pScrSht->Width = rect.right - rect.left;
175  pScrSht->Height = rect.bottom - rect.top;
176 
177  /* get a DC for the screen */
178  if (!(ScreenDC = GetDC(pScrSht->hSelf)))
179  return FALSE;
180 
181  /* get a bitmap handle for the screen
182  * needed to convert to a DIB */
183  pScrSht->hBitmap = CreateCompatibleBitmap(ScreenDC,
184  pScrSht->Width,
185  pScrSht->Height);
186  if (pScrSht->hBitmap == NULL)
187  {
188  GetError();
189  ReleaseDC(pScrSht->hSelf, ScreenDC);
190  return FALSE;
191  }
192 
193  /* get a DC compatable with the screen DC */
194  if (!(pScrSht->hDC = CreateCompatibleDC(ScreenDC)))
195  {
196  GetError();
197  ReleaseDC(pScrSht->hSelf, ScreenDC);
198  return FALSE;
199  }
200 
201  /* select the bitmap into the DC */
202  SelectObject(pScrSht->hDC,
203  pScrSht->hBitmap);
204 
205  /* copy the screen DC to the bitmap */
206  BitBlt(pScrSht->hDC,
207  0,
208  0,
209  pScrSht->Width,
210  pScrSht->Height,
211  ScreenDC,
212  0,
213  0,
214  SRCCOPY);
215 
216  /* we're finished with the screen DC */
217  ReleaseDC(pScrSht->hSelf, ScreenDC);
218 
219  return TRUE;
220 }
221 
222 
223 static BOOL
225 {
226  INT Ret;
227  BITMAP bitmap;
228  WORD cClrBits;
229 
230 
231 /*
232  / * can't call GetDIBits with hBitmap selected * /
233  //SelectObject(hDC, hOldBitmap);
234 
235  / * let GetDIBits fill the lpbi structure by passing NULL pointer * /
236  Ret = GetDIBits(hDC,
237  hBitmap,
238  0,
239  Height,
240  NULL,
241  lpbi,
242  DIB_RGB_COLORS);
243  if (Ret == 0)
244  {
245  GetError();
246  ReleaseDC(hwnd, hDC);
247  HeapFree(GetProcessHeap(), 0, lpbi);
248  return -1;
249  }
250 */
251 
253 
254  if (!GetObjectW(pScrSht->hBitmap,
255  sizeof(BITMAP),
256  (LPTSTR)&bitmap))
257  {
258  GetError();
259  return FALSE;
260  }
261 
262  cClrBits = (WORD)(bitmap.bmPlanes * bitmap.bmBitsPixel);
263  if (cClrBits == 1)
264  cClrBits = 1;
265  else if (cClrBits <= 4)
266  cClrBits = 4;
267  else if (cClrBits <= 8)
268  cClrBits = 8;
269  else if (cClrBits <= 16)
270  cClrBits = 16;
271  else if (cClrBits <= 24)
272  cClrBits = 24;
273  else cClrBits = 32;
274 
275  if (cClrBits != 24)
276  {
277  pScrSht->lpbi = (PBITMAPINFO) HeapAlloc(GetProcessHeap(),
278  0,
279  sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << cClrBits));
280  }
281  else
282  {
283  pScrSht->lpbi = (PBITMAPINFO) HeapAlloc(GetProcessHeap(),
284  0,
285  sizeof(BITMAPINFOHEADER));
286  }
287 
288  if (!pScrSht->lpbi)
289  {
290  GetError();
291  return FALSE;
292  }
293 
294  pScrSht->lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
295  pScrSht->lpbi->bmiHeader.biWidth = bitmap.bmWidth;
296  pScrSht->lpbi->bmiHeader.biHeight = bitmap.bmHeight;
297  pScrSht->lpbi->bmiHeader.biPlanes = bitmap.bmPlanes;
298  pScrSht->lpbi->bmiHeader.biBitCount = bitmap.bmBitsPixel;
299 
300  if (cClrBits < 24)
301  pScrSht->lpbi->bmiHeader.biClrUsed = (1 << cClrBits);
302 
303  pScrSht->lpbi->bmiHeader.biCompression = BI_RGB;
304  pScrSht->lpbi->bmiHeader.biSizeImage = ((pScrSht->lpbi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
305  * pScrSht->lpbi->bmiHeader.biHeight;
306 
307  pScrSht->lpbi->bmiHeader.biClrImportant = 0;
308 
310 
311  /* reserve memory to hold the screen bitmap */
312  pScrSht->lpvBits = HeapAlloc(GetProcessHeap(),
313  0,
314  pScrSht->lpbi->bmiHeader.biSizeImage);
315  if (pScrSht->lpvBits == NULL)
316  {
317  GetError();
318  return FALSE;
319  }
320 
321  /* convert the DDB to a DIB */
322  Ret = GetDIBits(pScrSht->hDC,
323  pScrSht->hBitmap,
324  0,
325  pScrSht->Height,
326  pScrSht->lpvBits,
327  pScrSht->lpbi,
329  if (Ret == 0)
330  {
331  GetError();
332  return FALSE;
333  }
334 
335  return TRUE;
336 
337 }
338 
339 
340 // INT WINAPI GetScreenshot(BOOL bFullScreen)
342  HINSTANCE hPrevInstance,
343  LPTSTR szCmdLine,
344  int iCmdShow)
345 {
346  PSCREENSHOT pScrSht;
347  TCHAR szFileName[MAX_PATH] = _T("");
348 
349  BOOL bFullScreen = TRUE;
350 
351  pScrSht = HeapAlloc(GetProcessHeap(),
352  0,
353  sizeof(SCREENSHOT));
354  if (pScrSht == NULL)
355  return -1;
356 
357  if (bFullScreen)
358  {
359  pScrSht->hSelf = GetDesktopWindow();
360  }
361  else
362  {
363  pScrSht->hSelf = GetForegroundWindow();
364  }
365 
366  if (pScrSht->hSelf == NULL)
367  {
369  0,
370  pScrSht);
371 
372  return -1;
373  }
374 
375  if (CaptureScreen(pScrSht))
376  {
377  /* convert the DDB image to DIB */
378  if(ConvertDDBtoDIB(pScrSht))
379  {
380  /* Get filename from user */
381  if(DoSaveFile(pScrSht->hSelf, szFileName))
382  {
383  /* build the headers and write to file */
384  DoWriteFile(pScrSht, szFileName);
385  }
386  }
387  }
388 
389  /* cleanup */
390  if (pScrSht->hSelf != NULL)
391  ReleaseDC(pScrSht->hSelf, pScrSht->hDC);
392  if (pScrSht->hBitmap != NULL)
393  DeleteObject(pScrSht->hBitmap);
394  if (pScrSht->lpbi != NULL)
396  0,
397  pScrSht->lpbi);
398  if (pScrSht->lpvBits != NULL)
400  0,
401  pScrSht->lpvBits);
402  if (pScrSht != NULL)
404  0,
405  pScrSht);
406 
407  return 0;
408 }
#define CDERR_GENERALCODES
Definition: cderr.h:5
#define OFN_EXPLORER
Definition: commdlg.h:104
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
HWND hSelf
Definition: screenshot.h:6
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1475
DWORD biClrImportant
Definition: amvideo.idl:40
HDC WINAPI GetDC(_In_opt_ HWND)
HWND hwndOwner
Definition: commdlg.h:330
HBITMAP WINAPI CreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
#define LANG_NEUTRAL
Definition: nls.h:22
struct tagBITMAPINFOHEADER BITMAPINFOHEADER
#define FILE_CURRENT
Definition: winbase.h:113
#define SUBLANG_DEFAULT
Definition: nls.h:168
static HDC
Definition: imagelist.c:92
OPENFILENAME ofn
Definition: main.cpp:37
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1642
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
LPCSTR lpstrDefExt
Definition: commdlg.h:345
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define DeleteFile
Definition: winbase.h:3598
static VOID NTAPI BitBlt(IN ULONG Left, IN ULONG Top, IN ULONG Width, IN ULONG Height, IN PUCHAR Buffer, IN ULONG BitsPerPixel, IN ULONG Delta)
Definition: vga.c:405
int32_t INT
Definition: typedefs.h:56
static BOOLEAN bSuccess
Definition: drive.cpp:419
& rect
Definition: startmenu.cpp:1413
CHAR * LPTSTR
Definition: xmlstorage.h:192
DWORD nMaxFile
Definition: commdlg.h:337
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
#define GetSaveFileName
Definition: commdlg.h:666
HINSTANCE hInstance
Definition: charmap.c:20
static VOID GetError(VOID)
Definition: screenshot.c:10
static BOOL DoSaveFile(HWND hwnd, LPTSTR szFileName)
Definition: screenshot.c:137
unsigned int BOOL
Definition: ntddk_ex.h:94
static BOOL CaptureScreen(PSCREENSHOT pScrSht)
Definition: screenshot.c:164
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
Definition: fltkernel.h:1802
#define GENERIC_WRITE
Definition: nt_native.h:90
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
DWORD biCompression
Definition: amvideo.idl:35
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
static BOOL DoWriteFile(PSCREENSHOT pScrSht, LPTSTR pstrFileName)
Definition: screenshot.c:34
smooth NULL
Definition: ftsmooth.c:416
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:652
OPENFILENAMEA OPENFILENAME
Definition: commdlg.h:657
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
#define OFN_PATHMUSTEXIST
Definition: commdlg.h:117
Definition: uimain.c:88
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static BOOL ConvertDDBtoDIB(PSCREENSHOT pScrSht)
Definition: screenshot.c:224
#define MAX_PATH
Definition: compat.h:26
DWORD lStructSize
Definition: commdlg.h:329
#define WINAPI
Definition: msvc.h:6
unsigned short WORD
Definition: ntddk_ex.h:93
LPBITMAPINFO lpbi
Definition: screenshot.h:9
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD biSizeImage
Definition: amvideo.idl:36
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow)
Definition: screenshot.c:341
#define FormatMessage
Definition: winbase.h:3629
HBITMAP hBitmap
Definition: screenshot.h:8
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define MB_ICONERROR
Definition: winuser.h:781
#define OFN_HIDEREADONLY
Definition: commdlg.h:107
#define MessageBox
Definition: winuser.h:5797
_In_ HANDLE hFile
Definition: mswsock.h:90
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:401
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define CREATE_ALWAYS
Definition: disk.h:72
#define FILE_BEGIN
Definition: winbase.h:112
IN OUT PVCB OUT PDIRENT OUT PBCB IN BOOLEAN CreateFile
Definition: fatprocs.h:904
LPSTR lpstrFile
Definition: commdlg.h:336
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
Definition: bl.h:1331
#define OFN_OVERWRITEPROMPT
Definition: commdlg.h:116
LPCSTR lpstrFilter
Definition: commdlg.h:332
#define MB_OK
Definition: winuser.h:784
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
LPVOID lpvBits
Definition: screenshot.h:10
int WINAPI GetDIBits(_In_ HDC hdc, _In_ HBITMAP hbm, _In_ UINT start, _In_ UINT cLines, _Out_opt_ LPVOID lpvBits, _At_((LPBITMAPINFOHEADER) lpbmi, _Inout_) LPBITMAPINFO lpbmi, _In_ UINT usage)
#define MAKELANGID(p, s)
Definition: nls.h:15
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
struct tagBITMAPINFO * PBITMAPINFO
static HBITMAP bitmap
Definition: clipboard.c:1344
#define DIB_RGB_COLORS
Definition: wingdi.h:366
DWORD WINAPI CommDlgExtendedError(void)
Definition: cdlg32.c:139
#define BI_RGB
Definition: precomp.h:41
#define HeapFree(x, y, z)
Definition: compat.h:402
#define SRCCOPY
Definition: wingdi.h:332
DWORD nMaxFileTitle
Definition: commdlg.h:339
DWORD Flags
Definition: commdlg.h:342