Custom Image Button

Discussion in 'C++' started by shabbir, Nov 27, 2007.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83

    Steps to integrate code into your programs



    This is an easy and flexible way to use bitmaps as buttons in your application, and here are the detail steps of how you can add the custom button to your application.

    1. Create a new MFC AppWizard (exe) based project and name it as BtnSample

      [​IMG]

    2. Select dialog based and click on Finish

      [​IMG]

    3. You will see the following dialog and click on OK button

      [​IMG]

    4. After some progress bars you will see the following project created for you.

      [​IMG]

    5. Now Add a button to the Dialog Application from the Control Toolbox

      [​IMG]

    6. Now Copy the GuiButton.h and GuiButton.cpp files from the attachment into your project location and Add the files to the workspace.

      [​IMG]

    7. Add a variable to the button using the class wizard and keep the variable type as CButton

      [​IMG]

    8. Open BtnSampleDlg.h and change the variable type you have created in the above step from CButton to CGuiButton and add the
      Code:
      #include "GuiButton.h"
      at the top of the file.
    9. Now copy the bitmap you would like to use for your button and add import the bitmap resource into the project

      [​IMG]

    10. Finally add the following line in the OnInitDialog of your dialog in the file BtnSampleDlg.cpp. Remember to skip the About Dialog classes.
      Code:
      m_btn.SetSkin(IDB_BITMAP1);
    11. If you have successfully done all the steps try compiling and runing the program and you should see

      [​IMG]

    What is it in the code ...



    This was all about running the program and integrating the GuiButton into your project but what is there in the GuiButton I will try to explain that as well.
    First the SetSkin function.
    Code:
    /////////////////////////////////////////////////////////////////////////
    /// <b>Function: SetSkin</b>
    ///
    /// \param	uiNormal	(in) Normal Bitmap ID
    ///
    /// \param	uiDisabled	(in) Disabled Bitmap ID
    ///
    /// \param	clrTextColor	(in) Text Color where default color is white
    ///
    /// \return	void 
    ///
    /// \remarks	Sets the skin to the button
    ///
    /////////////////////////////////////////////////////////////////////////
    void CGuiButton::SetSkin(UINT uiNormal, UINT uiDisabled, COLORREF clrTextColor)
    {
    	TRACE(TEXT("CGuiButton::SetSkin\n"));
    	// --------------------------------------
    	// Free previous allocated bitmaps
    	// --------------------------------------
    	m_NormalBitmapDC.DeleteObject();
    	m_DisabledBitmapDC.DeleteObject();
    
    	// --------------------------------------
    	// Load bitmaps corresponding to states
    	// --------------------------------------
    	if (uiNormal>0) 
    		m_NormalBitmapDC.LoadBitmap(uiNormal);
    	if (uiDisabled>0) 
    		m_DisabledBitmapDC.LoadBitmap(uiDisabled);
    
    	m_TextColor = clrTextColor;
    }
    
    I hope the code is pretty much self explanatory.

    Now some of the overridden methods and what they do.
    Code:
    /////////////////////////////////////////////////////////////////////////
    /// <b>Function: PreSubclassWindow</b>
    ///
    /// \param	NONE
    ///
    /// \return	void 
    ///
    /// \remarks	PreSubclassWindow to make the button is Owner Draw.
    ///
    /////////////////////////////////////////////////////////////////////////
    void CGuiButton::PreSubclassWindow() 
    {
    	CButton::PreSubclassWindow();
    
    	// Modifying the style to OwnerDraw
    	ModifyStyle(0, BS_OWNERDRAW );
    
    }
    
    
    /////////////////////////////////////////////////////////////////////////
    /// <b>Function: OnEraseBkgnd</b>
    ///
    /// \param	pDC	(in\out)
    ///
    /// \return	BOOL 
    ///
    /// \remarks	We do not want the base class to erase the background.
    ///
    /////////////////////////////////////////////////////////////////////////
    BOOL CGuiButton::OnEraseBkgnd(CDC* pDC) 
    {
    	// Do not erase background to be transparent
    	return true; 
    }
    
    
    /////////////////////////////////////////////////////////////////////////
    /// <b>Function: OnKillFocus</b>
    ///
    /// \param	pNewWnd	(in)
    ///
    /// \return	void 
    ///
    /// \remarks	Validates the button so that the Focus rect is removed 
    ///             correctly
    ///
    /////////////////////////////////////////////////////////////////////////
    void CGuiButton::OnKillFocus(CWnd* pNewWnd)
    {
    	this->Invalidate();
    }
    
    and each of them is well documented.

    Now the main function DrawItem
    Code:
    
    /////////////////////////////////////////////////////////////////////////
    /// <b>Function: DrawItem</b>
    ///
    /// \param	lpDrawItemStruct	(in\out)
    ///
    /// \return	void 
    ///
    /// \remarks	Draws the button in 3 steps
    ///             1. Bitmap     - Draws the loaded bitmap
    ///             2. Text       - Draws the button text
    ///             3. Focus Rect - Draws the focus rect of the button
    ///
    /////////////////////////////////////////////////////////////////////////
    void CGuiButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
        [URL=http://www.go4expert.com/articles/c-cpp-assert-function-t27488/]ASSERT[/URL] (lpDrawItemStruct);
    
    	CDC btnDC ;
    	btnDC.Attach(lpDrawItemStruct->hDC);	// get device context
    
    	CBitmap* pbitmapDC=NULL;
    	BITMAP bmpStruct;
    
    	CRect btnRect;
    	GetClientRect(&btnRect);
    
    	// --------------------------------------
    	// Draw the bitmap
    	// --------------------------------------
    	
    	// Get the correct Bitmap
    	if(! IsWindowEnabled())
    		pbitmapDC=&m_DisabledBitmapDC;
    	else
    		pbitmapDC=&m_NormalBitmapDC;
    	
    	// Select the bitmap into a Compatible DC
    	CDC *bmpDC = new CDC();
    	bmpDC->CreateCompatibleDC(&btnDC);
    	bmpDC->SelectObject(pbitmapDC);
    
    	if(pbitmapDC != NULL)
    	{
    		pbitmapDC->GetBitmap(&bmpStruct);
    		const int iDiff = 1;
    		// Draw the bitmap on the button leaving one pixel from each side of the button
    		btnDC.StretchBlt(iDiff, iDiff, btnRect.Width()-(2*iDiff), btnRect.Height()-(2*iDiff),bmpDC,0,0,bmpStruct.bmWidth,bmpStruct.bmHeight, SRCCOPY );
    	}
    
    	// --------------------------------------
    	// Draw the Text
    	// --------------------------------------
    
    	CString sCaption;
    	GetWindowText(sCaption);	// get button text
    
    	int iLength = sCaption.GetLength();
    
    	CRect textRect;
    	textRect = lpDrawItemStruct->rcItem;
    
    	int       oldMode = btnDC.SetBkMode(TRANSPARENT);
    	COLORREF oldColor = btnDC.SetTextColor(m_TextColor);
    
    	CSize sz;
    	sz = btnDC.GetTextExtent(sCaption);
     
    	BOOL bNoOfLines = FALSE; 
    	UINT uiDrawTextFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE;
    	
    	int iOffset = btnDC.DrawText(sCaption,textRect,uiDrawTextFormat);
    	
    	
    	// --------------------------------------
    	// Draw the Focus Rect
    	// --------------------------------------
    	if( (iLength)  && (lpDrawItemStruct->itemState & ODS_FOCUS) )
    	{
    		CRect focusRect( btnRect );
    		focusRect.InflateRect(-1,-1,-1,-1);
    		btnDC.DrawFocusRect(&focusRect);
    	}
    
    	btnDC.SetTextColor(oldColor) ;
    	btnDC.SetBkMode(oldMode) ;
    	btnDC.Detach() ;	
    	
    }
    
    Its also well explained and here is the quote from the comment
    You can download the attached sample and run the program.
     

    Attached Files:

    Last edited: Jan 21, 2017
    1 person likes this.
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
  3. skynetto

    skynetto New Member

    Joined:
    Dec 30, 2007
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    any chance of using an external image with LoadImage? SetSkin is expecting an UINT and LoadImage gives me a HANDLE or at least a HBITMAP
     
  4. skynetto

    skynetto New Member

    Joined:
    Dec 30, 2007
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    OK got just have to modify what setskin is expecting of and change the LoadBitmap reference on guibutton.cpp
     
  5. sampathkambar

    sampathkambar New Member

    Joined:
    Jan 25, 2008
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    What if,i want that button to be created dynamically..... what shall i do at that time.
    Thanks in advance...
     
  6. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Just make the object of the Custom button and specify the property as and when needed.
     
  7. CasualProgrammer

    CasualProgrammer New Member

    Joined:
    Jul 10, 2009
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Hello -

    Is there a later release of this?

    In GuiButton.cpp at line 229 (or so), there's:

    CDC *bmpDC = new CDC();

    But there is no corresponding "delete bmpDC" from that point to the end of the function. This produces a small (what, 16-byte?) memory leak each time the button is pressed.

    Casual
     
  8. nasko700

    nasko700 New Member

    Joined:
    Sep 17, 2009
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Hi! I find that if you drag the window (where is also your imageButton) out of the monitor's sizes and then drag it back, the image is not there anymore. I think, I have to use serialization, or?
     
  9. sammor

    sammor New Member

    Joined:
    Aug 2, 2010
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    HI,
    I have 6 buttons with images,
    when I launch the application, no problems,
    when I click on some buttons, some Buttons disappear.
    I am using it in CE 6.00 environment
    Thanks
     
  10. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    May be some paint issues.
     
  11. sammor

    sammor New Member

    Joined:
    Aug 2, 2010
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    what do u mean by paint issues,
    The image is a BMP format created by Paint as 24-bit bitmap. is something wrong with that?
     
  12. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    No but to use any image as control you need to paint that image in the Paint message handler.
     
  13. sammor

    sammor New Member

    Joined:
    Aug 2, 2010
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    I paint the images in the paint message handler,
    when launching, all the images are showing, then when clicking on one, others disappear
     
  14. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    It actually means there is some issue with painting and try moving the window and see if it comes back again
     
  15. ganesh kumar

    ganesh kumar New Member

    Joined:
    Oct 10, 2010
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    Hi all,
    I could not find the GuiButton.h and GuiButton.cpp from the zip file. Could any give me the proper file.
     
  16. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Then what did the zip file contain?
     
  17. ganesh kumar

    ganesh kumar New Member

    Joined:
    Oct 10, 2010
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    Hello shabbir,
    When i open the zip file, it contain GuiButton.file. I cannot open that file.
     
  18. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    I re-downloaded the stuff and things work normal for me. If you have issues PM me your email address and I will try sending you the files to your email address.
     
  19. ganesh kumar

    ganesh kumar New Member

    Joined:
    Oct 10, 2010
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
  20. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Sent and do let me know if you still have any issues.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice