Monday, September 22, 2008

Create DIB section from a BMP file

// Creates a DIB section from a BMP file

//

// lpszFileName : Name of the BMP file

// ppvBits : Receive address of bitmap bits

// hSection : Optional handle to a file mapping object

// dwOffset : Offset to the bitmap bit values within hSection

//

HBITMAP LoadDIBSectionFromFile( LPCTSTR lpszFileName, LPVOID *ppvBits /*= NULL*/, HANDLE hSection /*= NULL*/, DWORD dwOffset /*= 0*/)

{

LPVOID lpBits;

CFile file;

if( !file.Open( lpszFileName, CFile::modeRead) )

return NULL;

BITMAPFILEHEADER bmfHeader;

long nFileLen;

nFileLen = file.GetLength();

// Read file header

if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))

{

return NULL;

}

// File type should be ‘BM’

int ch1 = ‘M’;

int ch2 = 8;

int leftshift = ch1 <<>

int ch = ‘B’;

if ( bmfHeader.bfType != (WORD) (leftshift | ch )

{

return NULL;

}

BITMAPINFO *pbmInfo;

pbmInfo = (BITMAPINFO *)::GlobalAlloc(GMEM_FIXED, sizeof(BITMAPINFO) + sizeof(RGBQUAD)*256 );

if (pbmInfo == NULL)

{

return NULL;

}

// Read the BITMAPINFO

file.Read( pbmInfo, sizeof(BITMAPINFO) + sizeof(RGBQUAD)*256 );

BITMAPINFO &bmInfo = *pbmInfo ;

HBITMAP hBmp = CreateDIBSection( NULL, pbmInfo, DIB_RGB_COLORS, &lpBits, hSection, dwOffset );

LPBYTE lpDIBBits; // Pointer to DIB bits

int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed : 1 <<>

if( bmInfo.bmiHeader.biBitCount > 8 )

{

lpDIBBits = (LPBYTE)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) + ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));

}

else

{

lpDIBBits = (LPBYTE)(bmInfo.bmiColors + nColors);

}

int nOffset = sizeof(BITMAPFILEHEADER) + (lpDIBBits - (LPBYTE)pbmInfo);

file.Seek( nOffset, CFile::begin);

file.ReadHuge((LPSTR)lpBits, nFileLen - nOffset); //bmInfo.biSizeImage );

::GlobalFree(pbmInfo);

if( ppvBits )

{

*ppvBits = lpBits;

}

return hBmp;

}

Converting double to a CString (0.005 to 5e-003)

Input:

double d = 0.005;

CString strTemp;

strTemp.Format("%.0e",d);

Output : 5e-003

But if I want “5e-03 then

Input:

// Enable two-digit exponent format

unsigned int old_exponent_format;

old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);

double d = 0.005;

CString strTemp;

strTemp.Format("%.0e",d);

Output : 5e-03

Conversion to scientific notation is done automatically. But as far as I know “5e-3” is impossible.

Retrieve the Application Directory

// With standard string

char szAppPath[MAX_PATH] = "";

char szAppDirectory[MAX_PATH] = "";

::GetModuleFileName(0, szAppPath, sizeof(szAppPath) - 1);

// Extract directory

strncpy(szAppDirectory, szAppPath, strrchr(szAppPath, '\\') - szAppPath);

szAppDirectory[strlen(szAppDirectory)] = '\0';

Thursday, September 11, 2008

Draw Multi-line Text into a Window in MFC

// Draw multiline text into a window

//

// pDC : Specifies the device context

// str : Specifies the string

// rectText : Specifies the text rectangle

// nFirstVisibleLineIndex : Specifies the first visible line index

// nFormat : Specifies the method of formatting the text

//

void CEMCHotCtrl::DrawMultilineText(CDC* pDC, CString str, CRect rectText, int nFirstVisibleLineIndex, int nFormat)

