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. Create a new MFC AppWizard (exe) based project and name it as BtnSample Select dialog based and click on Finish You will see the following dialog and click on OK button After some progress bars you will see the following project created for you. Now Add a button to the Dialog Application from the Control Toolbox Now Copy the GuiButton.h and GuiButton.cpp files from the attachment into your project location and Add the files to the workspace. Add a variable to the button using the class wizard and keep the variable type as CButton 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. Now copy the bitmap you would like to use for your button and add import the bitmap resource into the project 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); If you have successfully done all the steps try compiling and runing the program and you should see 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.
I have reported the article for Nominate your favorite article of the month for November 2007. Add your nominations as well.
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
OK got just have to modify what setskin is expecting of and change the LoadBitmap reference on guibutton.cpp
What if,i want that button to be created dynamically..... what shall i do at that time. Thanks in advance...
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
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?
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
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?
I paint the images in the paint message handler, when launching, all the images are showing, then when clicking on one, others disappear
It actually means there is some issue with painting and try moving the window and see if it comes back again
Hi all, I could not find the GuiButton.h and GuiButton.cpp from the zip file. Could any give me the proper file.
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.