see my windows procedure:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    bool blnMouseEnter=false;
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_KEYUP:
            if (wParam ==VK_ESCAPE)
                DestroyWindow(hwnd);
            else
            {
                char strDataToSend[32];
                sprintf(strDataToSend, "%c", wParam);
                MessageBox(NULL,strDataToSend, "keyselected",MB_OK);
            }
        break;

        case WM_MOUSEMOVE:
            SetWindowText(hwnd,"hi");
            break;
        case WM_MOUSELEAVE://is ignored :(
            SetWindowText(hwnd,"bye");
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

i'm trying testing the Mouse Enter and Mouse Leave, but the mouse leave isn't activated and the Mouse Move isn't activated with window border :(
what isn't right?

Recommended Answers

All 8 Replies

You cannot get mouse event like this. You need to "track" the mouse and determine when it has entered and when it has left your window/control. I've written a small example below.

#include <iostream>
#include <windows.h>

void TrackMouse(HWND hwnd)
{
    TRACKMOUSEEVENT tme;
    tme.cbSize = sizeof(TRACKMOUSEEVENT);
    tme.dwFlags = TME_HOVER | TME_LEAVE; //Type of events to track & trigger.
    tme.dwHoverTime = 1; //How long the mouse has to be in the window to trigger a hover event.
    tme.hwndTrack = hwnd;
    TrackMouseEvent(&tme);
}

LRESULT WndProc(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    static bool Tracking = false;

    switch(Msg)
    {
        case WM_MOUSEMOVE:
        {
            if (!Tracking)
            {
                TrackMouse(Hwnd);
                Tracking = true;
            }
        }
        break;

        case WM_MOUSEHOVER:
            std::cout<<"MOUSE ENTERED\n";
            break;

        case WM_MOUSELEAVE:
            std::cout<<"MOUSE LEFT\n";
            Tracking = false;
            break;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        default:
            return DefWindowProc(Hwnd, Msg, wParam, lParam);
    }
    return 0;
};

thanks.. let me ask:
1 - why the mouse works for client size and not window size?
2 - the mouse hover it's confuse me:( the mouse hover is the time that mouse stoped, right?

I think the MouseTracking is for client area only. It doesn't make much sense to track the mouse within the window's title bar. Mouse hover is just the amount of time (milliseconds) the mouse has to be in the client area before the WM_MOUSEHOVER event is triggered. In the above code, dwHoverTime is set to one.. If the mouse has been within a window or control's bounds for 1ms or more, the window/control will receive the WM_MOUSEHOVER event. If you set this paramter to 100000, it will need to be within the window's bounds for 100000ms before the window receives the event.

In other words, it does not matter whether the mouse is moving over the window/control, it only matters how long it has been within the window/control's bounds.

thanks for correct me ;)
let me ask anotherthing: how can i detect the MouseStoped and WindowStoped messages?

i'm using the WM_EXITSIZEMOVE, but seems freeze the window :(