{

if(str.GetLength() > 0)

{

const TCHAR* p = (LPCTSTR) str;

CSize sz = pDC->GetTextExtent(p);

const TCHAR* end = p;

int nLine = 0;

if(nFirstVisibleLineIndex > 0)

{

while(*end != 0)

{

if(*end == _T('\n'))

{

nLine++;

if(nLine == nFirstVisibleLineIndex)

{

end++;

break;

}

}

end++;

}

}

int len = 0;

TCHAR buf[10000];

while(*end != 0)

{

buf[len] = *end;

end++;

len++;

if(*end == _T('\n') || (*end == 0))

{

if(buf[len - 1] == _T('\r'))

{

buf[len - 1] = 0;

}

buf[len] = 0;

pDC->DrawText(buf, -1, rectText, nFormat);

if(*end == _T('\n'))

{

end++;

}

rectText.top += sz.cy;

len = 0;

}

}

}

}

Draw a Transparent Bitmap into the destination DC with Pallete in MFC

// Draw a transparent bitmap into the destination DC with Pallete

void CEMCHotCtrl::TransparentBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, COLORREF colorTransparent, HPALETTE hPal)

{

CDC dc, memDC, maskDC, tempDC;

dc.Attach( hdcDest );

maskDC.CreateCompatibleDC(&dc);

CBitmap maskBitmap;

// These store return of SelectObject() calls

CBitmap* pOldMemBmp = NULL;

CBitmap* pOldMaskBmp = NULL;

HBITMAP hOldTempBmp = NULL;

memDC.CreateCompatibleDC (&dc);

tempDC.CreateCompatibleDC (&dc);

CBitmap bmpImage;

bmpImage.CreateCompatibleBitmap (&dc, nWidth, nHeight);

pOldMemBmp = memDC.SelectObject (&bmpImage);

// Select and realize the palette

if (dc.GetDeviceCaps (RASTERCAPS) & RC_PALETTE && hPal)

{

::SelectPalette( dc, hPal, FALSE );

dc.RealizePalette();

::SelectPalette( memDC, hPal, FALSE );

}

hOldTempBmp = (HBITMAP) ::SelectObject (tempDC.m_hDC, hBitmap);

memDC.BitBlt (0, 0, nWidth, nHeight, &tempDC, nXSrc, nYSrc, SRCCOPY);

// Create monochrome bitmap for the mask

maskBitmap.CreateBitmap (nWidth, nHeight, 1, 1, NULL);

pOldMaskBmp = maskDC.SelectObject (&maskBitmap);

memDC.SetBkColor (colorTransparent);

// Create the mask from the memory DC

maskDC.BitBlt (0, 0, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);

// Set the background in memDC to black. Using SRCPAINT with black and any other color results in the other color, thus making black the transparent color

memDC.SetBkColor (RGB (0,0,0));

memDC.SetTextColor (RGB (255,255,255));

memDC.BitBlt (0, 0, nWidth, nHeight, &maskDC, 0, 0, SRCAND);

// Set the foreground to black. See comment above.

dc.SetBkColor (RGB (255,255,255));

dc.SetTextColor (RGB (0,0,0));

dc.BitBlt (nXDest, nYDest, nWidth, nHeight, &maskDC, 0, 0, SRCAND);

// Combine the foreground with the background

dc.BitBlt (nXDest, nYDest, nWidth, nHeight, &memDC, 0, 0, SRCPAINT);

if (hOldTempBmp)

::SelectObject (tempDC.m_hDC, hOldTempBmp);

if (pOldMaskBmp)

maskDC.SelectObject (pOldMaskBmp);

if (pOldMemBmp)

memDC.SelectObject (pOldMemBmp);

dc.Detach();

}

Draw a Transparent Bitmap into the destination DC in MFC

// Draw a transparent bitmap into the destination DC.

void CEMCHotCtrl::TransparentBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, COLORREF cTransparentColor)

{

COLORREF cColor;

HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;

HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;

HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;

POINT ptSize;

hdcTemp = CreateCompatibleDC(hdcDest);

SelectObject(hdcTemp, hBitmap); // Select the bitmap

ptSize.x = nWidth;

ptSize.y = nHeight;

DPtoLP(hdcTemp, &ptSize, 1); // Convert from device

// Create some DCs to hold temporary data.

hdcBack = CreateCompatibleDC(hdcDest);

hdcObject = CreateCompatibleDC(hdcDest);

hdcMem = CreateCompatibleDC(hdcDest);

hdcSave = CreateCompatibleDC(hdcDest);

// Create a bitmap for each DC. DCs are required for a number of GDI functions.

// Monochrome DC

bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

// Monochrome DC

bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

bmAndMem = CreateCompatibleBitmap(hdcDest, ptSize.x, ptSize.y);

bmSave = CreateCompatibleBitmap(hdcDest, ptSize.x, ptSize.y);

// Each DC must select a bitmap object to store pixel data.

bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);

bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);

bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);

bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);

// Set proper mapping mode.

SetMapMode(hdcTemp, GetMapMode(hdcDest));

// Save the bitmap sent here, because it will be overwritten.

BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);

// Set the background color of the source DC to the color.

// contained in the parts of the bitmap that should be transparent

cColor = SetBkColor(hdcTemp, cTransparentColor);

// Create the object mask for the bitmap by performing a BitBlt

// from the source bitmap to a monochrome bitmap.

BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);

// Set the background color of the source DC back to the original color.

SetBkColor(hdcTemp, cColor);

// Create the inverse of the object mask.

BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);

// Copy the background of the main DC to the destination.

BitBlt(hdcMem, nXDest, nYDest, ptSize.x, ptSize.y, hdcDest, nXSrc, nYSrc, SRCCOPY);

// Mask out the places where the bitmap will be placed.

BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);

// Mask out the transparent colored pixels on the bitmap.

BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);

// XOR the bitmap with the background on the destination DC.

BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);

// Copy the destination to the screen.

BitBlt(hdcDest, nXDest, nYDest, ptSize.x, ptSize.y, hdcMem, nXSrc, nYSrc, SRCCOPY);

// Delete the memory bitmaps.

DeleteObject(SelectObject(hdcBack, bmBackOld));

DeleteObject(SelectObject(hdcObject, bmObjectOld));

DeleteObject(SelectObject(hdcMem, bmMemOld));

DeleteObject(SelectObject(hdcSave, bmSaveOld));

// Delete the memory DCs.

DeleteDC(hdcMem);

DeleteDC(hdcBack);

DeleteDC(hdcObject);

DeleteDC(hdcSave);

DeleteDC(hdcTemp);

}

Tuesday, September 9, 2008

Draw a Disabled Bitmap into the destination DC in MFC

void CEMCHotButton::DisabledBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc)

{

ASSERT (hdcDest && hBitmap);

ASSERT (nWidth > 0 && nHeight > 0);

// Create a generic DC for all BitBlts

HDC hDC = CreateCompatibleDC (hdcDest);

ASSERT (hDC);

if (hDC)

{

// Create a DC for the monochrome DIB section

HDC bwDC = CreateCompatibleDC(hDC);

ASSERT (bwDC);

if (bwDC)

{

// Create the monochrome DIB section with a black and white palette

struct

{

BITMAPINFOHEADER bmiHeader;

RGBQUAD bmiColors[2];

} RGBBWBITMAPINFO =

{

{ // a BITMAPINFOHEADER

sizeof(BITMAPINFOHEADER), // biSize

nWidth, // biWidth;

nHeight, // biHeight;

1, // biPlanes;

1, // biBitCount

BI_RGB, // biCompression;

0, // biSizeImage;

0, // biXPelsPerMeter;

0, // biYPelsPerMeter;

0, // biClrUsed;

0 // biClrImportant;

},

{

{ 0x00, 0x00, 0x00, 0x00 },

{ 0xFF, 0xFF, 0xFF, 0x00 }

}

};

void* pbitsBW;

HBITMAP hBitmapBW = CreateDIBSection (bwDC, (LPBITMAPINFO) &RGBBWBITMAPINFO, DIB_RGB_COLORS, &pbitsBW, NULL, 0);

ASSERT (hBitmapBW);

if (hBitmapBW)

{

// Attach the monochrome DIB section and the bitmap to the DCs

SelectObject (bwDC, hBitmapBW);

SelectObject (hDC, hBitmap);

// BitBlt the bitmap into the monochrome DIB section

BitBlt (bwDC, 0, 0, nWidth, nHeight, hDC, nXSrc, nYSrc, SRCCOPY);

// Paint the destination rectangle in gray

FillRect (hdcDest, CRect (nXDest, nYDest, nXDest + nWidth, nYDest + nHeight), GetSysColorBrush (COLOR_3DFACE));

// BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT bits in the destination DC

// The magic ROP comes from the Charles Petzold's book

HBRUSH hb = CreateSolidBrush (GetSysColor (COLOR_3DHILIGHT));

HBRUSH oldBrush = (HBRUSH) SelectObject (hdcDest, hb);

BitBlt (hdcDest, nXDest + 1, nYDest + 1, nWidth, nHeight, bwDC, 0, 0, 0xB8074A);

// BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW bits in the destination DC

hb = CreateSolidBrush (GetSysColor (COLOR_3DSHADOW));

DeleteObject (SelectObject(hdcDest, hb));

BitBlt (hdcDest, nXDest, nYDest, nWidth, nHeight, bwDC, 0, 0, 0xB8074A);

DeleteObject (SelectObject (hdcDest, oldBrush));

DeleteObject (hBitmapBW);

}

VERIFY (DeleteDC (bwDC));

}

VERIFY (DeleteDC(hDC));

}

}

