⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dibsection.cpp

📁 通过同步软件来获取移动智能设备屏幕画面
💻 CPP
📖 第 1 页 / 共 4 页
字号:

    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 + -