// LuButton.cpp : implementation file // #include "stdafx.h" #include "LuButton.h" #include //加入对多媒体控制的类,记得加入winmm.lib #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // LuButton LuButton::LuButton() { m_bSelect = false; //用于此按扭是否被选中 m_bFlat = false; //此按扭是否是浮动的 m_bFlash = false; //此按扭是否在闪动 m_bSound = false; //现在没有声音 m_bTransBk= false; //现在不需要显示透明位图 m_lBmpCount=0; //所加入图片的总数 m_lNowBmp=0; //现在显示的图片数为0; m_lMaxBmp =5; //最大能加入的图片数,跟据以下m_bmpX决定 m_lFlashCount=0; //闪动计数,当计数为0时则不闪 m_lMaxFlashCount=0; //最大的闪动计数 m_lFlashTime=LUBUTTON_FLASHTIME; //闪动的间隔时间 m_lDHTime = 800; //动画间隔时间 m_bUnBmp = false; //现在还没有设UnBmp m_bFlatBmp = false; //现在还没有设FlatBmp m_bDisBmp = false; m_bClickBmp = false; m_bMouseOnButton = false; //鼠标还没有在按扭之上 m_ToolTip.m_hWnd = NULL; //用于显示按扭的提示信息 *m_szSelTip = 0; *m_szUnSelTip = 0; m_RGBTrans= RGB(0,0,0);//需要去掉背景色的颜色 m_bHandBmp = false; //不需直接从HBITMAP中绘制 m_bHandBmp2 = false; } LuButton::~LuButton() { if (m_dcBk.m_hDC != NULL && m_pbmpOldBk != NULL) { m_dcBk.SelectObject(m_pbmpOldBk); } } BEGIN_MESSAGE_MAP(LuButton, CButton) //{{AFX_MSG_MAP(LuButton) ON_WM_MOUSEMOVE() ON_WM_TIMER() ON_WM_KILLFOCUS() ON_WM_CAPTURECHANGED() ON_WM_ERASEBKGND() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // LuButton message handlers void LuButton::PreSubclassWindow() { UINT nBS; nBS = GetButtonStyle(); // Check if this is the default button //if (nBS & BS_DEFPUSHBUTTON) m_bIsDefault = TRUE; // Add BS_OWNERDRAW style SetButtonStyle(nBS | BS_OWNERDRAW); CButton::PreSubclassWindow(); } void LuButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) { //如果设置为闪动,有时则不需要重画 if ( m_bFlash && m_lFlashCount % 2 != 0 ) { return ; } //取得dc; //CDC* pDC = CDC::FromHandle(lpDIS->hDC); CDC *pdrawDC = CDC::FromHandle(lpDIS->hDC); CMemDC2 memDC(pdrawDC); CDC *pDC = &memDC; CDC pDispDC; pDispDC.CreateCompatibleDC( pDC ); CBitmap * pOldBitmap; //用于存旧的Bitmap BOOL bOldBitmap=false; //是否已把旧的Bitmpa存起来 BITMAP bmpSize; //用于取bmp的大小 BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED); //取得当前状态 BOOL bIsFocused = (lpDIS->itemState & ODS_FOCUS); BOOL bIsDisabled = (lpDIS->itemState & ODS_DISABLED); BOOL bIsSelect = (lpDIS->itemAction & ODA_SELECT ); //char Buf[ 256 ]; //_stprintf( Buf , " %d , %d , %d , %d \n" , bIsPressed , bIsFocused , bIsDisabled , bIsSelect); //TRACE( Buf ); CRect itemRect = lpDIS->rcItem; //第一步先将背景置为淡灰 CBrush brush_LTGRAY( RGB( 192 , 192 , 192 ) ); pDC->FillRect( &itemRect ,&brush_LTGRAY);//将整个背景置为淡灰 if ( bIsDisabled && m_bDisBmp ) //如果按扭已DISABLE及已设置了DISABLE图片 { if (!this->m_bTransBk) { if ( !bOldBitmap ) { pOldBitmap = pDispDC.SelectObject( &m_DisBmp ); bOldBitmap = true; } m_DisBmp.GetBitmap( &bmpSize ); pDC->StretchBlt( itemRect.left , itemRect.top , itemRect.right - itemRect.left , itemRect.bottom - itemRect.top , &pDispDC , 0 , 0 , bmpSize.bmWidth , bmpSize.bmHeight , SRCCOPY ); } else { PaintBk(pDC); this->DrawTransparentBitmap( pDC , itemRect.left , itemRect.top , &m_DisBmp , m_RGBTrans ); } pDispDC.SelectObject( pOldBitmap ); return; } //如果为选中状态 if ( m_bSelect && m_lBmpCount > 0 ) { CBitmap * pTempBmp = NULL; switch( m_lNowBmp ) { case 1: pTempBmp = &m_bmp1; break; case 2: pTempBmp = &m_bmp2; break; case 3: pTempBmp = &m_bmp3; break; case 4: pTempBmp = &m_bmp4; break; case 5: pTempBmp = &m_bmp5; break; default: pTempBmp = &m_bmp1; break; } if (!this->m_bTransBk) { if ( !bOldBitmap ) { pOldBitmap = pDispDC.SelectObject( pTempBmp ); bOldBitmap = true; } pTempBmp->GetBitmap( &bmpSize ); pDC->StretchBlt( itemRect.left , itemRect.top , itemRect.right - itemRect.left , itemRect.bottom - itemRect.top , &pDispDC , 0 , 0 , bmpSize.bmWidth , bmpSize.bmHeight , SRCCOPY ); } else { PaintBk(pDC); this->DrawTransparentBitmap( pDC , itemRect.left , itemRect.top , pTempBmp , m_RGBTrans ); } } else { if ( m_bUnBmp ) { //画未被选中的图片 if (!this->m_bTransBk) { if ( !bOldBitmap ) { pOldBitmap = pDispDC.SelectObject( &m_unBmp ); bOldBitmap = true; } m_unBmp.GetBitmap( &bmpSize ); pDC->StretchBlt( itemRect.left , itemRect.top , itemRect.right - itemRect.left , itemRect.bottom - itemRect.top , &pDispDC , 0 , 0 , bmpSize.bmWidth , bmpSize.bmHeight , SRCCOPY ); } else { PaintBk(pDC); this->DrawTransparentBitmap( pDC , itemRect.left , itemRect.top , &m_unBmp , m_RGBTrans ); } } } if ( m_bMouseOnButton && m_bFlatBmp && !bIsPressed ) //如果鼠标在按扭之上和已设置了浮动图片 { if (!this->m_bTransBk) { if ( !bOldBitmap ) { pDispDC.SelectObject( &m_FlatBmp ); bOldBitmap = true; } m_FlatBmp.GetBitmap( &bmpSize ); pDC->StretchBlt( itemRect.left , itemRect.top , itemRect.right - itemRect.left , itemRect.bottom - itemRect.top , &pDispDC , 0 , 0 , bmpSize.bmWidth , bmpSize.bmHeight , SRCCOPY ); } else { PaintBk(pDC); this->DrawTransparentBitmap( pDC , itemRect.left , itemRect.top , &m_FlatBmp , m_RGBTrans ); } } if ( bIsPressed && m_bClickBmp ) //如果鼠标已按下及已设置了Click图片 { if (!this->m_bTransBk) { if ( !bOldBitmap ) { pDispDC.SelectObject( &m_ClickBmp ); bOldBitmap = true; } m_ClickBmp.GetBitmap( &bmpSize ); pDC->StretchBlt( itemRect.left , itemRect.top , itemRect.right - itemRect.left , itemRect.bottom - itemRect.top , &pDispDC , 0 , 0 , bmpSize.bmWidth , bmpSize.bmHeight , SRCCOPY ); } else { PaintBk(pDC); this->DrawTransparentBitmap( pDC , itemRect.left , itemRect.top , &m_ClickBmp , m_RGBTrans ); } } //直接从HBITMAP中绘制 if ( m_bHandBmp && m_bHandBmp2 ) //直接从HBITMAP中绘制 { CBitmap * pBmp = CBitmap::FromHandle( m_hHandBmp ); //画未被选中的图片 if (!this->m_bTransBk) { if ( !bOldBitmap ) { pOldBitmap = pDispDC.SelectObject( pBmp ); bOldBitmap = true; } pBmp->GetBitmap( &bmpSize ); pDC->StretchBlt( itemRect.left , itemRect.top , itemRect.right - itemRect.left , itemRect.bottom - itemRect.top , &pDispDC , 0 , 0 , bmpSize.bmWidth , bmpSize.bmHeight , SRCCOPY ); } else { PaintBk(pDC); this->DrawTransparentBitmap( pDC , itemRect.left , itemRect.top , pBmp , m_RGBTrans ); } } else { TRACE( _T("No Draw Hand \r\n") ); } if ( m_bMouseOnButton && m_bFlat ) //如果鼠标在按扭之上则需要画 { //CPen p_BLACK(PS_SOLID,1,RGB(0,0,0)); //黑色画笔 CPen p_WHITE(PS_SOLID,1,RGB(255,255,255)); //白色画笔 CPen p_GRAY(PS_SOLID,1,RGB(128,128,128)); //灰色画笔 //CPen p_LTGRAY(PS_SOLID,1,RGB(192,192,192)); //淡灰色画笔 CPen *pOldPen; //用于存旧的Pen if ( !bIsPressed ) //此变量是否是在鼠标下在按下沿未弹起之中 { pOldPen = pDC->SelectObject( &p_WHITE ); //上 pDC->MoveTo( itemRect.left , itemRect.top ); pDC->LineTo( itemRect.right -1, itemRect.top ); //左 pDC->MoveTo( itemRect.left , itemRect.top ); pDC->LineTo( itemRect.left , itemRect.bottom -1); //右 pDC->SelectObject( &p_GRAY ); pDC->MoveTo( itemRect.right -1, itemRect.top ); pDC->LineTo( itemRect.right -1 , itemRect.bottom -1 ); //下 pDC->MoveTo( itemRect.left , itemRect.bottom -1 ); pDC->LineTo( itemRect.right -1, itemRect.bottom -1); } else { pOldPen = pDC->SelectObject( &p_GRAY ); //上 pDC->MoveTo( itemRect.left , itemRect.top ); pDC->LineTo( itemRect.right -1, itemRect.top ); //左 pDC->MoveTo( itemRect.left , itemRect.top ); pDC->LineTo( itemRect.left , itemRect.bottom -1); //右 pDC->SelectObject( &p_WHITE ); pDC->MoveTo( itemRect.right -1, itemRect.top ); pDC->LineTo( itemRect.right -1 , itemRect.bottom -1 ); //下 pDC->MoveTo( itemRect.left , itemRect.bottom -1 ); pDC->LineTo( itemRect.right -1, itemRect.bottom -1); } pDC->SelectObject( pOldPen ); } if (bOldBitmap ) pDispDC.SelectObject( pOldBitmap ); } BOOL LuButton::PreTranslateMessage(MSG* pMsg) { if (m_ToolTip.m_hWnd == NULL) { m_ToolTip.Create(this); m_ToolTip.SetMaxTipWidth(400); m_ToolTip.Activate(FALSE); } m_ToolTip.RelayEvent(pMsg); return CButton::PreTranslateMessage(pMsg); } void LuButton::OnMouseMove(UINT nFlags, CPoint point) { CButton::OnMouseMove(nFlags, point); /* //正在点击 if (nFlags & MK_LBUTTON ) { Invalidate(true); return; } */ if (GetCapture() != this ) { if ( m_bSound ) //发出声音 sndPlaySound( m_szSoundFile , SND_ASYNC ); m_bMouseOnButton = true; SetCapture(); Invalidate(true); } else { POINT p2 = point; ClientToScreen(&p2); CWnd* wndUnderMouse = WindowFromPoint(p2); if (wndUnderMouse != this) { if (m_bMouseOnButton == TRUE) { m_bMouseOnButton = FALSE; Invalidate(); } if (!(nFlags & MK_LBUTTON)) ReleaseCapture(); } } } void LuButton::OnTimer(UINT nIDEvent) { switch( nIDEvent ) { case 1: //如果为选中状态,则需要变换显示的图片 if ( m_bSelect && m_lBmpCount > 0) { m_lNowBmp ++; if ( m_lNowBmp >m_lBmpCount ) m_lNowBmp = 1; this->Invalidate(); } break; case 2: if ( m_bFlash && m_lMaxFlashCount > 0 ) { m_lFlashCount ++; this->Invalidate(); } break; } CButton::OnTimer(nIDEvent); } BOOL LuButton::SetSelTooltip(TCHAR *szText) { if ( szText ) { _stprintf( m_szSelTip , szText ); return true; } else { return false; } } BOOL LuButton::ActiveToolTip(bool bActive) { TCHAR szTipText[ 256 ]; if ( m_bSelect ) _stprintf( szTipText , m_szSelTip ); else _stprintf( szTipText , m_szUnSelTip ); // Initialize ToolTip if (m_ToolTip.m_hWnd == NULL) { // Create ToolTip control m_ToolTip.Create(this); m_ToolTip.SetMaxTipWidth(400); // Create inactive m_ToolTip.Activate(FALSE); } // If there is no tooltip defined then add it if (m_ToolTip.GetToolCount() == 0) { CRect rectBtn; GetClientRect(rectBtn); m_ToolTip.AddTool(this, szTipText, rectBtn, 1); } // Set text for tooltip m_ToolTip.UpdateTipText(szTipText, this, 1); m_ToolTip.Activate(bActive); return true; } BOOL LuButton::SetUnSelToolTip(TCHAR *szText) { if ( szText ) { _stprintf( m_szUnSelTip , szText ); return true; } else { return false; } } BOOL LuButton::SetButtonSel(BOOL bSelect) { m_bSelect = bSelect; if ( m_bSelect ) {//如果当前为选中状态,则需要设时间 if ( m_lBmpCount > 1 ) //只有当总图片数大于1时才认为此按扭为动画的,所以需要设置timer SetTimer( 1 , m_lDHTime , NULL ); } else {//否则将杀死timer,不能留情 KillTimer( 1 ); } ActiveToolTip( true ); this->Invalidate(); return m_bSelect; } BOOL LuButton::GetButtonSel() { return m_bSelect; } long LuButton::AddButtonBmp(UINT nIDResource) { if ( m_lBmpCount >= m_lMaxBmp ) return -1; m_lBmpCount = m_lBmpCount +1; switch( m_lBmpCount ) { case 1: m_bmp1.LoadBitmap( nIDResource );break; case 2: m_bmp2.LoadBitmap( nIDResource );break; case 3: m_bmp3.LoadBitmap( nIDResource );break; case 4: m_bmp4.LoadBitmap( nIDResource );break; case 5: m_bmp5.LoadBitmap( nIDResource );break; } return m_lBmpCount; } long LuButton::AddButtonBmp(LPCTSTR lpszResourceName) { if ( m_lBmpCount >= m_lMaxBmp ) return -1; m_lBmpCount = m_lBmpCount +1; switch( m_lBmpCount ) { case 1: m_bmp1.LoadBitmap( lpszResourceName );break; case 2: m_bmp2.LoadBitmap( lpszResourceName );break; case 3: m_bmp3.LoadBitmap( lpszResourceName );break; case 4: m_bmp4.LoadBitmap( lpszResourceName );break; case 5: m_bmp5.LoadBitmap( lpszResourceName );break; } return m_lBmpCount; } BOOL LuButton::SetUnSelBmp(UINT nIDResource) { if ( !m_bUnBmp ) { m_unBmp.LoadBitmap( nIDResource ); m_bUnBmp = true; return true; } else { m_unBmp.DeleteObject(); m_unBmp.LoadBitmap( nIDResource ); return true; } return false; } BOOL LuButton::SetUnSelBmp(LPCTSTR lpszResourceName ) { if ( !m_bUnBmp ) { m_unBmp.LoadBitmap( lpszResourceName ); m_bUnBmp = true; return true; } else { m_unBmp.DeleteObject(); m_unBmp.LoadBitmap( lpszResourceName ); return true; } return false; } //DEL void LuButton::OnClicked() //DEL { //DEL // if ( m_lBmpCount >0 ) //DEL // SetButtonSel( m_bSelect ? false : true ); //DEL } BOOL LuButton::SetFlat(BOOL bFlat) { BOOL bOldFlat = m_bFlat; m_bFlat = bFlat ; return bOldFlat ; } BOOL LuButton::GetFlat() { return m_bFlat ; } BOOL LuButton::SetSound(bool bSound) { BOOL bOldSound = bSound; m_bSound = bSound; return bOldSound; } BOOL LuButton::SetSoundFileName(TCHAR *szFile) { if ( szFile ) { _stprintf( m_szSoundFile , szFile ); m_bSound = true; return true; } else { return false; } } BOOL LuButton::SetDisableBmp(UINT nIDResource) { if ( !m_bDisBmp ) { m_DisBmp.LoadBitmap( nIDResource ); m_bDisBmp = true; return true; } else { m_DisBmp.DeleteObject(); m_DisBmp.LoadBitmap( nIDResource ); return true; } return false; } BOOL LuButton::SetDisableBmp(LPCTSTR lpszResourceName) { if ( !m_bDisBmp ) { m_DisBmp.LoadBitmap( lpszResourceName ); m_bDisBmp = true; return true; } else { m_DisBmp.DeleteObject(); m_DisBmp.LoadBitmap( lpszResourceName ); return true; } return false; } BOOL LuButton::SetFlatBmp(UINT nIDResource) { if ( !m_bFlatBmp ) { m_FlatBmp.LoadBitmap( nIDResource ); m_bFlatBmp = true; return true; } else { m_FlatBmp.DeleteObject(); m_FlatBmp.LoadBitmap( nIDResource ); return true; } return false; } BOOL LuButton::SetFlatBmp(LPCTSTR lpszResourceName) { if ( !m_bFlatBmp ) { m_FlatBmp.LoadBitmap( lpszResourceName ); m_bFlatBmp = true; return true; } else { m_FlatBmp.DeleteObject(); m_FlatBmp.LoadBitmap( lpszResourceName ); return true; } return false; } BOOL LuButton::SetClickBmp(UINT nIDResource) { if ( !m_bClickBmp ) { m_ClickBmp.LoadBitmap( nIDResource ); m_bClickBmp = true; return true; } else { m_ClickBmp.DeleteObject(); m_ClickBmp.LoadBitmap( nIDResource ); return true; } return false; } BOOL LuButton::SetClickBmp(LPCTSTR lpszResourceName) { if ( !m_bClickBmp ) { m_ClickBmp.LoadBitmap( lpszResourceName ); m_bClickBmp = true; return true; } else { m_ClickBmp.DeleteObject(); m_ClickBmp.LoadBitmap( lpszResourceName ); return true; } return false; } void LuButton::OnKillFocus(CWnd* pNewWnd) { CButton::OnKillFocus(pNewWnd); if ( !m_bFlat && !m_bFlatBmp ) return; if (m_bMouseOnButton == TRUE) { m_bMouseOnButton = FALSE; Invalidate(); } } void LuButton::OnCaptureChanged(CWnd *pWnd) { if (m_bMouseOnButton == TRUE) { ReleaseCapture(); Invalidate(); } CButton::OnCaptureChanged(pWnd); } BOOL LuButton::SetFlash(long lFlashTimer, long lFlashCount, BOOL bFlash) { BOOL bOldFlash = m_bFlash; if ( lFlashCount > 0) { m_lMaxFlashCount = lFlashCount; m_lFlashCount = 0; } else { m_lMaxFlashCount = 0; m_lFlashCount = 0; } if ( lFlashTimer > 0 ) m_lFlashTime = lFlashTimer; m_bFlash = bFlash; if ( m_bFlash ) SetTimer( 2 , m_lFlashTime , NULL ); else KillTimer( 2 ); return bOldFlash; } void LuButton::DrawTransparentBitmap(CDC *pDC, int x, int y, CBitmap * pBmp, COLORREF crColor) // x,y 是要显示的图象的位置,id 是要显示的位图资源的ID // crColor 是要显示位图的背景色 { COLORREF crOldBack=pDC->SetBkColor(RGB(255,255,255)); COLORREF crOldText=pDC->SetTextColor(RGB(0,0,0)); CDC dcImage,dcMask; //CBitmap bmp; BITMAP bm; //bmp.LoadBitmap(id); //bmp.LoadBitmap(129); //bmp.CreateBitmapIndirect(pBmp); //bmp.FromHandle( (HBITMAP)pBmp ); //bmp = *pBmp pBmp->GetBitmap(&bm); int nWidth=bm.bmWidth,nHeight=bm.bmHeight; dcImage.CreateCompatibleDC(pDC); dcMask.CreateCompatibleDC(pDC); CBitmap * pOldBitmapImage=dcImage.SelectObject(pBmp); CBitmap bitmapMask; bitmapMask.CreateBitmap(nWidth,nHeight,1,1,NULL); CBitmap * pOldBitmapMask=dcMask.SelectObject(&bitmapMask); dcImage.SetBkColor(crColor); dcMask.BitBlt(0,0,nWidth,nHeight,&dcImage,0,0,SRCCOPY); pDC->BitBlt(x,y,nWidth,nHeight,&dcImage,0,0,SRCINVERT); pDC->BitBlt(x,y,nWidth,nHeight,&dcMask,0,0,SRCAND); pDC->BitBlt(x,y,nWidth,nHeight,&dcImage,0,0,SRCINVERT); dcImage.SelectObject(pOldBitmapImage); dcMask.SelectObject(pOldBitmapMask); pDC->SetBkColor(crOldBack); pDC->SetTextColor(crOldText); } BOOL LuButton::SetTransBK(BOOL bTransBk) { BOOL bOldTransBk = m_bTransBk; m_bTransBk = bTransBk ; return bOldTransBk ; } long LuButton::SetTransBKColor(COLORREF rgbColor) { long lOldTransColor = m_RGBTrans; m_RGBTrans = rgbColor; return lOldTransColor; } long LuButton::SetDHTime( long lDHTime ) { long lOldTime = m_lDHTime; m_lDHTime = lDHTime; return lOldTime; } BOOL LuButton::SetWindowRgnFromBmp(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance) { HRGN hRgn = NULL; BITMAP bm; if (hBmp) { // Create a memory DC inside which we will scan the bitmap content HDC hMemDC = CreateCompatibleDC(NULL); if (hMemDC) { // Get bitmap size //BITMAP bm; GetObject(hBmp, sizeof(bm), &bm); // Create a 32 bits depth bitmap and select it into the memory DC BITMAPINFOHEADER RGB32BITSBITMAPINFO = { sizeof(BITMAPINFOHEADER), // biSize bm.bmWidth, // biWidth; bm.bmHeight, // biHeight; 1, // biPlanes; 32, // biBitCount BI_RGB, // biCompression; 0, // biSizeImage; 0, // biXPelsPerMeter; 0, // biYPelsPerMeter; 0, // biClrUsed; 0 // biClrImportant; }; VOID * pbits32; HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0); if (hbm32) { HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32); // Create a DC just to copy the bitmap into the memory DC HDC hDC = CreateCompatibleDC(hMemDC); if (hDC) { // Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits) BITMAP bm32; GetObject(hbm32, sizeof(bm32), &bm32); while (bm32.bmWidthBytes % 4) bm32.bmWidthBytes++; // Copy the bitmap into the memory DC HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp); BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY); // For better performances, we will use the ExtCreateRegion() function to create the // region. This function take a RGNDATA structure on entry. We will add rectangles by // amount of ALLOC_UNIT number in this structure. #define ALLOC_UNIT 100 DWORD maxRects = ALLOC_UNIT; HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects)); RGNDATA *pData = (RGNDATA *)GlobalLock(hData); pData->rdh.dwSize = sizeof(RGNDATAHEADER); pData->rdh.iType = RDH_RECTANGLES; pData->rdh.nCount = pData->rdh.nRgnSize = 0; SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); // Keep on hand highest and lowest values for the "transparent" pixels BYTE lr = GetRValue(cTransparentColor); BYTE lg = GetGValue(cTransparentColor); BYTE lb = GetBValue(cTransparentColor); BYTE hr = min(0xff, lr + GetRValue(cTolerance)); BYTE hg = min(0xff, lg + GetGValue(cTolerance)); BYTE hb = min(0xff, lb + GetBValue(cTolerance)); // Scan each bitmap row from bottom to top (the bitmap is inverted vertically) BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes; for (int y = 0; y < bm.bmHeight; y++) { // Scan each bitmap pixel from left to right for (int x = 0; x < bm.bmWidth; x++) { // Search for a continuous range of "non transparent pixels" int x0 = x; LONG *p = (LONG *)p32 + x; while (x < bm.bmWidth) { BYTE b = GetRValue(*p); if (b >= lr && b <= hr) { b = GetGValue(*p); if (b >= lg && b <= hg) { b = GetBValue(*p); if (b >= lb && b <= hb) // This pixel is "transparent" break; } } p++; x++; } if (x > x0) { // Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region if (pData->rdh.nCount >= maxRects) { GlobalUnlock(hData); maxRects += ALLOC_UNIT; hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE); pData = (RGNDATA *)GlobalLock(hData); } RECT *pr = (RECT *)&pData->Buffer; SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1); if (x0 < pData->rdh.rcBound.left) pData->rdh.rcBound.left = x0; if (y < pData->rdh.rcBound.top) pData->rdh.rcBound.top = y; if (x > pData->rdh.rcBound.right) pData->rdh.rcBound.right = x; if (y+1 > pData->rdh.rcBound.bottom) pData->rdh.rcBound.bottom = y+1; pData->rdh.nCount++; // On Windows98, ExtCreateRegion() may fail if the number of rectangles is too // large (ie: > 4000). Therefore, we have to create the region by multiple steps. if (pData->rdh.nCount == 2000) { HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData); if (hRgn) { CombineRgn(hRgn, hRgn, h, RGN_OR); DeleteObject(h); } else hRgn = h; pData->rdh.nCount = 0; SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); } } } // Go to next row (remember, the bitmap is inverted vertically) p32 -= bm32.bmWidthBytes; } // Create or extend the region with the remaining rectangles HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData); if (hRgn) { CombineRgn(hRgn, hRgn, h, RGN_OR); DeleteObject(h); } else hRgn = h; // Clean up SelectObject(hDC, holdBmp); DeleteDC(hDC); } DeleteObject(SelectObject(hMemDC, holdBmp)); } DeleteDC(hMemDC); } } if ( hRgn ) { CRect rect; this->GetWindowRect( &rect); //this->ClientToScreen(&rect); this->MoveWindow( rect.left , rect.top , bm.bmWidth , bm.bmHeight ); this->SetWindowRgn( hRgn , true); return true; } return false; } void LuButton::PaintBk(CDC *pDC) { CClientDC clDC(GetParent()); //CPaintDC clDC(m_pMainWnd); //CDC clDC(this->GetParent() ); //CDC * p2DC =GetParent()->GetDC(); CRect rect; CRect rect1; GetClientRect(rect); GetWindowRect(rect1); GetParent()->ScreenToClient(rect1); if (m_dcBk.m_hDC == NULL) { m_dcBk.CreateCompatibleDC(&clDC); m_bmpBk.CreateCompatibleBitmap(&clDC, rect.Width(), rect.Height()); m_pbmpOldBk = m_dcBk.SelectObject(&m_bmpBk); m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), &clDC, rect1.left, rect1.top, SRCCOPY); } pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcBk,0,0, SRCCOPY); } void LuButton::SetMainWin(CWnd *pWnd) { m_pMainWnd = pWnd; } BOOL LuButton::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default return false; //return CButton::OnEraseBkgnd(pDC); } BOOL LuButton::SetWindowRgnFromBmp(UINT uiBmp, COLORREF cTransparentColor, COLORREF cTolerance) { CBitmap bmp; if ( bmp.LoadBitmap( uiBmp ) ) { SetWindowRgnFromBmp((HBITMAP)bmp , cTransparentColor , cTolerance ); return true; } else return false; } void LuButton::SetHandBmp(HBITMAP hBmp) { m_bHandBmp = true; m_bHandBmp2 = true; m_hHandBmp = hBmp; } void LuButton::SetHandBmp(BOOL bTrue) { m_bHandBmp = bTrue; m_bHandBmp2 = bTrue; }