1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
#include <stdio.h>
#include <windows.h>
#include "wtypes.h"
#pragma comment(lib,"gd132.lib")
#pragma comment(lib,"user32.lib")
// Helper function to retrieve current position of file pointer:
inline int GetFilePointer(HANDLE FileHandle){
return SetFilePointer(FileHandle, 0, 0, FILE_CURRENT);
}
//---------------------------------------------------------------------------
// Screenshot
// -> FileName: Name of file to save screenshot to
// -> lpDDS: DirectDraw surface to capture
// <- Result: Success
//
extern bool SaveBMPFile(char *filename, HBITMAP bitmap, HDC bitmapDC, int width, int height){
bool Success=false;
HDC SurfDC=NULL; // GDI-compatible device context for the surface
HBITMAP OffscrBmp=NULL; // bitmap that is converted to a DIB
HDC OffscrDC=NULL; // offscreen DC that we can select OffscrBmp into
LPBITMAPINFO lpbi=NULL; // bitmap format info; used by GetDIBits
LPVOID lpvBits=NULL; // pointer to bitmap bits array
HANDLE BmpFile=INVALID_HANDLE_VALUE; // destination .bmp file
BITMAPFILEHEADER bmfh; // .bmp file header
// We need an HBITMAP to convert it to a DIB:
if ((OffscrBmp = CreateCompatibleBitmap(bitmapDC, width, height)) == NULL)
return false;
// The bitmap is empty, so let's copy the contents of the surface to it.
// For that we need to select it into a device context. We create one.
if ((OffscrDC = CreateCompatibleDC(bitmapDC)) == NULL)
return false;
// Select OffscrBmp into OffscrDC:
HBITMAP OldBmp = (HBITMAP)SelectObject(OffscrDC, OffscrBmp);
// Now we can copy the contents of the surface to the offscreen bitmap:
BitBlt(OffscrDC, 0, 0, width, height, bitmapDC, 0, 0, SRCCOPY);
// GetDIBits requires format info about the bitmap. We can have GetDIBits
// fill a structure with that info if we pass a NULL pointer for lpvBits:
// Reserve memory for bitmap info (BITMAPINFOHEADER + largest possible
// palette):
if ((lpbi = (LPBITMAPINFO)(new char[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)])) == NULL)
return false;
ZeroMemory(&lpbi->bmiHeader, sizeof(BITMAPINFOHEADER));
lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Get info but first de-select OffscrBmp because GetDIBits requires it:
SelectObject(OffscrDC, OldBmp);
if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, NULL, lpbi, DIB_RGB_COLORS))
return false;
// Reserve memory for bitmap bits:
if ((lpvBits = new char[lpbi->bmiHeader.biSizeImage]) == NULL)
return false;
// Have GetDIBits convert OffscrBmp to a DIB (device-independent bitmap):
if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, lpvBits, lpbi, DIB_RGB_COLORS))
return false;
// Create a file to save the DIB to:
if ((BmpFile = CreateFile(filename,
GENERIC_WRITE,
0, NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
return false;
DWORD Written; // number of bytes written by WriteFile
// Write a file header to the file:
bmfh.bfType = 19778; // 'BM'
// bmfh.bfSize = ??? // we'll write that later
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
// bmfh.bfOffBits = ??? // we'll write that later
if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
return false;
if (Written < sizeof(bmfh))
return false;
// Write BITMAPINFOHEADER to the file:
if (!WriteFile(BmpFile, &lpbi->bmiHeader, sizeof(BITMAPINFOHEADER), &Written, NULL))
return false;
if (Written < sizeof(BITMAPINFOHEADER))
return false;
// Calculate size of palette:
int PalEntries;
// 16-bit or 32-bit bitmaps require bit masks:
if (lpbi->bmiHeader.biCompression == BI_BITFIELDS)
PalEntries = 3;
else
// bitmap is palettized?
PalEntries = (lpbi->bmiHeader.biBitCount <= 8) ?
// 2^biBitCount palette entries max.:
(int)(1 << lpbi->bmiHeader.biBitCount)
// bitmap is TrueColor -> no palette:
: 0;
// If biClrUsed use only biClrUsed palette entries:
if(lpbi->bmiHeader.biClrUsed)
PalEntries = lpbi->bmiHeader.biClrUsed;
// Write palette to the file:
if(PalEntries){
if (!WriteFile(BmpFile, &lpbi->bmiColors, PalEntries * sizeof(RGBQUAD), &Written, NULL))
return false;
if (Written < PalEntries * sizeof(RGBQUAD))
return false;
}
// The current position in the file (at the beginning of the bitmap bits)
// will be saved to the BITMAPFILEHEADER:
bmfh.bfOffBits = GetFilePointer(BmpFile);
// Write bitmap bits to the file:
if (!WriteFile(BmpFile, lpvBits, lpbi->bmiHeader.biSizeImage, &Written, NULL))
return false;
if (Written < lpbi->bmiHeader.biSizeImage)
return false;
// The current pos. in the file is the final file size and will be saved:
bmfh.bfSize = GetFilePointer(BmpFile);
// We have all the info for the file header. Save the updated version:
SetFilePointer(BmpFile, 0, 0, FILE_BEGIN);
if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
return false;
if (Written < sizeof(bmfh))
return false;
return true;
}
bool ScreenCapture(int x, int y, int width, int height, char *filename){
// get a DC compat. w/ the screen
HDC hDc = CreateCompatibleDC(0);
// make a bmp in memory to store the capture in
HBITMAP hBmp = CreateCompatibleBitmap(GetDC(0), width, height);
// join em up
SelectObject(hDc, hBmp);
// copy from the screen to my bitmap
BitBlt(hDc, 0, 0, width, height, GetDC(0), x, y, SRCCOPY);
// save my bitmap
bool ret = SaveBMPFile(filename, hBmp, hDc, width, height);
// free the bitmap memory
DeleteObject(hBmp);
}
int main()
{
int horizontal = 0;
int vertical = 0;
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
GetWindowRect(hDesktop, &desktop);
horizontal = desktop.right;
vertical = desktop.bottom;
Sleep(10000);
ScreenCapture(0, 0, horizontal, vertical, "testScreenCap.bmp");
printf("wrote to testScreenCap.bmp");
}
|