1 #define ALIGNEDONDWORD(theBytes) ( ( ( (DWORD)(theBytes) + 31 ) & ~31 ) >> 3 )
2
3 BOOL BmpFromHandle( HDC hDC, HBITMAP hBitmap, WORD nBits, LPCTSTR lpszFile )
4 {
5 BITMAP bmp;
6 WORD cClrBits;
7 LPBITMAPINFO bi;
8 BITMAPFILEHEADER bf;
9 LPVOID lpData;
10 HANDLE hFile;
11 DWORD dwBytes;
12 int nRet;
13 BOOL bRet;
14
15 nRet = ::GetObject( ( HANDLE )hBitmap, sizeof( BITMAP ), &bmp );
16 if ( nRet != sizeof( BITMAP ) )
17 {
18 return FALSE;
19 }
20
21 bmp.bmBitsPixel = nBits;
22
23 cClrBits = ( WORD )( bmp.bmPlanes * bmp.bmBitsPixel );
24
25 if ( cClrBits == 1 )
26 {
27 cClrBits = 1;
28 }
29 else if ( cClrBits <= 4 )
30 {
31 cClrBits = 4;
32 }
33 else if ( cClrBits <= 8 )
34 {
35 cClrBits = 8;
36 }
37 else if ( cClrBits <= 16 )
38 {
39 cClrBits = 16;
40 }
41 else if ( cClrBits <= 24 )
42 {
43 cClrBits = 24;
44 }
45 else
46 {
47 cClrBits = 32;
48 }
49
50 if ( cClrBits < 24 )
51 {
52 bi = ( LPBITMAPINFO )calloc( 1, sizeof( BITMAPINFOHEADER ) + sizeof( RGBQUAD ) * ( 1 << cClrBits ) );
53 }
54 else
55 {
56 bi = ( LPBITMAPINFO )calloc( 1, sizeof( BITMAPINFOHEADER ) );
57 }
58
59 if ( bi == NULL )
60 {
61 return FALSE;
62 }
63
64 bi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
65 bi->bmiHeader.biWidth = bmp.bmWidth;
66 bi->bmiHeader.biHeight = bmp.bmHeight;
67 bi->bmiHeader.biPlanes = bmp.bmPlanes;
68 bi->bmiHeader.biBitCount = bmp.bmBitsPixel;
69 bi->bmiHeader.biCompression = BI_RGB;
70 bi->bmiHeader.biSizeImage = ( ( ( bi->bmiHeader.biWidth * cClrBits + 31 ) & ~31 ) >> 3 ) * bi->bmiHeader.biHeight;
71 /*bi->bmiHeader.biXPelsPerMeter = 0;
72 bi->bmiHeader.biYPelsPerMeter = 0;*/
73
74 if ( cClrBits < 24 )
75 {
76 bi->bmiHeader.biClrUsed = ( 1 << cClrBits );
77 }
78 /*else
79 {
80 bi->bmiHeader.biClrUsed = 0;
81 }*/
82
83 /*bi->bmiHeader.biClrImportant = 0;*/
84
85
86 lpData = calloc( ( bi->bmiHeader.biSizeImage + 4095 ) >> 12, 4096 );
87 if ( lpData == NULL )
88 {
89 free( bi );
90 return FALSE;
91 }
92
93 nRet = ::GetDIBits( hDC, hBitmap, 0, bi->bmiHeader.biHeight, lpData, bi, DIB_RGB_COLORS );
94 if ( nRet != bi->bmiHeader.biHeight )
95 {
96 goto err_exit;
97 }
98
99 if ( cClrBits < 24 )
100 {
101 bi->bmiHeader.biClrUsed = ( 1 << cClrBits );
102 }
103
104 memset( &bf, 0, sizeof( BITMAPFILEHEADER ) );
105 bf.bfType = 0x4d42;
106 bf.bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + bi->bmiHeader.biClrUsed * sizeof( RGBQUAD ) + bi->bmiHeader.biSizeImage;
107 /*bf.bfReserved1 = 0;
108 bf.bfReserved2 = 0;*/
109 bf.bfOffBits = bf.bfSize - bi->bmiHeader.biSizeImage;
110
111 hFile = ::CreateFile( lpszFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
112 if ( hFile == INVALID_HANDLE_VALUE )
113 {
114 goto err_exit;
115 }
116
117 bRet = ::WriteFile( hFile, &bf, sizeof( BITMAPFILEHEADER ), &dwBytes, NULL );
118 if ( !bRet || dwBytes != sizeof( BITMAPFILEHEADER ) )
119 {
120 ::CloseHandle( hFile );
121 goto err_exit;
122 }
123
124 bRet = ::WriteFile( hFile, bi, bf.bfOffBits - sizeof( BITMAPFILEHEADER ), &dwBytes, NULL );
125 if ( !bRet || dwBytes != bf.bfOffBits - sizeof( BITMAPFILEHEADER ) )
126 {
127 ::CloseHandle( hFile );
128 goto err_exit;
129 }
130
131 bRet = ::WriteFile( hFile, lpData, bi->bmiHeader.biSizeImage, &dwBytes, NULL );
132 if ( !bRet || dwBytes != bi->bmiHeader.biSizeImage )
133 {
134 ::CloseHandle( hFile );
135 goto err_exit;
136 }
137
138 ::CloseHandle( hFile );
139
140 free( lpData );
141 free( bi );
142 return TRUE;
143
144 err_exit:
145 free( lpData );
146 free( bi );
147 return FALSE;
148 }
149
150 BOOL CopyScreen( LPCTSTR lpszFile, WORD nBits = 24 )
151 {
152 HDC hDC, hMemDC;
153 HBITMAP hBitmap, hBitmapOld;
154 int nWidth, nHeight;
155 BOOL bRet;
156
157 bRet = TRUE;
158
159 hDC = ::GetDC( NULL );
160 nWidth = ::GetSystemMetrics( SM_CXSCREEN );
161 nHeight = ::GetSystemMetrics( SM_CYSCREEN );
162 hMemDC = ::CreateCompatibleDC( hDC );
163 hBitmap = ::CreateCompatibleBitmap( hDC, nWidth, nHeight );
164 hBitmapOld = ( HBITMAP )::SelectObject( hMemDC, ( HGDIOBJ )hBitmap );
165
166 bRet = ::BitBlt( hMemDC, 0, 0, nWidth, nHeight, hDC, 0, 0, SRCCOPY );
167 if ( bRet )
168 {
169 bRet = BmpFromHandle( hMemDC, hBitmap, nBits, lpszFile );
170 }
171
172 ::SelectObject( hMemDC, ( HGDIOBJ )hBitmapOld );
173 ::DeleteObject( ( HGDIOBJ )hBitmap );
174 ::DeleteDC( hMemDC );
175 ::ReleaseDC( NULL, hDC );
176 return bRet;
177 }
178
179 BOOL CopyRC( UINT nBitmapID, LPCTSTR lpszFile, WORD nBits = 24 )
180 {
181 HDC hDC;
182 HBITMAP hBitmap;
183 BOOL bRet;
184
185 bRet = TRUE;
186
187 hDC = ::GetDC( NULL );
188
189 hBitmap = ::LoadBitmap( ::GetModuleHandle( NULL ), MAKEINTRESOURCE( nBitmapID ) );
190 if ( hBitmap )
191 {
192 bRet = BmpFromHandle( hDC, hBitmap, nBits, lpszFile );
193 }
194 else
195 {
196 bRet = FALSE;
197 }
198
199 ::DeleteObject( ( HGDIOBJ )hBitmap );
200 ::ReleaseDC( NULL, hDC );
201
202 return bRet;
203 }