sorry i did a mistake: i said WM_EXITSIZEMOVE but used WM_EXITSIZEMOVEMODE(but don't exists).
now i can track the window stoped size and move:

void TrackMouse(HWND hwnd)
{
    TRACKMOUSEEVENT tme;
    tme.cbSize = sizeof(TRACKMOUSEEVENT);
    tme.dwFlags = TME_HOVER | TME_LEAVE; //Type of events to track & trigger.
    tme.dwHoverTime = 5000; //How long the mouse has to be in the window to trigger a hover event.
    tme.hwndTrack = hwnd;
    TrackMouseEvent(&tme);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static bool TrackingMouse = false;
    static bool WindowStopMoving = NULL;
    static bool WindowStopResize = NULL;

    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_KEYUP:
            if (wParam ==VK_ESCAPE)
                DestroyWindow(hwnd);
            else
            {
                char strDataToSend[32];
                sprintf(strDataToSend, "%c", wParam);
                MessageBox(NULL,strDataToSend, "keyselected",MB_OK);
            }
            break;

        case WM_MOUSEMOVE:
            if (!TrackingMouse)
            {
                TrackMouse(hwnd);
                TrackingMouse = true;
                SetWindowText(hwnd,"MOUSE Entered");
            }
            break;
        case WM_MOUSEHOVER:
            SetWindowText(hwnd,"MOUSE hover");
            break;
        case WM_MOUSELEAVE :
            SetWindowText(hwnd,"MOUSE LEFT");
            TrackingMouse = false;
            break;
        case WM_MOVE:
            SetWindowText(hwnd,"window move");
            WindowStopMoving=false;
            WindowStopResize=true;
            break;
        case WM_SIZE :
            SetWindowText(hwnd,"Resized");
            WindowStopResize=false;
            WindowStopMoving=true;
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_EXITSIZEMOVE:
            if(WindowStopResize==false)
            {
                SetWindowText(hwnd,"stop Resized");
                WindowStopResize=true;
            }
            else if (WindowStopMoving==false)
            {
                SetWindowText(hwnd,"stop MOve");
                WindowStopMoving=true;
            }
            break;
        default:

            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

these code works fine, but how can i track the mouse stoped?

I'm not exactly sure what you're trying to do here.

However, since you mentioned "mouse stop", I assume you want to know when the mouse has stopped moving. In that case, you're going to need to set a Timer and check the WM_TIMER event. http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx
and
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644902(v=vs.85).aspx

What you'll do is.. When you receive a WM_MOUSEMOVE message, call SetTimer with the timerproc paramter as null. If the mouse moves again, you want to call KillTimer. If you receive a WM_TIMER message, it means the mouse has stopped moving.

For example:

LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static UINT_PTR MouseStopTimerID = 1; //Just some unique TimerID.

    switch(msg)
    {
        case WM_MOUSEMOVE:
        {
            KillTimer(hwnd, MouseStopTimerID);
            SetTimer(hwnd, MouseStopTimerID, 500, NULL); //if the mouse hasn't moved for 500ms, a timer event will be triggered.

            //SetTimer(hwnd, MouseStopTimerID, 500, OnMouseStop); //Can be used as a callback as well. Instead of receiving a WM_TIMER, it will call the function "OnMouseStop".
        }
        break;

        case WM_TIMER:
        {
            switch(wParam)
            {
                case MouseStopTimer:
                {
                    /**
                     * Do whatever you want here.. The mouse hasn't moved for 500ms since the timer has been set..
                     */
                    KillTimer(hwnd, MouseStopTimerID); //Kill the timer after processing it.
                }
                return 0; //This procedure must immediately return 0 if it processes a timer event.
            }
        }
        break;

        case WM_DESTROY:
            KillTimer(hwnd, MouseStopTimerID); //Just in case the timer is still alive, kill it before the application closes..
            PostQuitMessage(0);
        break;
    }
}

/*void __stdcall OnMouseStop(HWND hwnd, UINT msg, UINT_PTR TimerID, DWORD dwTime)
{
    if (TimerID == 1 && dwTime > 500) //if TimerID == same ID as MouseStopTimerID && TimeElapsed > 500ms..
    {
        //Mouse hasn't moved for 500ms since the timer started..
        KillTimer(hwnd, 1);
    }
}*/

So in the above, what I did was I crammed two examples into one as I'm quite tired atm..

The first example is using the Timer. It sets the last parameter as NULL meaning it will send your application a WM_TIMER event. If the last parameter is NOT NULL, it will call the function instead of sending a WM_TIMER message. That's what all the commented out code is for.

In other words, you have two options here. Either use WM_TIMER event OR use the callback function "OnMouseStop". Like the hover tracker, the timer will only send you an event or call the OnMouseStop if the mouse hasn't moved for 500ms. You can increase or decrease the time as you wish. I wrote it all in notepad and I hope it compiles and works. I will check back in the morning when I'm not so tired and see how you're doing.

commented: thanks +2

i found 2 errors on your code;)
heres the entire windproc:

void TrackMouse(HWND hwnd)
{
    TRACKMOUSEEVENT tme;
    tme.cbSize = sizeof(TRACKMOUSEEVENT);
    tme.dwFlags = TME_HOVER | TME_LEAVE; //Type of events to track & trigger.
    tme.dwHoverTime = 5000; //How long the mouse has to be in the window to trigger a hover event.
    tme.hwndTrack = hwnd;
    TrackMouseEvent(&tme);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static bool TrackingMouse = false;
    static bool WindowStopMoving = NULL;
    static bool WindowStopResize = NULL;
    static const UINT_PTR MouseStopTimerID = 1;

    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_KEYUP:
            if (wParam ==VK_ESCAPE)
                DestroyWindow(hwnd);
            else
            {
                char strDataToSend[32];
                sprintf(strDataToSend, "%c", wParam);
                MessageBox(NULL,strDataToSend, "keyselected",MB_OK);
            }
            break;

        case WM_MOUSEMOVE:
            if (!TrackingMouse)
            {
                TrackMouse(hwnd);
                TrackingMouse = true;
                SetWindowText(hwnd,"MOUSE Entered");
            }
            KillTimer(hwnd, MouseStopTimerID);
            SetTimer(hwnd, MouseStopTimerID, 100, NULL);
            break;
        case WM_MOUSEHOVER:
            SetWindowText(hwnd,"MOUSE hover");
            break;
        case WM_MOUSELEAVE :
            SetWindowText(hwnd,"MOUSE LEFT");
            TrackingMouse = false;
            break;
        case WM_MOVE:
            SetWindowText(hwnd,"window move");
            WindowStopMoving=false;
            WindowStopResize=true;
            break;
        case WM_SIZE :
            SetWindowText(hwnd,"Resized");
            WindowStopResize=false;
            WindowStopMoving=true;
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_EXITSIZEMOVE:
            if(WindowStopResize==false)
            {
                SetWindowText(hwnd,"stop Resized");
                WindowStopResize=true;
            }
            else if (WindowStopMoving==false)
            {
                SetWindowText(hwnd,"stop MOve");
                WindowStopMoving=true;
            }
            break;
        case WM_TIMER:
            switch(wParam)
            {
                case MouseStopTimerID:
                {
                    SetWindowText(hwnd,"mouse stoped");
                    KillTimer(hwnd, MouseStopTimerID); //Kill the timer after processing it.
                }
                return 0; //This procedure must immediately return 0 if it processes a timer event.
            }
            break;

        default:

            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

yes.. i change the timer time for 100(but you can advice);)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.