CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 36

Threaded View

  1. #30
    Join Date
    Jan 2006
    Location
    Marseille, France
    Posts
    94

    Lightbulb Re: MFC : Make a bitmap with a transparant color

    Last Update

    I just modify the source code to get automatically it's parent window's image

    Code:
    #pragma once
    #include "afxext.h"
    
    class CTransparentBitmapButton :
    	public CBitmapButton
    {
    private:
    	void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap);
    
    	// The colour inside this button's bitmap(s) that should be regarded as transparent
    	// is selected by the one of the pixel locate by X, Y
    	int m_iXPxlTranparent, m_iYPxlTranparent;
    
    	CBitmap m_BitmapBackground;
    	BOOL	m_HasBackGround;
    
    public:
    	CTransparentBitmapButton(int XPxlT, int YPxlT);
    	~CTransparentBitmapButton(void);
    
    	//virtual void OnPaint();
    	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    	DECLARE_MESSAGE_MAP()
    	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    
    protected:
    	virtual void PreSubclassWindow();
    };
    
    
    
    
    
    
    
    
    #include "StdAfx.h"
    #include ".\transparentbitmapbutton.h"
    
    BEGIN_MESSAGE_MAP(CTransparentBitmapButton, CBitmapButton)
    	ON_WM_ERASEBKGND()
    END_MESSAGE_MAP()
    
    CTransparentBitmapButton::CTransparentBitmapButton(int XPxlT,int YPxlT)
    {
    	// Initialise the transparent pixel X,Y
    	m_iXPxlTranparent = XPxlT;
    	m_iYPxlTranparent = YPxlT;
    
    	m_HasBackGround = FALSE;
    }
    
    CTransparentBitmapButton::~CTransparentBitmapButton(void)
    {
    }
    
    void CTransparentBitmapButton::PreSubclassWindow() 
    {
    	CBitmapButton::PreSubclassWindow();
    
    	CWnd *pParent = GetParent();
    	if (pParent)
    	{	   
    		CRect Rect;
    		GetClientRect(&Rect);
    		ClientToScreen(&Rect);
    		pParent->ScreenToClient(&Rect);
    		CDC *pDC = pParent->GetDC();
    		m_BitmapBackground.CreateCompatibleBitmap(pDC,Rect.Width(),Rect.Height());	  
    	}
    }
    
    BOOL CTransparentBitmapButton::OnEraseBkgnd(CDC* pDC)
    {
    	if (!m_HasBackGround)
    	{
    		CWnd *pParent = GetParent();
    		if (pParent)
    		{
    			CRect Rect;
    			GetClientRect(&Rect);
    			ClientToScreen(&Rect);
    			pParent->ScreenToClient(&Rect);
    			CDC *pDC = pParent->GetDC();
    			CDC memdc;
    			memdc.CreateCompatibleDC(pDC);
    			CBitmap *oldbmp = memdc.SelectObject(&m_BitmapBackground);
    			memdc.BitBlt(0,0,Rect.Width(),Rect.Height(),pDC,Rect.left,Rect.top,SRCCOPY);
    			memdc.SelectObject(oldbmp);
    			m_HasBackGround = TRUE;
    			pParent->ReleaseDC(pDC);
    		}
    	}
    	   
    	return TRUE;
    }
    
    /*
    // From 'OnPaint()
    void CTransparentBitmapButton::OnPaint() 
    {
    	if ((GetParent()) && (GetParent()->IsIconic()))
    	{
    		CBitmapButton::OnPaint();
    	}
    	else
    	{
    		CPaintDC dc(this); // device context for painting
    		
    		// At least onw bitmap must be loaded before calling 'Paint()'
    		ASSERT(m_bitmap.m_hObject != NULL);
    
    		// and we'll assume until we find otherwise, that
    		// the button is being drawn in its normal state.
    		CBitmap* pBitmap = &m_bitmap;
    
    		if ((!(IsWindowEnabled())) && (NULL != m_bitmapDisabled.m_hObject))
    			pBitmap = &m_bitmapDisabled;
    
    		DrawTransparentBitmap(dc.m_hDC, *pBitmap);
    	}
    }
    */
    
    void CTransparentBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    	ASSERT(lpDrawItemStruct != NULL);
    
    	// At least onw bitmap must be loaded before calling 'DrawItem()'
    	ASSERT(m_bitmap.m_hObject != NULL);
    
    	CBitmap* pBitmap = &m_bitmap;
    	UINT state = lpDrawItemStruct->itemState;
    
    	if ((state & ODS_SELECTED) && (NULL != m_bitmapSel.m_hObject))
    		pBitmap = &m_bitmapSel;
    	else if ((state & ODS_FOCUS) && (NULL != m_bitmapFocus.m_hObject))
    		pBitmap = &m_bitmapFocus;
    	else if ((state & ODS_DISABLED) && (NULL != m_bitmapDisabled.m_hObject))
    		pBitmap = &m_bitmapDisabled;
    
    	DrawTransparentBitmap(lpDrawItemStruct->hDC, *pBitmap);
    }
    
    void CTransparentBitmapButton::DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap)
    {
    BITMAP	bm;
    COLORREF cColour;
    HBITMAP	bmAndBack, bmAndObject, bmAndMem, bmSave;
    HBITMAP	bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
    HDC		hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
    POINT		ptSize;
    
    
    	hdcTemp = CreateCompatibleDC(hdc);
    	if (HGDIOBJ hOldObj = SelectObject(hdcTemp, hBitmap)) // Select the bitmap
    		DeleteObject(hOldObj);
    
    	GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
    	ptSize.x = bm.bmWidth;		  // Get width of bitmap
    	ptSize.y = bm.bmHeight;		  // Get height of bitmap
    	DPtoLP(hdcTemp, &ptSize, 1); // Convert from device  to logical points
    
    	// Create some DCs to hold temporary data.
    	hdcBack	 = CreateCompatibleDC(hdc);
    	hdcObject = CreateCompatibleDC(hdc);
    	hdcMem	 = CreateCompatibleDC(hdc);
    	hdcSave	 = CreateCompatibleDC(hdc);
    
    	// 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(hdc, ptSize.x, ptSize.y);
    	bmSave = CreateCompatibleBitmap(hdc, 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(hdc));
    
    	// Save the bitmap sent here, because it will be overwritten.
    	BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
    
    	COLORREF transparentColour = GetPixel(hdcTemp, m_iXPxlTranparent, m_iYPxlTranparent);
    
    	if (transparentColour) cColour = SetBkColor(hdcTemp, transparentColour);
    
    	// 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);
    
    	SetBkColor(hdcTemp, cColour);
    	
    	// 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.
    	if (m_HasBackGround)
    	{	
    		CDC MemDC;
    		CDC* pDC = CDC::FromHandle(hdc) ;
    		
    		BITMAP InfosBmp;
    		m_BitmapBackground.GetBitmap(&InfosBmp);
    		MemDC.CreateCompatibleDC(pDC);
    		MemDC.SelectObject(&m_BitmapBackground);
    		BitBlt(hdcMem, 0, 0, InfosBmp.bmWidth, InfosBmp.bmHeight, MemDC, 0, 0, SRCCOPY);
    
    		DeleteDC(MemDC);
    	}
    	else
    	{
    		BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, 0, 0, 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 coloured 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(hdc, 0, 0, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);
    
    	// Place the original bitmap back into the bitmap sent here.
    	BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, 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);
    }
    Last edited by FireJocker; February 21st, 2006 at 09:05 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured