Search code examples
c++mfchoverbackground-colorcbutton

How to change BackgroundColor OnMouseHover c++ MFC


I've derived a Window from CWnd in which I create some OwnerDrawn Buttons. The Buttons are derived from CButton.

Now I want to change to BackgroundColor of my Buttons when the User is Hovering over it.

Therefore I already implemented that the OnMouseHover() and the OnMouseLeave() Messages are getting sent:

BEGIN_MESSAGE_MAP(CFooterButton, CButton)
   ON_WM_MOUSEHOVER()
   ON_WM_MOUSEMOVE()
   ON_WM_MOUSELEAVE()
END_MESSAGE_MAP()

void CFooterButton::OnMouseMove(UINT nFlags, CPoint point)
{

   //start tracking of Hover and Leave Event
   TRACKMOUSEEVENT tme;
   tme.cbSize = sizeof(TRACKMOUSEEVENT);
   tme.dwFlags = TME_HOVER | TME_LEAVE;
   tme.hwndTrack = m_hWnd;
   tme.dwHoverTime = HOVER_DEFAULT;
   TrackMouseEvent(&tme);

   CButton::OnMouseMove(nFlags, point);
}


void CFooterButton::OnMouseHover(UINT nFlags, CPoint point)
{


   HDC hdc = *GetWindowDC();

   SetBkColor(hdc,RGB(54, 125, 184));
   CButton::OnMouseHover(nFlags, point);
}

In the Debugger and Spy I can see that the code is getting called but nothing happens. Since I'm relatively new to MFC/c++ I assume I'm not using the DC correctly.. can someone explain me why it is not working and how i can fix it?


Solution

  • For anyone else who is struggling my Solution:

    • Create a member bool m_bHover = false in your Button class
    • implement OnMouseMove as provided in the Question to Track Hover and Leave
    • implement OnMouseHover

      void CFooterButton::OnMouseHover(UINT nFlags, CPoint point)
      {
         m_bHover = true;
         Invalidate();
         CButton::OnMouseHover(nFlags, point);
      }
      
    • implement OnMouseLeave

      void CFooterButton::OnMouseLeave()
      {
         m_bHover = false;
         Invalidate();
         CButton::OnMouseHover(nFlags, point);
      }
      
    • handle Hover effect in yourButtonClass::DrawItem (Invalidate() assures that it'll be called)

      void CFooterButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
      {
          //default colors
          COLORREF textColor = RGB(202, 228, 251), backgroundColor = RGB(84, 150, 205);
      
          switch (lpDrawItemStruct->itemAction)
          {
          case ODA_DRAWENTIRE:
              //check if the user is just hovering over the button
             if (m_isHovered){
                   backgroundColor = RGB(54, 125, 184);
                   textColor = RGB(255, 255, 255); 
             }
             else{
      
                   backgroundColor = RGB(84, 150, 205);
                   textColor = RGB(202, 228, 251);
             }
             break;
      
          case ODA_FOCUS:
             //Button was clicked incase you want to change sth OnClick
             break;
          }
      
          CDC dc;
          dc.Attach(lpDrawItemStruct->hDC);
          dc.FillSolidRect(rect, backgroundColor);
          dc.SetTextColor(textColor);
      
          //your drawing code...
          //DrawFrameControl()etc..
          dc.Detach();
      }
      

    Note: The lp-Structure has another itemAction -> ODA_SELECT refer to MSDN https://msdn.microsoft.com/de-de/library/windows/desktop/bb775802(v=vs.85).aspx