4/22/09

c++ Hover button with two state images left and right

In this c++ example hover button with two state images is based on the example
http://www.codeproject.com/KB/buttons/Cool_Buttons.aspx in codeproject.com

I deleted unnecessary codes and I added my stuff to it
I could not use SetStatus function so I wrote it every time I use it( 2 line functions)
Every thing that does not make changes I omitted it

DOWNLOAD
The downloads contains complete file plus the exe in the folder of debug

The idea and the theme of this project is to have a button with two state hover
like the one shown in the images below,











The first image is when the mouse cursor on the right side and the second one is when the cursor is over the left side

These depend on the location of mouse cursor

To expand this project you can make multifunction buttons or double function buttons

or multiple hover button or another thing to add is to use 2 tooltips for a single button



1-Start visualc++ project MFC Application wizard let name a weird name tasho or tashi if you like and Chose Dialog and Deselct about Box and activeX controls ( no need for them)
and deselect compiler comments generated by the compiler

2-Rename the Dialog resource ID to IDD_TASHO_DIALOG

3-Add the following bitmap resources to resources go to resource View and Insert Insert Bitmap
and draw 5 bitmaps as shown here



anyway Send me better if you can




Make the images of size 40 120

chose id for the bitmaps IDB_NORMAL ,IDB_LEFT ,IDB_RIGHT ,IDB CLICKED ,IDB_DOWN
note that IDB CLICKED is currently unused but it will be used in future programs
4- In the insert menu Insert new class MFC class Chose Cbutton as the base class for it and Name it CCoolButton
5- Add the following data members to the newly created class
and make them public

CBitmap m_bmp_normal ,m_bmp_left ,m_bmp_right ,m_bmp_clicked ,m_bmp_down;
enum ButtonStatus { NORMAL ,LEFT ,RIGHT ,CLICKED ,DOWN};
ButtonStatus m_old_status ,m_current_status ;

6-In the newly created class
Add the following constructor . five elements
as follows '
CCoolButton::CCoolButton(int nidNormal, int nidleft, int nidright, int nidclicked, int niddown)
{
m_current_status = NORMAL ;

m_bmp_normal.LoadBitmap(nidNormal);
m_bmp_left.LoadBitmap(nidleft);
m_bmp_right.LoadBitmap(nidright);
m_bmp_clicked.LoadBitmap(nidclicked);
m_bmp_down.LoadBitmap(niddown);

}

7- Add the 2 windows messege handler and edit them as follows
first OnleftbuttonDown

void CCoolButton::OnLButtonDown(UINT nFlags, CPoint point)
{
m_old_status = m_current_status ;
m_current_status = DOWN ;
SetCapture();

CButton::OnLButtonDown(nFlags, point);
}

and OnleftbuttonUp

void CCoolButton::OnLButtonUp(UINT nFlags, CPoint point)
{


CRect totalrect ;
GetClientRect(&totalrect);
CRect left = totalrect;
left.DeflateRect(60,0);
if( PtInRect(totalrect,point))
{
if(PtInRect(left ,point))
{
m_old_status = m_current_status ;

m_current_status = RIGHT ;
ReleaseCapture();
}
else {
m_old_status = m_current_status ;

m_current_status = LEFT ;
ReleaseCapture();

}}
else
m_old_status = m_current_status ;

m_current_status = NORMAL ;
ReleaseCapture();

CButton::OnLButtonUp(nFlags, point);
}


and OnMouseMove as follows

