//File: XdBmp.h
/*
2017.05.04 2:10 AM bjt
littleflute
*/
class CXdBmp
{
#pragma warning (disable : 4183)
public:
CXdBmp::CXdBmp():m_hMyB(NULL){
strcpy(m_szV,"V0.0.2");
}
CXdBmp::~CXdBmp(){}
void drawByByteData(HDC hDC,BYTE* pByte,int n, LPRECT pRect)
{
HBITMAP &h = m_hMyB;
if(NULL==h)
{
h = ptCreateDIBSection(n,n,24,0);
}
::memcpy(m_pBmpBits,pByte,n*n*3);
if(h)
BOOL b = ptDrawDIBSectionOnDC(hDC,h,pRect);
}
void CXdBmp::getDataFromScreen(LPRECT lpRect)
{
if(NULL==lpRect) return;
HDC hScrDC = CreateDC("DISPLAY",NULL,NULL,NULL);
int nX = lpRect->left;
int nY = lpRect->top;
int nX2 = lpRect->right;
int nY2 = lpRect->bottom;
int xScreen = ::GetSystemMetrics(SM_CXSCREEN);
int yScreen = GetSystemMetrics(SM_CYSCREEN);
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScreen)
nX2 = xScreen;
if (nY2 > yScreen)
nY2 = yScreen;
int nWidth = nX2 - nX;
int nHeight = nY2 - nY;
m_hMyB = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
DeleteDC(hScrDC);
}
HBITMAP CXdBmp::getScreenToBmp(LPRECT lpRect,BOOL bSave)
{
HDC hScrDC, hMemDC;
HBITMAP hBitmap, hOldBitmap;
int nX, nY, nX2, nY2;
int nWidth, nHeight;
if (IsRectEmpty(lpRect))
return NULL;
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
hMemDC = CreateCompatibleDC(hScrDC);
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
//»ñÈ¡ÆÁÄ»·Ö±çÂÊ
int xScreen = ::GetSystemMetrics(SM_CXSCREEN);
int yScreen = GetSystemMetrics(SM_CYSCREEN);
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScreen)
nX2 = xScreen;
if (nY2 > yScreen)
nY2 = yScreen;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, nWidth, nHeight,hScrDC, nX, nY, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
if(bSave)
{
save(hMemDC,hBitmap,"d:\\xd\\h1.bmp");
}
DeleteDC(hScrDC);
DeleteDC(hMemDC);
return hBitmap;
}
HBITMAP CXdBmp::draw2File(LPRECT lpRect,BOOL bSave)
{
HDC hScrDC, hMemDC;
HBITMAP hBitmap, hOldBitmap;
int nX, nY, nX2, nY2;
int nWidth, nHeight;
if (IsRectEmpty(lpRect))
return NULL;
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
hMemDC = CreateCompatibleDC(hScrDC);
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
//»ñÈ¡ÆÁÄ»·Ö±çÂÊ
int xScreen = ::GetSystemMetrics(SM_CXSCREEN);
int yScreen = GetSystemMetrics(SM_CYSCREEN);
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScreen)
nX2 = xScreen;
if (nY2 > yScreen)
nY2 = yScreen;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
::Rectangle(hMemDC,10,10,300,300);
::TextOut(hMemDC,100,100,"xd drawing test",16);
::TextOut(hMemDC,100,200,m_szV,strlen(m_szV));
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
if(bSave)
{
save(hMemDC,hBitmap,"d:\\xd\\3.bmp");
}
DeleteDC(hScrDC);
DeleteDC(hMemDC);
return hBitmap;
}
private:
int CXdBmp::save(HDC hDC,HBITMAP hBmp,char* filePath)
{
HBITMAP hBitmap = hBmp;
int iBits;
WORD wBitCount;
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
BITMAP Bitmap;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE fh, hDib, hPal,hOldPal=NULL;
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize,
(BITMAPINFO *)lpbi, DIB_RGB_COLORS);
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
fh = CreateFile(filePath, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE)
return 0;
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return 1;
}
BOOL ptDrawDIBSectionOnDC( HDC hDC, HBITMAP hBitmap, LPRECT pxdRect )
{
DIBSECTION ds;
HPALETTE hPal, hOldPal;
BOOL bRes;
GetObject( hBitmap, sizeof(DIBSECTION), &ds );
if( GetDeviceCaps( hDC, RASTERCAPS ) & RC_PALETTE )
{ // if it's a palette device, select and realize a palette
// as a background palette (won't cause a problem is the
// palette was not selected in the foreground in the main app
hPal = ptCreatePaletteForDIBSection( hBitmap );
hOldPal = SelectPalette( hDC, hPal, TRUE );
RealizePalette( hDC );
}
if( GetDeviceCaps( hDC, TECHNOLOGY ) == DT_RASDISPLAY )
{ // going to the screen, use StretchBlt()
HDC hMemDC;
HBITMAP hOldBitmap;
hMemDC = CreateCompatibleDC( hDC );
hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
bRes = StretchBlt( hDC, pxdRect->left, pxdRect->top,
pxdRect->right-pxdRect->left, pxdRect->bottom-pxdRect->top,
hMemDC, 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, SRCCOPY );
SelectObject( hMemDC, hOldBitmap );
DeleteDC( hMemDC );
}
else
{ // going to the printer, use StretchDIBits()
LPBITMAPINFO pbmi;
// if the printer is palettized,
pbmi = ptGetBITMAPINFOForDIBSection( hBitmap );
bRes = (GDI_ERROR != StretchDIBits( hDC, pxdRect->left, pxdRect->top,
pxdRect->right-pxdRect->left, pxdRect->bottom-pxdRect->top,
0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBits,
pbmi, DIB_RGB_COLORS, SRCCOPY ));
free( pbmi );
}
if( GetDeviceCaps( hDC, RASTERCAPS ) & RC_PALETTE )
{
SelectPalette( hDC, hOldPal, TRUE );
DeleteObject( hPal );
}
return bRes;
}
HPALETTE ptCreatePaletteForDIBSection( HBITMAP hBitmap )
{
BITMAP bm;
HPALETTE hPalette;
// Get the color depth of the DIBSection
GetObject( hBitmap, sizeof(BITMAP), &bm );
// If the DIBSection is 256 color or less, it has a color table
if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 )
{
HDC hMemDC;
HBITMAP hOldBitmap;
RGBQUAD rgb[256];
LPLOGPALETTE pLogPal;
WORD i;
int nColors;
// Find out how many colors are in the color table
nColors = 1 << ( bm.bmBitsPixel * bm.bmPlanes );
// Create a memory DC and select the DIBSection into it
hMemDC = CreateCompatibleDC( NULL );
hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
// Get the DIBSection's color table
GetDIBColorTable( hMemDC, 0, nColors, rgb );
// Create a palette from the color table
pLogPal = (LOGPALETTE*)malloc( sizeof(LOGPALETTE) + (nColors*sizeof(PALETTEENTRY)) );
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = nColors;
for(i=0;i<nColors;i++)
{
pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
}
hPalette = CreatePalette( pLogPal );
// Clean up
free( pLogPal );
SelectObject( hMemDC, hOldBitmap );
DeleteDC( hMemDC );
}
else // It has no color table, so make one up
{
hPalette = ptCreateSpectrumPalette();
}
return hPalette;
}
HPALETTE ptCreateSpectrumPalette( void )
{
HPALETTE hPal;
LPLOGPALETTE lplgPal;
BYTE red, green, blue;
int i;
lplgPal = (LPLOGPALETTE)GlobalAlloc( GPTR, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256 );
if (!lplgPal)
return NULL;
lplgPal->palVersion = 0x300;
lplgPal->palNumEntries = 256;
red = green = blue = 0;
for (i = 0; i < 256; i++) {
lplgPal->palPalEntry[i].peRed = red;
lplgPal->palPalEntry[i].peGreen = green;
lplgPal->palPalEntry[i].peBlue = blue;
lplgPal->palPalEntry[i].peFlags = (BYTE)0;
if (!(red += 32))
if (!(green += 32))
blue += 64;
}
hPal = CreatePalette(lplgPal);
GlobalFree(lplgPal);
return hPal;
}
LPBITMAPINFO ptGetBITMAPINFOForDIBSection( HBITMAP hBitmap )
{
LPBITMAPINFO pbmi;
DIBSECTION ds;
LPRGBQUAD prgb;
GetObject( hBitmap, sizeof(DIBSECTION), &ds );
// load the header and the bitmasks if present
// per function comments above, we allocate space for a color
// table even if it is not needed
if( ds.dsBmih.biCompression == BI_BITFIELDS )
{ // has a bitmask - be sure to allocate for and copy them
pbmi = (BITMAPINFO*)malloc( sizeof(BITMAPINFOHEADER) + (3*sizeof(DWORD)) + (256*sizeof(RGBQUAD)) );
CopyMemory( &(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER) + (3*sizeof(DWORD)) );
prgb = (LPRGBQUAD)&(pbmi->bmiColors[3]);
}
else
{ // no bitmask - just the header and color table
pbmi = (BITMAPINFO*)malloc( sizeof(BITMAPINFOHEADER) + (256*sizeof(RGBQUAD)) );
CopyMemory( &(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER) );
prgb = pbmi->bmiColors;
}
// at this point, prgb points to the color table, even
// if bitmasks are present
// Now for the color table
if( ( ds.dsBm.bmBitsPixel * ds.dsBm.bmPlanes ) <= 8 )
{ // the DIBSection is 256 color or less (has color table)
HDC hMemDC;
HBITMAP hOldBitmap;
hMemDC = CreateCompatibleDC( NULL );
hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
GetDIBColorTable( hMemDC, 0, 1<<(ds.dsBm.bmBitsPixel*ds.dsBm.bmPlanes), prgb );
SelectObject( hMemDC, hOldBitmap );
DeleteDC( hMemDC );
}
else
{ // the DIBSection is >8bpp (has no color table) so make one up
HPALETTE hPal;
PALETTEENTRY pe[256];
int i;
// where are we going to get the colors? from a spectrum palette
hPal = ptCreateSpectrumPalette();
GetPaletteEntries( hPal, 0, 256, pe );
for(i=0;i<256;i++)
{
prgb[i].rgbRed = pe[i].peRed;
prgb[i].rgbGreen = pe[i].peGreen;
prgb[i].rgbBlue = pe[i].peBlue;
prgb[i].rgbReserved = 0;
}
DeleteObject( hPal );
pbmi->bmiHeader.biClrUsed = 256;
}
return pbmi;
}
HBITMAP ptCreateDIBSection( DWORD dwX, DWORD dwY, WORD wBits, BOOL Monochrome )
{
HBITMAP hBitmap;
int nInfoSize;
LPBITMAPINFO pbmi;
HDC hRefDC;
nInfoSize = sizeof( BITMAPINFOHEADER );
if( wBits <= 8 )
nInfoSize += sizeof(RGBQUAD) * (1 << wBits);
if( ( wBits == 16 ) || ( wBits == 32 ) )
nInfoSize += 3 * sizeof(DWORD);
// Create the header big enough to contain color table and bitmasks if needed
pbmi = (LPBITMAPINFO)malloc( nInfoSize );
ZeroMemory( pbmi, nInfoSize );
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = dwX;
pbmi->bmiHeader.biHeight = dwY;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = wBits;
pbmi->bmiHeader.biCompression = BI_RGB; // override below for 16 and 32bpp
switch( wBits )
{
case 24:
// 24bpp requires no special handling
break;
case 16:
{ // if it's 16bpp, fill in the masks and override the compression
// these are the default masks - you could change them if needed
LPDWORD pMasks = (LPDWORD)(pbmi->bmiColors);
pMasks[0] = 0x00007c00;
pMasks[1] = 0x000003e0;
pMasks[2] = 0x0000001f;
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
}
break;
case 32:
{ // if it's 32bpp, fill in the masks and override the compression
// these are the default masks - you could change them if needed
LPDWORD pMasks = (LPDWORD)(pbmi->bmiColors);
pMasks[0] = 0x00ff0000;
pMasks[1] = 0x0000ff00;
pMasks[2] = 0x000000ff;
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
}
break;
case 8:
{
if(Monochrome)
{
int i;
for(i=0;i<256;i++)
{
pbmi->bmiColors[i].rgbRed = i;
pbmi->bmiColors[i].rgbGreen = i;
pbmi->bmiColors[i].rgbBlue = i;
pbmi->bmiColors[i].rgbReserved = 0;
}
pbmi->bmiHeader.biClrUsed = 256;
}
else
{
HPALETTE hPal;
PALETTEENTRY pe[256];
int i;
// at this point, prgb points to the color table, even
// if bitmasks are present
hPal = ptCreateSpectrumPalette();
GetPaletteEntries( hPal, 0, 256, pe );
for(i=0;i<256;i++)
{
pbmi->bmiColors[i].rgbRed = pe[i].peRed;
pbmi->bmiColors[i].rgbGreen = pe[i].peGreen;
pbmi->bmiColors[i].rgbBlue = pe[i].peBlue;
pbmi->bmiColors[i].rgbReserved = 0;
}
DeleteObject( hPal );
pbmi->bmiHeader.biClrUsed = 256;
}
}
break;
case 4:
{ // Use a default 16 color table for 4bpp DIBSections
RGBTRIPLE rgb[16] = { { 0x00, 0x00, 0x00 }, // black
{ 0x80, 0x00, 0x00 }, // dark red
{ 0x00, 0x80, 0x00 }, // dark green
{ 0x80, 0x80, 0x00 }, // dark yellow
{ 0x00, 0x00, 0x80 }, // dark blue
{ 0x80, 0x00, 0x80 }, // dark magenta
{ 0x00, 0x80, 0x80 }, // dark cyan
{ 0xC0, 0xC0, 0xC0 }, // light gray
// { 0xC0, 0xDC, 0xC0 }, // money green
// { 0xA6, 0xCA, 0xF0 }, // sky blue
// { 0xFF, 0xFB, 0xF0 }, // cream
// { 0xA0, 0xA0, 0xA4 }, // light gray
{ 0x80, 0x80, 0x80 }, // medium gray
{ 0xFF, 0x00, 0x00 }, // red
{ 0x00, 0xFF, 0x00 }, // green
{ 0xFF, 0xFF, 0x00 }, // yellow
{ 0x00, 0x00, 0xFF }, // blue
{ 0xFF, 0x00, 0xFF }, // magenta
{ 0x00, 0xFF, 0xFF }, // cyan
{ 0xFF, 0xFF, 0xFF } }; // white
int i;
for(i=0;i<16;i++)
{
pbmi->bmiColors[i].rgbRed = rgb[i].rgbtRed;
pbmi->bmiColors[i].rgbGreen = rgb[i].rgbtGreen;
pbmi->bmiColors[i].rgbBlue = rgb[i].rgbtBlue;
pbmi->bmiColors[i].rgbReserved = 0;
}
pbmi->bmiHeader.biClrUsed = 16;
}
break;
case 1: // BW
pbmi->bmiColors[0].rgbRed = pbmi->bmiColors[0].rgbGreen = pbmi->bmiColors[0].rgbBlue = 0;
pbmi->bmiColors[1].rgbRed = pbmi->bmiColors[1].rgbGreen = pbmi->bmiColors[1].rgbBlue = 255;
pbmi->bmiColors[0].rgbReserved = pbmi->bmiColors[1].rgbReserved = 0;
break;
}
hRefDC = ::GetDC( NULL );
hBitmap = CreateDIBSection( hRefDC, pbmi, DIB_RGB_COLORS, (void**)&m_pBmpBits, NULL, 0 );
nInfoSize = GetLastError();
::ReleaseDC( NULL, hRefDC );
free( pbmi );
if( hBitmap == NULL )
{
TCHAR szTemp[64];
wsprintf( szTemp, "Error %d", nInfoSize );
::MessageBox( NULL, szTemp, "Error", MB_OK );
}
return hBitmap;
}
char m_szV[16];
HBITMAP m_hMyB;
LPBYTE m_pBmpBits;
};