Link to home
Start Free TrialLog in
Avatar of derrickh
derrickh

asked on

Mouse notification when leaving the client area

How can I be notified when the mouse leaves a child view in an MDI App when no mouse buttons are down?  Is there a way that doesn't involvethe CWnd::SetCapture() method?  I am implementing a customized cursor and need to do some GDI cleanup when the mouse leaves the client window.
Avatar of gelbert
gelbert

Use OnMouseMove, it gives you coordinates of cursor. Based on them you can figure out where you are.
Avatar of derrickh

ASKER

I AM using the OnMouseMove() notification for processing inside  of the client area.  My view does not receive notification of mouse messages when it is outside of the client area. I am trying to determine when the mouse leaves the client area.  There is a nice function (I forget the name) that does notify the view when the mouse leaves IF the left mouse button is down, but I need it when the mouse button is up. Is there a straightforward way to do this?
ASKER CERTIFIED SOLUTION
Avatar of RONSLOW
RONSLOW

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This code is an SDK solution. I was looking for a MFC way to do this.
You simply override PumpMessage for your CMyApp to do normal pump message then call the special dispatch code using m_msgCur

(Please refer to my e-Mail reply for details).

I'll see if I can get it working in my own app and will post some code here for reference.  If you get it working first, let me know.

Roger

If you are working under NT, check TrackMouseEvent routine in Win32 API.
Nope.  I found that already, and to my dismay it only works for NT (as you said).  We're writing the software for Windows 95 AND NT.  It must be compatible with both. :-(
I've got it working - will post solution here shortly (when I get a break from my real work :-)

Here is my code (seems to work OK).

in my WinApp.h
====================
extern const UINT WM_MOUSEMOVEIN;
extern const UINT WM_MOUSEMOVEOUT;

class QWinApp : public CWinApp {
      ...
      bool m_bMouseIn;
      bool m_bMouseInOutUnknown;
      bool m_bGenerateMouseInOutMessages;
      ...
      //{{AFX_VIRTUAL(QWinApp)
      ...
      virtual BOOL PumpMessage();
      ...
      //}}AFX_VIRTUAL
      ...
};

in my WinApp.cpp
====================

const UINT WM_MOUSEMOVEIN = ::RegisterWindowMessage("WM_MOUSEMOVEIN");
const UINT WM_MOUSEMOVEOUT = ::RegisterWindowMessage("WM_MOUSEMOVEOUT");

QWinApp::QWinApp() :
      ...
      , m_bMouseIn(FALSE)      // doesn't matter because don't know yet
      , m_bMouseInOutUnknown(TRUE)      // don't know whether in or out yet
      , m_bGenerateMouseInOutMessages(FALSE)      // TRUE if you want mouse move in/out message generated
{
      ...
}

BOOL QWinApp::PumpMessage() {
      BOOL ok = CWinApp::PumpMessage();
      if (ok && m_bGenerateMouseInOutMessages) {
            //If mouse is in then check if it has gone out. If
            //mouse is not in then check if it has come in.
            if (m_bMouseIn || m_bMouseInOutUnknown) {
                  //As long as there is no message for this application
                  //track the mouse cursor position.
                  while(!PeekMessage(&m_msgCur, 0, 0, 0, PM_NOREMOVE)) {
                        CWnd* pMainWnd = ::AfxGetMainWnd();
                        if (pMainWnd) {
                              CPoint pt; GetCursorPos(&pt);
                              CWnd* pMsgWnd = CWnd::WindowFromPoint(pt);
                              //If window at mouse cursor position is not this
                              //app's window and not any of its child windows
                              //then it means mouse has left the app area.
                              if (pMsgWnd != pMainWnd && !pMainWnd->IsChild(pMsgWnd)) {
                                    m_bMouseIn = FALSE;
                                    m_bMouseInOutUnknown = FALSE;
                                    pMainWnd->PostMessage(WM_MOUSEMOVEOUT, 0, 0L);
                                    break;
                              }
                        }
                  }
            }
            if (! m_bMouseIn || m_bMouseInOutUnknown) {
                  //If the mouse is not in and the app has received
                  //mouse move message the it means mouse has entered.
                  if (
                        m_msgCur.message == WM_MOUSEMOVE ||
                        m_msgCur.message == WM_NCMOUSEMOVE
                  ) {
                        CWnd* pMainWnd = ::AfxGetMainWnd();
                        if (pMainWnd) {
                              m_bMouseIn = TRUE;
                              m_bMouseInOutUnknown = FALSE;
                              pMainWnd->PostMessage(WM_MOUSEMOVEIN, 0, 0L);
                        }
                  }
            }
      }
      return ok;
}

example of how to handle a message in MainFrame.h/cpp
============================================================

BEGIN_MESSAGE_MAP(QMainFrame, CFrameWnd)
...
ON_REGISTERED_MESSAGE(WM_MOUSEMOVEIN, OnMouseMoveIn)
ON_REGISTERED_MESSAGE(WM_MOUSEMOVEOUT, OnMouseMoveOut)
...
END_MESSAGE_MAP()

LRESULT QMainFrame::OnMouseMoveIn(WPARAM /*wparam*/, LPARAM /*lparam*/) {
      TRACE("OnMouseMoveIn\n");
      return 0;
}

LRESULT QMainFrame::OnMouseMoveOut(WPARAM /*wparam*/, LPARAM /*lparam*/) {
      TRACE("OnMouseMoveOut\n");
      return 0;
}

Hope this helps.

Roger

This I can work with. Thank for the time you put in!