1 #include "screenshot.h"
4 * Save a screenshot to file until the clipboard
5 * is ready to accept images.
14 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
15 FORMAT_MESSAGE_FROM_SYSTEM
|
16 FORMAT_MESSAGE_IGNORE_INSERTS
,
19 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
27 MB_OK
| MB_ICONERROR
);
34 DoWriteFile(PSCREENSHOT pScrSht
,
37 BITMAPFILEHEADER bmfh
;
43 hFile
= CreateFile(pstrFileName
,
48 FILE_ATTRIBUTE_NORMAL
,
51 if (hFile
== INVALID_HANDLE_VALUE
)
54 /* write the BITMAPFILEHEADER to file */
55 bmfh
.bfType
= *(WORD
*)"BM"; // 0x4D 0x42
58 bSuccess
= WriteFile(hFile
,
63 if ((!bSuccess
) || (dwBytesWritten
< sizeof(bmfh
)))
66 /* write the BITMAPINFOHEADER to file */
67 bSuccess
= WriteFile(hFile
,
68 &pScrSht
->lpbi
->bmiHeader
,
69 sizeof(BITMAPINFOHEADER
),
72 if ((!bSuccess
) || (dwBytesWritten
< sizeof(BITMAPINFOHEADER
)))
75 /* calculate the size of the pallete * /
76 if (pScrSht->lpbi->bmiHeader.biCompression == BI_BITFIELDS)
80 if (pScrSht->lpbi->bmiHeader.biBitCount <= 8)
81 PalEntries = (INT)(1 << pScrSht->lpbi->bmiHeader.biBitCount);
85 if (pScrSht->lpbi->bmiHeader.biClrUsed)
86 PalEntries = pScrSht->lpbi->bmiHeader.biClrUsed;
88 / * write pallete to file * /
91 bSuccess = WriteFile(hFile,
92 &pScrSht->lpbi->bmiColors,
93 PalEntries * sizeof(RGBQUAD),
96 if ((!bSuccess) || (dwBytesWritten < PalEntries * sizeof(RGBQUAD)))
100 /* save the current file position at the bginning of the bitmap bits */
101 bmfh
.bfOffBits
= SetFilePointer(hFile
, 0, 0, FILE_CURRENT
);
103 /* write the bitmap bits to file */
104 bSuccess
= WriteFile(hFile
,
106 pScrSht
->lpbi
->bmiHeader
.biSizeImage
,
109 if ((!bSuccess
) || (dwBytesWritten
< pScrSht
->lpbi
->bmiHeader
.biSizeImage
))
112 /* save the current file position at the final file size */
113 bmfh
.bfSize
= SetFilePointer(hFile
, 0, 0, FILE_CURRENT
);
115 /* rewrite the updated file headers */
116 SetFilePointer(hFile
, 0, 0, FILE_BEGIN
);
117 bSuccess
= WriteFile(hFile
,
122 if ((!bSuccess
) || (dwBytesWritten
< sizeof(bmfh
)))
129 if (hFile
) CloseHandle(hFile
);
130 DeleteFile(pstrFileName
);
137 DoSaveFile(HWND hwnd
, LPTSTR szFileName
)
141 static TCHAR Filter
[] = _T("24 bit Bitmap (*.bmp,*.dib)\0*.bmp\0");
143 ZeroMemory(&ofn
, sizeof(ofn
));
144 ofn
.lStructSize
= sizeof(OPENFILENAME
);
145 ofn
.hwndOwner
= hwnd
;
146 ofn
.nMaxFile
= MAX_PATH
;
147 ofn
.nMaxFileTitle
= MAX_PATH
;
148 ofn
.lpstrDefExt
= _T("bmp");
149 ofn
.lpstrFilter
= Filter
;
150 ofn
.lpstrFile
= szFileName
;
151 ofn
.Flags
= OFN_EXPLORER
| OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_OVERWRITEPROMPT
;
153 if (GetSaveFileName(&ofn
))
156 if (CommDlgExtendedError() != CDERR_GENERALCODES
)
157 MessageBox(NULL
, _T("Save to file failed"), NULL
, 0);
164 CaptureScreen(PSCREENSHOT pScrSht
)
169 /* get window resolution */
170 //pScrSht->Width = GetSystemMetrics(SM_CXSCREEN);
171 //pScrSht->Height = GetSystemMetrics(SM_CYSCREEN);
173 GetWindowRect(pScrSht
->hSelf
, &rect
);
174 pScrSht
->Width
= rect
.right
- rect
.left
;
175 pScrSht
->Height
= rect
.bottom
- rect
.top
;
177 /* get a DC for the screen */
178 if (!(ScreenDC
= GetDC(pScrSht
->hSelf
)))
181 /* get a bitmap handle for the screen
182 * needed to convert to a DIB */
183 pScrSht
->hBitmap
= CreateCompatibleBitmap(ScreenDC
,
186 if (pScrSht
->hBitmap
== NULL
)
189 ReleaseDC(pScrSht
->hSelf
, ScreenDC
);
193 /* get a DC compatable with the screen DC */
194 if (!(pScrSht
->hDC
= CreateCompatibleDC(ScreenDC
)))
197 ReleaseDC(pScrSht
->hSelf
, ScreenDC
);
201 /* select the bitmap into the DC */
202 SelectObject(pScrSht
->hDC
,
205 /* copy the screen DC to the bitmap */
216 /* we're finished with the screen DC */
217 ReleaseDC(pScrSht
->hSelf
, ScreenDC
);
224 ConvertDDBtoDIB(PSCREENSHOT pScrSht
)
232 / * can't call GetDIBits with hBitmap selected * /
233 //SelectObject(hDC, hOldBitmap);
235 / * let GetDIBits fill the lpbi structure by passing NULL pointer * /
246 ReleaseDC(hwnd, hDC);
247 HeapFree(GetProcessHeap(), 0, lpbi);
252 ////////////////////////////////////////////////////
254 if (!GetObjectW(pScrSht
->hBitmap
,
262 cClrBits
= (WORD
)(bitmap
.bmPlanes
* bitmap
.bmBitsPixel
);
265 else if (cClrBits
<= 4)
267 else if (cClrBits
<= 8)
269 else if (cClrBits
<= 16)
271 else if (cClrBits
<= 24)
276 pScrSht
->lpbi
= (PBITMAPINFO
) HeapAlloc(GetProcessHeap(),
278 sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
) * (1 << cClrBits
));
280 pScrSht
->lpbi
= (PBITMAPINFO
) HeapAlloc(GetProcessHeap(),
282 sizeof(BITMAPINFOHEADER
));
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
;
297 pScrSht
->lpbi
->bmiHeader
.biClrUsed
= (1 << cClrBits
);
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
;
303 pScrSht
->lpbi
->bmiHeader
.biClrImportant
= 0;
305 //////////////////////////////////////////////////////
307 /* reserve memory to hold the screen bitmap */
308 pScrSht
->lpvBits
= HeapAlloc(GetProcessHeap(),
310 pScrSht
->lpbi
->bmiHeader
.biSizeImage
);
311 if (pScrSht
->lpvBits
== NULL
)
317 /* convert the DDB to a DIB */
318 Ret
= GetDIBits(pScrSht
->hDC
,
336 // INT WINAPI GetScreenshot(BOOL bFullScreen)
337 int WINAPI
WinMain(HINSTANCE hInstance
,
338 HINSTANCE hPrevInstance
,
343 TCHAR szFileName
[MAX_PATH
] = _T("");
345 BOOL bFullScreen
= TRUE
;
347 pScrSht
= HeapAlloc(GetProcessHeap(),
355 pScrSht
->hSelf
= GetDesktopWindow();
359 pScrSht
->hSelf
= GetForegroundWindow();
362 if (pScrSht
->hSelf
== NULL
)
364 HeapFree(GetProcessHeap(),
371 if (CaptureScreen(pScrSht
))
373 /* convert the DDB image to DIB */
374 if(ConvertDDBtoDIB(pScrSht
))
376 /* Get filename from user */
377 if(DoSaveFile(pScrSht
->hSelf
, szFileName
))
379 /* build the headers and write to file */
380 DoWriteFile(pScrSht
, szFileName
);
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
)
391 HeapFree(GetProcessHeap(),
394 if (pScrSht
->lpvBits
!= NULL
)
395 HeapFree(GetProcessHeap(),
399 HeapFree(GetProcessHeap(),