📄 dibsection.cpp
字号:
if(hdc != NULL)
ReleaseDC(NULL, hdc);
exit:
// Create Palette
if(bPalInfoReady)
m_hPalette = CreatePalette(&pi);
else
m_hPalette = CreateHalftonePalette(m_uColorTableSize ? m_uColorTableSize : 256);
return m_hPalette != NULL;
}
BOOL CDIBSection::SetPalette(HPALETTE hPalette)
{
if(m_hPalette != NULL)
{
DeleteObject(m_hPalette);
m_hPalette = NULL;
}
if(hPalette == NULL)
return FALSE;
WORD wEntries;
GetObject(hPalette, sizeof(WORD), &wEntries);
UINT uColors = (int)wEntries;
if(uColors <= 0 || uColors > 256)
return FALSE;
// Get palette entries
PALETTEINFO pi;
pi.palNumEntries = (WORD)GetPaletteEntries(hPalette, 0, uColors, pi.palPalEntry);
/// TODO: If pi.palNumEntries < m_uColorTableSize, then fill in blanks with 0's
return SetLogPalette(&pi);
}
BOOL CDIBSection::SetLogPalette(PLOGPALETTE pLogPalette)
{
if(pLogPalette == NULL)
{
CreateSparePalette();
return FALSE;
}
// Create new palette
ASSERT(pLogPalette->palVersion == (WORD)0x300);
UINT uColors = pLogPalette->palNumEntries;
if(uColors > 0 && uColors <= 256)
{
if(m_hPalette != NULL)
DeleteObject(m_hPalette);
m_hPalette = CreatePalette(pLogPalette);
}
if(uColors <= 0 || uColors > 256 || m_hPalette == NULL)
{
CreateSparePalette();
return FALSE;
}
if(m_uColorTableSize == 0)
return TRUE;
// Set the DIB colors
RGBQUAD RGBquads[256];
for(UINT i=0; i<uColors; i++)
{
RGBquads[i].rgbRed = pLogPalette->palPalEntry[i].peRed;
RGBquads[i].rgbGreen = pLogPalette->palPalEntry[i].peGreen;
RGBquads[i].rgbBlue = pLogPalette->palPalEntry[i].peBlue;
RGBquads[i].rgbReserved = 0;
}
return FillDIBColorTable(uColors, RGBquads);
}
// Sets the colors used by the image. Only works if # colors <= 256
BOOL CDIBSection::FillDIBColorTable(UINT uNumColors, LPRGBQUAD pRGB)
{
if(m_hBitmap == NULL || pRGB == NULL || uNumColors == 0 || uNumColors > 256 || m_uColorTableSize == 0)
return FALSE;
UINT uColors = 0;
#ifndef _WIN32_WCE
// Create a memory DC compatible with the screen
HDC hdcMem = CreateCompatibleDC(NULL);
if(hdcMem == NULL)
return FALSE;
HGDIOBJ hbmpOld = SelectObject(hdcMem, m_hBitmap);
// Set the bitmap colors.
uColors = SetDIBColorTable(hdcMem, 0, uNumColors, pRGB);
// Bug fixed. Update the m_DIBInfo too
GetDIBColorTable(hdcMem, 0, m_uColorTableSize, m_DIBinfo.bmiColors);
// Clean up
if(hbmpOld != NULL)
SelectObject(hdcMem, hbmpOld);
DeleteDC(hdcMem);
#else // !_WIN32_WCE
// get the number of colors to return per BITMAPINFOHEADER docs
BITMAPINFOHEADER& bmih = *(PBITMAPINFOHEADER)m_DIBinfo;
if(bmih.biClrUsed)
uColors = bmih.biClrUsed;
else
uColors = 1 << (bmih.biBitCount * bmih.biPlanes);
// Initialize the loop variables
uColors = min(uNumColors, uColors);
LPRGBQUAD pColorTable = m_DIBinfo.GetColorTable();
for(UINT i=0; i<uColors; i++)
{
pColorTable[i].rgbRed = pRGB[i].rgbRed;
pColorTable[i].rgbGreen = pRGB[i].rgbGreen;
pColorTable[i].rgbBlue = pRGB[i].rgbBlue;
pColorTable[i].rgbReserved = 0;
}
#endif // !_WIN32_WCE
return uColors > 0;
}
#endif // DIBSECTION_NO_PALETTE
// --- In : hdc - the Device Context in which the DIBSection is selected
// hBitmap - the bitmap whose solor entries are to be queried
// lpbi - a pointer to a BITMAPINFO structure that will have it's
// color table filled.
// --- Out :
// --- Returns : the number of colors placed in the color table
// --- Effect : This function is a replacement for GetDIBits, in that it retrieves
// (or synthesizes) the color table from the given bitmap, and stores
// the values in the BITMAPINFO structure supplied.
//
///////////////////////////////////////////////////////////////////////////////
UINT CDIBSection::GetColorTableEntries(HDC hdc, HBITMAP hBitmap)
{
UINT nCount = 0;
#ifndef _WIN32_WCE
// calls GetDIBits with NULL bits pointer to fill in the BITMAPINFOHEADER data
if(::GetDIBits(hdc, hBitmap, 0, GetHeight(), NULL, m_DIBinfo, m_uColorDataType))
{
BITMAPINFOHEADER& bmih = *(PBITMAPINFOHEADER)m_DIBinfo;
if(bmih.biClrUsed)
nCount = bmih.biClrUsed;
else
nCount = 1 << (bmih.biBitCount * bmih.biPlanes);
}
#else // !_WIN32_WCE
if(!m_uColorTableSize)
return 0;
// Fill the color table with the colors from the bitmap's color table
LPRGBQUAD pColorTable = GetColorTable();
#ifdef _WIN32_WCE
// DCR 4/02/01 If you are dealing with a 16bpp bitmap in PocketPC, you must
// set the 3 DWORD color mask. This mask will be applied to a 16bit value to find the
// RGB components. Blue is lowest 5 bits, then Green, then Red.
if(m_DIBinfo.bmiHeader.biBitCount == 16)
{
DWORD dw[3];
dw[0] = 31744; // RED bitmask Bits: 0 11111 00000 00000
dw[1] = 992; // GREEN bitmask Bits: 0 00000 11111 00000
dw[2] = 31; // BLUE bitmask Bits: 0 00000 00000 11111
CopyMemory(pColorTable, dw, sizeof(DWORD) * 3);
return 3;
}
#endif // _WIN32_WCE
// Get the color table from the HBITMAP and copy them over.
LPRGBQUAD pRGB = new RGBQUAD[m_uColorTableSize];
if(pRGB)
{
HGDIOBJ hbmpOld = SelectObject(hdc, hBitmap);
nCount = GetDIBColorTable(hdc, 0, m_uColorTableSize, pRGB);
SelectObject(hdc, hbmpOld);
if(nCount)
CopyMemory(pColorTable, pRGB, sizeof(RGBQUAD) * nCount);
delete[] pRGB;
}
// Didn't work - so synthesize one.
if(!nCount)
{
nCount = min(m_uColorTableSize, sizeof(ms_StdColors) / sizeof(ms_StdColors[0]));
CopyMemory(pColorTable, ms_StdColors, sizeof(RGBQUAD) * nCount);
}
#endif // !_WIN32_WCE
return nCount;
}
// Makes trace windows a little bit more informative...
void CDIBSection::_ShowLastError()
{
#ifdef _DEBUG
PVOID pMessage;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pMessage, 0, NULL);
TRACE("Last error: %s\n", pMessage);
LocalFree(pMessage);
#endif
}
#ifdef _WIN32_WCE
///////////////////////////////////////////////////////////////////////////////
//
// This function is from the MS KB article "HOWTO: Get the Color Table of a
// DIBSection in Windows CE".
//
// PARAMETERS:
// HDC - the Device Context in which the DIBSection is selected
// UINT - the index of the first color table entry to retrieve
// UINT - the number of color table entries to retrieve
// LPRGBQUAD - a buffer large enough to hold the number of RGBQUAD entries requested
//
// RETURNS:
// UINT - the number of colors placed in the buffer
//
//
///////////////////////////////////////////////////////////////////////////////
UINT WINAPI GetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, LPRGBQUAD pColors)
{
if(pColors == NULL)
return 0; // No place to put them, fail
// Get a description of the DIB Section
HBITMAP hDIBSection = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP);
DIBSECTION ds;
DWORD dwSize = GetObject(hDIBSection, sizeof(DIBSECTION), &ds);
if(dwSize != sizeof(DIBSECTION))
return 0; // Must not be a DIBSection, fail
if(ds.dsBmih.biBitCount > 8)
return 0; // Not Palettized, fail
// get the number of colors to return per BITMAPINFOHEADER docs
UINT cColors;
if(ds.dsBmih.biClrUsed)
cColors = ds.dsBmih.biClrUsed;
else
cColors = 1 << (ds.dsBmih.biBitCount * ds.dsBmih.biPlanes);
// Create a mask for the palette index bits for 1, 2, 4, and 8 bpp
WORD wIndexMask = (0xFF << (8 - ds.dsBmih.biBitCount)) & 0x00FF;
// Get the pointer to the image bits
PBYTE pBits = (PBYTE)ds.dsBm.bmBits;
// Initialize the loop variables
cColors = min(cColors, cEntries);
BYTE OldPalIndex = *pBits;
UINT TestPixelY;
if(ds.dsBmih.biHeight > 0 )
// If button up DIB, pBits points to last row
TestPixelY = ds.dsBm.bmHeight - 1;
else
// If top down DIB, pBits points to first row
TestPixelY = 0;
for(UINT iColor=uStartIndex; iColor<cColors; iColor++)
{
COLORREF rgbColor;
// Set the palette index for the test pixel,
// modifying only the bits for one pixel
*pBits = (iColor << (8 - ds.dsBmih.biBitCount)) | (*pBits & ~wIndexMask);
// now get the resulting color
rgbColor = GetPixel(hdc, 0, TestPixelY);
pColors[iColor - uStartIndex].rgbReserved = 0;
pColors[iColor - uStartIndex].rgbBlue = GetBValue(rgbColor);
pColors[iColor - uStartIndex].rgbRed = GetRValue(rgbColor);
pColors[iColor - uStartIndex].rgbGreen = GetGValue(rgbColor);
}
// Restore the test pixel
*pBits = OldPalIndex;
return cColors;
}
#endif // _WIN32_WCE
#ifdef _WIN32_WCE
// Creates a memory DC and selects in the current bitmap so it can be modified using
// the GDI functions. Only one memory DC can be created for a given CDIBSection
// object. If you have a memory DC but wish to recreate it as compatible with a
// different DC, then call ReleaseMemoryDC first.
// If the memory DC has already been created then it will be recycled.
// Note that if using this in an environment where the color depth of the screen may
// change, then you will need to set "m_bReuseMemDC" to FALSE
HDC CDIBSection::GetMemoryDC(HDC hdc, BOOL bSelectPalette)
{
#ifdef DIBSECTION_NO_MEMDC_REUSE
ReleaseMemoryDC(TRUE);
#else
if(!m_bReuseMemoryDC)
ReleaseMemoryDC(TRUE);
else if(m_hdcMem) // Already created?
{
#ifndef _WIN32_WCE
// Flush the GDI batch queue
GdiFlush();
#endif
return m_hdcMem;
}
#endif // DIBSECTION_NO_MEMDC_REUSE
// Create a memory DC compatible with the given DC
m_hdcMem = ::CreateCompatibleDC(hdc);
if(m_hdcMem == NULL)
return NULL;
// Select in the bitmap
m_hbmpOld = ::SelectObject(m_hdcMem, m_hBitmap);
#ifndef DIBSECTION_NO_PALETTE
// Select in the palette
if(bSelectPalette && IsPaletteEnabled(m_hdcMem))
{
// Palette should already have been created - but just in case...
if(m_hPalette == NULL)
CreateSparePalette();
m_hpalOld = SelectPalette(m_hdcMem, m_hPalette, FALSE);
RealizePalette(m_hdcMem);
}
else
m_hpalOld = NULL;
#endif // DIBSECTION_NO_PALETTE
#ifndef _WIN32_WCE
// Flush the GDI batch queue
GdiFlush();
#endif // _WIN32_WCE
return m_hdcMem;
}
// Selects out the current bitmap and deletes the mem dc. If bForceRelease is FALSE,
// then the DC release will not actually occur. This is provided so you can have
//
// GetMemoryDC(...)
// ... do something
// ReleaseMemoryDC()
//
// bracketed calls. If m_bReuseMemDC is subsequently set to FALSE, then the same code
// fragment will still work.
BOOL CDIBSection::ReleaseMemoryDC(BOOL bForceRelease /*=FALSE*/)
{
if(m_hdcMem == NULL
#ifndef DIBSECTION_NO_MEMDC_REUSE
|| (m_bReuseMemoryDC && !bForceRelease)
#endif // DIBSECTION_NO_MEMDC_REUSE
)
return TRUE; // Nothing to do
#ifndef _WIN32_WCE
// Flush the GDI batch queue
GdiFlush();
#endif // _WIN32_WCE
// Select out the current bitmap
if(m_hbmpOld)
{
::SelectObject(m_hdcMem, m_hbmpOld);
m_hbmpOld = NULL;
}
#ifndef DIBSECTION_NO_PALETTE
// Select out the current palette
if(m_hpalOld)
{
::SelectPalette(m_hdcMem, m_hpalOld, FALSE);
m_hpalOld = NULL;
}
#endif // DIBSECTION_NO_PALETTE
// Delete the memory DC
BOOL bRet = ::DeleteDC(m_hdcMem);
m_hdcMem = NULL;
return bRet;
}
#endif // _WIN32_WCE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -