ReactOS  0.4.13-dev-544-gede3fdd
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  pScrSht->lpbi = (PBITMAPINFO) HeapAlloc(GetProcessHeap(),
277  0,
278  sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << cClrBits));
279  else
280  pScrSht->lpbi = (PBITMAPINFO) HeapAlloc(GetProcessHeap(),
281  0,
282  sizeof(BITMAPINFOHEADER));
283 
284  if (!pScrSht->lpbi)
285  {
286  GetError();
287  return FALSE;
288  }
289 
290  pScrSht->lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
291  pScrSht->lpbi->bmiHeader.biWidth = bitmap.bmWidth;
292  pScrSht->lpbi->bmiHeader.biHeight = bitmap.bmHeight;
293  pScrSht->lpbi->bmiHeader.biPlanes = bitmap.bmPlanes;
294  pScrSht->lpbi->bmiHeader.biBitCount = bitmap.bmBitsPixel;
295 
296  if (cClrBits < 24)
297  pScrSht->lpbi->bmiHeader.biClrUsed = (1 << cClrBits);
298 
299  pScrSht->lpbi->bmiHeader.biCompression = BI_RGB;
300  pScrSht->lpbi->bmiHeader.biSizeImage = ((pScrSht->lpbi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
301  * pScrSht->lpbi->bmiHeader.biHeight;
302 
303  pScrSht->lpbi->bmiHeader.biClrImportant = 0;
304 
306 
307  /* reserve memory to hold the screen bitmap */
308  pScrSht->lpvBits = HeapAlloc(GetProcessHeap(),
309  0,
310  pScrSht->lpbi->bmiHeader.biSizeImage);
311  if (pScrSht->lpvBits == NULL)
312  {
313  GetError();
314  return FALSE;
315  }
316 
317  /* convert the DDB to a DIB */
318  Ret = GetDIBits(pScrSht->hDC,
319  pScrSht->hBitmap,
320  0,
321  pScrSht->Height,
322  pScrSht->lpvBits,
323  pScrSht->lpbi,
325  if (Ret == 0)
326  {
327  GetError();
328  return FALSE;
329  }
330 
331  return TRUE;
332 
333 }
334 
335 
336 // INT WINAPI GetScreenshot(BOOL bFullScreen)
338  HINSTANCE hPrevInstance,
339  LPTSTR szCmdLine,
340  int iCmdShow)
341 {
342  PSCREENSHOT pScrSht;
343  TCHAR szFileName[MAX_PATH] = _T("");
344 
345  BOOL bFullScreen = TRUE;
346 
347  pScrSht = HeapAlloc(GetProcessHeap(),
348  0,
349  sizeof(SCREENSHOT));
350  if (pScrSht == NULL)
351  return -1;
352 
353  if (bFullScreen)
354  {
355  pScrSht->hSelf = GetDesktopWindow();
356  }
357  else
358  {
359  pScrSht->hSelf = GetForegroundWindow();
360  }
361 
362  if (pScrSht->hSelf == NULL)
363  {
365  0,
366  pScrSht);
367 
368  return -1;
369  }
370 
371  if (CaptureScreen(pScrSht))
372  {
373  /* convert the DDB image to DIB */
374  if(ConvertDDBtoDIB(pScrSht))
375  {
376  /* Get filename from user */
377  if(DoSaveFile(pScrSht->hSelf, szFileName))
378  {
379  /* build the headers and write to file */
380  DoWriteFile(pScrSht, szFileName);
381  }
382  }
383  }
384 
385  /* cleanup */
386  if (pScrSht->hSelf != NULL)
387  ReleaseDC(pScrSht->hSelf, pScrSht->hDC);
388  if (pScrSht->hBitmap != NULL)
389  DeleteObject(pScrSht->hBitmap);
390  if (pScrSht->lpbi != NULL)
392  0,
393  pScrSht->lpbi);
394  if (pScrSht->lpvBits != NULL)
396  0,
397  pScrSht->lpvBits);
398  if (pScrSht != NULL)
400  0,
401  pScrSht);
402 
403  return 0;
404 }
#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:398
HWND hSelf
Definition: screenshot.h:6
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1454
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:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
LPCSTR lpstrDefExt
Definition: commdlg.h:345
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define DeleteFile
Definition: winbase.h:3578
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:410
int32_t INT
Definition: typedefs.h:56
static BOOLEAN bSuccess
Definition: drive.cpp:417
& 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:622
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:395
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:8
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:337
#define FormatMessage
Definition: winbase.h:3609
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:5688
_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:34
#define HeapFree(x, y, z)
Definition: compat.h:394
#define SRCCOPY
Definition: wingdi.h:332
DWORD nMaxFileTitle
Definition: commdlg.h:339
DWORD Flags
Definition: commdlg.h:342