Draw a Gradient Rectangle in MFC

void CEMCHotButton::DrawGradientRect (CDC *pDC, CRect r, COLORREF cLeft, COLORREF cRight, BOOL bVertical)

{

CRect stepR; // rectangle for color's band

COLORREF color; // color for the bands

float fStep;

if(bVertical)

fStep = ((float)r.Height())/255.0f;

else

fStep = ((float)r.Width())/255.0f; // width of color's band

for (int iOnBand = 0; iOnBand <>

{

// set current band

if(bVertical)

{

SetRect(&stepR,

r.left,

r.top+(int)(iOnBand * fStep),

r.right,

r.top+(int)((iOnBand+1)* fStep));

}

else

{

SetRect(&stepR,

r.left+(int)(iOnBand * fStep),

r.top,

r.left+(int)((iOnBand+1)* fStep),

r.bottom);

}

// set current color

color = RGB((GetRValue(cRight)-GetRValue(cLeft))*((float)iOnBand)/255.0f+GetRValue(cLeft),

(GetGValue(cRight)-GetGValue(cLeft))*((float)iOnBand)/255.0f+GetGValue(cLeft),

(GetBValue(cRight)-GetBValue(cLeft))*((float)iOnBand)/255.0f+GetBValue(cLeft));

// fill current band

pDC->FillSolidRect(stepR,color);

}

}

Convert an Icon to a Bitmap image in MFC

HBITMAP CHotButton::ConvertIconToBitmap(HICON hIcon)

{

CClientDC clientDC(this);

CDC dc;

dc.CreateCompatibleDC(&clientDC);

CRect rectButton;

GetClientRect (&rectButton);

CSize sizeButton = rectButton.Size();

// bitmap size:

int cx = 0, cy = 0;

if (sizeButton.cy <=16)

{

// bitmap size:

cx = 12;

cy = 12;

}

else if (sizeButton.cy > 16)

{

// bitmap size:

cx = 16;

cy = 16;

}

CBitmap bmp;

bmp.CreateCompatibleBitmap(&clientDC, cx, cy);

CBitmap* pOldBmp = (CBitmap*)dc.SelectObject(&bmp);

::DrawIconEx( dc.GetSafeHdc(), 0, 0, hIcon, cx, cy, 0, (HBRUSH)RGB(192, 192, 192), DI_NORMAL);

dc.SelectObject( pOldBmp );

dc.DeleteDC();

// return the image

return ((HBITMAP)::CopyImage((HANDLE)((HBITMAP)bmp), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION));

}

Monday, September 8, 2008

Loading a bitmaps from a MFC DLL resource

HMODULE hPrevInst = AfxGetResourceHandle();

HMODULE hDLLInstance = ::LoadLibrary( _T("ESIMFCControls"));

if (hDLLInstance != NULL)

{

AfxSetResourceHandle(hDLLInstance);

CBitmap bmp;

if ( bmp.LoadBitmap(MAKEINTRESOURCE(IDB_FILTER_BITMAP)) )

{

CDC dcMemory;

BITMAP bm;

dcMemory.CreateCompatibleDC(pDC);

dcMemory.SelectObject(&bmp);

// Get the height and width of the bitmap

bmp.GetBitmap(&bm);

pDC->BitBlt(rcFilter.left, rcFilter.top, bm.bmWidth, bm.bmHeight, &dcMemory, 0, 0, SRCCOPY);

}

// Restore previous resource handle

AfxSetResourceHandle(hPrevInst);

}