본문 바로가기

Windows/MFC

Using TrackMouseEvent to find out when the mouse leaves your window

Link : http://www.codeguru.com/cpp/misc/misc/article.php/c307/

********************************************************************************

[code]
// TrackView.h changes
//

class CTrackView : public CView
{
// Add data members
protected:
    CRect m_rectLast;    // Added line
    BOOL m_bMouseTracking;    // Added line

// Add message handler prototype
    afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);    // Added line

};[/code]

****************************************************************************************

[code]// TrackView.cpp changes
//

// Add message handler
BEGIN_MESSAGE_MAP(CTrackView, CView)
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)    // Added line
END_MESSAGE_MAP()

CTrackView::CTrackView()
{
    m_bMouseTracking = FALSE;    // Added line
}

/////////////////////////////////////////////////////////////////////////////
// CTrackView message handlers

// Added function
LRESULT CTrackView::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
    // Draw last rect, but no new one (erase old rect)
    CClientDC dc(this);
    dc.DrawDragRect(CRect(0,0,0,0), CSize(0,0), m_rectLast, CSize(2,2));
    m_rectLast = CRect(0,0,0,0);

    m_bMouseTracking = FALSE;
    return TRUE;
}

void CTrackView::OnMouseMove(UINT nFlags, CPoint point)
{
    // Calc new rectangle
    CRect rectNew(point.x-20, point.y-20, point.x+20, point.y+20);
    CClientDC dc(this);

    // WM_MOUSEMOVE + !m_bMouseTracking becomes the equivalent of
    // WM_MOUSEENTER of which there is no such thing.
    if (!m_bMouseTracking)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE;
        tme.hwndTrack = this->m_hWnd;

        if (::_TrackMouseEvent(&tme))
        {
            m_bMouseTracking = TRUE;

            // Draw new rect, but no last rect as we are starting anew
            dc.DrawDragRect(rectNew, CSize(2,2), NULL, CSize(0,0));
        }
    }
    else
    {
        // Draw new rect and erase old rect
        dc.DrawDragRect(rectNew, CSize(2,2), m_rectLast, CSize(2,2));
    }

    // Remember where we drew this rectangle
    m_rectLast = rectNew;

    CView::OnMouseMove(nFlags, point);
}[/code]

****************************************************************************************


Here's a helper class I use to make it a little simpler:

[code]class CTrackMouseEvent : public tagTRACKMOUSEEVENT
{
public:
    CTrackMouseEvent(CWnd* pWnd, DWORD dwFlags = TME_LEAVE, DWORD dwHoverTime = HOVER_DEFAULT)
    {
        ASSERT_VALID(pWnd);
        ASSERT(::IsWindow(pWnd->m_hWnd));

        this->cbSize = sizeof(TRACKMOUSEEVENT);
        this->dwFlags = dwFlags;
        this->hwndTrack = pWnd->m_hWnd;
        this->dwHoverTime = dwHoverTime;
    }

    BOOL Track()
        { return _TrackMouseEvent(this); }
};
[/code]

You can start tracking like this:

[code]if (!m_bMouseTracking)
    m_bMouseTracking = CTrackMouseEvent(this).Track();
[/code]