void CCoolButton::OnMouseMove(UINT nFlags, CPoint pnt)
{

CRect buttonrect , leftrect ;

GetWindowRect(buttonrect);
leftrect = buttonrect;
leftrect.DeflateRect(60 ,0);


if (m_current_status ==DOWN )
{

if( sRect(buttonrect ,pnt ))
{
Invalidate(FALSE) ; }

else{

m_old_status = m_current_status ;
m_current_status = CLICKED ;
Invalidate(FALSE) ;
}}


else if (m_old_status == DOWN && (PtInRect(buttonrect,pnt)))
{
m_old_status = m_current_status ;
m_current_status = DOWN ;
}



else {
if(sRect ( buttonrect, pnt ))

{if(sRect(leftrect , pnt))
{
m_old_status =m_current_status ;
m_current_status = LEFT ;
Invalidate(FALSE);
}
else

{

m_old_status =m_current_status ;
m_current_status = RIGHT ;
Invalidate(FALSE);


}
}


else {
m_old_status =m_current_status ;
m_current_status = NORMAL ;
Invalidate(FALSE);



}
}




TRACKMOUSEEVENT tm_Event ;
tm_Event.dwFlags = TME_LEAVE ;
tm_Event.hwndTrack = m_hWnd ;
tm_Event.cbSize =sizeof(TRACKMOUSEEVENT) ;


_TrackMouseEvent(& tm_Event );

CButton::OnMouseMove(nFlags, pnt);



}
As you can see I could not use SetStatus in the original example

Also add the virtual function DrawItem

void CCoolButton::DrawItem(LPDRAWITEMSTRUCT lp_di_struct)
{


CDC *DrawDc = CDC::FromHandle(lp_di_struct->hDC);
CBitmap * pOldBitmap ;
CDC membtmDC ;
membtmDC.CreateCompatibleDC(DrawDc) ;


switch( m_current_status)
{
case NORMAL :
pOldBitmap = membtmDC.SelectObject( & m_bmp_normal) ;
break ;

case LEFT:
pOldBitmap = membtmDC.SelectObject(& m_bmp_left);
break ;
case RIGHT :

pOldBitmap = membtmDC.SelectObject(& m_bmp_right);
break ;

case DOWN :
pOldBitmap = membtmDC.SelectObject(& m_bmp_down);
break ;


case CLICKED :
pOldBitmap = membtmDC.SelectObject(& m_bmp_clicked);
break ;

}




DrawDc->BitBlt(0,0, lp_di_struct->rcItem.right -lp_di_struct->rcItem.left , lp_di_struct->rcItem.bottom - lp_di_struct->rcItem.top , &membtmDC,0,0,SRCCOPY);


membtmDC.SelectObject(pOldBitmap);

membtmDC.DeleteDC();


}
As you can see it is almost the same as in the original example but there is 5 switch statements instead of 3 because we have here 5 bimaps notice I altered some names

Then add new function and name it sRect of type BOOL
BOOL CCoolButton::sRect(CRect &rct, CPoint &pnt)
{

return(pnt.x> 0 && pnt.x< (rct.right -rct.left) && pnt.y>0 && pnt.y< (rct.bottom -rct.top) )?TRUE :FALSE ; }


And finally add new function OnMouseLeave and edit as follows

void CCoolButton::OnMouseLeave()
{
m_old_status = m_current_status ;

m_current_status = NORMAL ;
Invalidate();

}

Since this function is part of CWnd class add the following to BeginMessageMap
ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
under
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
in ur class cpp file


Now we finished CCoolButton we move to the dialog class CTashoDlg
class

8-In the dialog resource make In the class wizard Add member variable chose the Ok button chose variable type CCoolButton and let us chose a name for it m_mono or anything you like and do not forget to add #include "CoolButton.h" in your dialog class header file

9-In the InitDialog Add the following code snippet

SetWindowText("hiee");
UpdateData(FALSE);
m_mono.MoveWindow( 30,45,150,90);


10- Delete the original constructor and replace it with the following constructor with no arguments
CTashoDlg::CTashoDlg() :CDialog(IDD_TASHO_DIALOG,NULL), m_mono(IDB_NORMAL ,IDB_LEFT ,IDB_RIGHT ,IDB_CLICKED ,IDB_DOWN)
{
}


11- Build the application and see the result

My next project would be a button with 2 ToolTips one on the left and one on the right I hope that you enjoyed it and benefited from it /.......

for more tutorials see other posts in the blog

It is hard and I made it loll

If you have any comment and any ideas you want to share leave it below :!~