Hover effects, IMessageFilter not working as expected

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • ThunderMusic

    Hover effects, IMessageFilter not working as expected

    Hi,
    I'm developping a form that renders differently when hovered and trigger
    some processing when not hovered (leaved). The thing is, when I leave my
    form and another form from my application is underneath, it works fine, but
    if I leave my form and anything that is not from my application is
    underneath, the Leave event does not fire until I hover something from my
    application.

    Here's my filtered code for the IMessageFilter (I did not pasted the
    declarations, I just pasted my message proc) (at the end of the post)

    Can someone tell me what's wrong with this code?

    thanks

    ThunderMusic

    Code:
    public bool PreFilterMessage(ref Message m)
    {
    // Everything is done with WM_MOUSEMOVE
    if (m.Msg == WM_MOUSEMOVE)
    {
    // look if the target is our control or contained by our control
    Control ctrl = Control.FromHandle(m.HWnd);
    if (ctrl != null && (ctrl == this._container ||
    this._container.Contains(ctrl)))
    {
    // if this message WM_MOUSEMOVE is the first we get,
    // we must trigger the MouseEnter event
    if (!this._isEntered)
    {
    // trigger MouseEnter
    this.OnMouseEnter();
    this._isEntered = true;
    }
    // Get point (using target control coordinates)
    Point pt = new Point(m.LParam.ToInt32());
    // convert to controls coordinates if necessary
    Point containerPoint;
    if (ctrl != this._container)
    containerPoint =
    this._container.PointToClient(ctrl.PointToScreen(pt));
    else
    containerPoint = pt;
    // Trigger MouseMove
    this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0,
    containerPoint.X, containerPoint.Y, 0));
    }
    else
    {
    // If the target is not a child and MouseLeaves has not been
    triggered
    // we must trigger MouseLeave
    if (this._isEntered)
    {
    // Trigger MouseLeave
    this.OnMouseLeave();
    this._isEntered = false;
    }
    }
    }
    return false;
    }

  • Bryan Phillips

    #2
    Re: Hover effects, IMessageFilter not working as expected

    Have you tried using the Activated and Deactivated events instead? See
    this from MSDN help:

    The Enter and Leave events are suppressed by the Form class. The
    equivalent events in the Form class are the Activated and Deactivate
    events. The Enter and Leave events are hierarchical and will cascade up
    and down the parent chain until the appropriate control is reached. For
    example, assume you have a Form with two GroupBox controls, and each
    GroupBox control has one TextBox control. When the caret is moved from
    one TextBox to the other, the Leave event is raised for the TextBox and
    GroupBox, and the Enter event is raised for the other GroupBox and
    TextBox.

    Bryan Phillips
    MCSD, MCDBA, MCSE
    Blog: http://bphillips76.spaces.live.com




    "ThunderMus ic" <NoSpAmdanlatat hotmaildotcom@N oSpAm.comwrote in message
    news:eh#7bOT#GH A.3456@TK2MSFTN GP02.phx.gbl:
    Hi,
    I'm developping a form that renders differently when hovered and trigger
    some processing when not hovered (leaved). The thing is, when I leave my
    form and another form from my application is underneath, it works fine, but
    if I leave my form and anything that is not from my application is
    underneath, the Leave event does not fire until I hover something from my
    application.
    >
    Here's my filtered code for the IMessageFilter (I did not pasted the
    declarations, I just pasted my message proc) (at the end of the post)
    >
    Can someone tell me what's wrong with this code?
    >
    thanks
    >
    ThunderMusic
    >
    Code:
    public bool PreFilterMessage(ref Message m)
    {
        // Everything is done with WM_MOUSEMOVE
        if (m.Msg == WM_MOUSEMOVE)
        {
            // look if the target is our control or contained by our control
            Control ctrl = Control.FromHandle(m.HWnd);
            if (ctrl != null && (ctrl == this._container ||
    this._container.Contains(ctrl)))
            {
                // if this message WM_MOUSEMOVE is the first we get,
                // we must trigger the MouseEnter event
                if (!this._isEntered)
                {
                    // trigger MouseEnter
                    this.OnMouseEnter();
                    this._isEntered = true;
                }
                // Get point (using target control coordinates)
                Point pt = new Point(m.LParam.ToInt32());
                // convert to controls coordinates if necessary
                Point containerPoint;
                if (ctrl != this._container)
                    containerPoint =
    this._container.PointToClient(ctrl.PointToScreen(pt));
                else
                    containerPoint = pt;
                // Trigger MouseMove
                this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0,
    containerPoint.X, containerPoint.Y, 0));
            }
            else
            {
                // If the target is not a child and MouseLeaves has not been
    triggered
                // we must trigger MouseLeave
                if (this._isEntered)
                {
                    // Trigger MouseLeave
                    this.OnMouseLeave();
                    this._isEntered = false;
                }
            }
        }
        return false;
    }

    Comment

    • ThunderMusic

      #3
      Re: Hover effects, IMessageFilter not working as expected

      hi, thanks for your answer... unfortunately, it's not exactly what I
      need... Activate and Deactivate are triggered when a user clicks on a form
      (activated) or click on another form or minimize (Deactivate)... The
      behavior I need is when the user move his mouse over the form or out of the
      form...

      I agree that the MouseEnter and MouseLeave of the form are hierarchical,
      that's why I did implement IMessageFilter. ... Now the thing is, I must
      discover how to receive the message (or event) so the program can tell when
      the mouse cursor went out of the form's boundaries.

      Thanks

      ThunderMusic

      "Bryan Phillips" <bphillips@nosp am.crowechizek. com.spammenotwr ote in
      message news:O7NrmmW%23 GHA.4468@TK2MSF TNGP05.phx.gbl. ..
      Have you tried using the Activated and Deactivated events instead? See
      this from MSDN help:
      >
      The Enter and Leave events are suppressed by the Form class. The
      equivalent events in the Form class are the Activated and Deactivate
      events. The Enter and Leave events are hierarchical and will cascade up
      and down the parent chain until the appropriate control is reached. For
      example, assume you have a Form with two GroupBox controls, and each
      GroupBox control has one TextBox control. When the caret is moved from one
      TextBox to the other, the Leave event is raised for the TextBox and
      GroupBox, and the Enter event is raised for the other GroupBox and
      TextBox.
      >
      Bryan Phillips
      MCSD, MCDBA, MCSE
      Blog: http://bphillips76.spaces.live.com
      >
      >
      >
      >
      "ThunderMus ic" <NoSpAmdanlatat hotmaildotcom@N oSpAm.comwrote in message
      news:eh#7bOT#GH A.3456@TK2MSFTN GP02.phx.gbl:
      >
      >Hi,
      >I'm developping a form that renders differently when hovered and trigger
      >some processing when not hovered (leaved). The thing is, when I leave my
      >form and another form from my application is underneath, it works fine,
      >but
      >if I leave my form and anything that is not from my application is
      >underneath, the Leave event does not fire until I hover something from my
      >application.
      >>
      >Here's my filtered code for the IMessageFilter (I did not pasted the
      >declarations , I just pasted my message proc) (at the end of the post)
      >>
      >Can someone tell me what's wrong with this code?
      >>
      >thanks
      >>
      >ThunderMusic
      >>
      >
      Code:
      >public bool PreFilterMessage(ref Message m)
      >{
      >    // Everything is done with WM_MOUSEMOVE
      >    if (m.Msg == WM_MOUSEMOVE)
      >    {
      >        // look if the target is our control or contained by our control
      >        Control ctrl = Control.FromHandle(m.HWnd);
      >        if (ctrl != null && (ctrl == this._container ||
      >this._container.Contains(ctrl)))
      >        {
      >            // if this message WM_MOUSEMOVE is the first we get,
      >            // we must trigger the MouseEnter event
      >            if (!this._isEntered)
      >            {
      >                // trigger MouseEnter
      >                this.OnMouseEnter();
      >                this._isEntered = true;
      >            }
      >            // Get point (using target control coordinates)
      >            Point pt = new Point(m.LParam.ToInt32());
      >            // convert to controls coordinates if necessary
      >            Point containerPoint;
      >            if (ctrl != this._container)
      >                containerPoint =
      >this._container.PointToClient(ctrl.PointToScreen(pt));
      >            else
      >                containerPoint = pt;
      >            // Trigger MouseMove
      >            this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0,
      >containerPoint.X, containerPoint.Y, 0));
      >        }
      >        else
      >        {
      >            // If the target is not a child and MouseLeaves has not been
      >triggered
      >            // we must trigger MouseLeave
      >            if (this._isEntered)
      >            {
      >                // Trigger MouseLeave
      >                this.OnMouseLeave();
      >                this._isEntered = false;
      >            }
      >        }
      >    }
      >    return false;
      >}
      >
      >

      Comment

      • Stoitcho Goutsev \(100\)

        #4
        Re: Hover effects, IMessageFilter not working as expected

        Hi,

        Here is your problem. You are using MouseMove event which is based on
        WM_MOUSEMOVE. This message as any other mouse messages are posted to the
        window under the mouse cursor. Because you use message filter you receive
        this message if the mouse is over any form (control) that belongs to your
        application. However when the mouse moves over window that is not part of
        your application we just stop receiving mouse messages and there is no
        notification when this happens they just stop. Windows have three solutions
        to the problem (at least these are the ones that I can come up with at the
        moment): installing window hook WH_MOUSE_LL, using TrackMouseEvent API and
        setting mouse capture.

        - WH_MOUSE_LL are possible to be implemented in .NET, but it requires using
        PInvoke and I think it is the hardest one to implement
        - Setint the mouse capture means that the mouse message will be dispatched
        to your window even when the mouse cursor is outside of the window. The
        problem is that it works only if mouse button has been pressed when the
        mouse is inside the window is held down while moving the mouse. WindowsForms
        sets the mouse capture when the mouse button is pressed, so it should work
        by itself, but if it doesn't work for you that means you want to register
        mouse leave not only when the mouse button is down.
        - TrackMouseEvent is used internaly by Windows forms and the functionality
        is exposed as MouseLeave and MouseHover events. Why don't use these events
        instead of implementing your own solution?
        The only problem that I see is that you are going to receive mouse leave
        even if the mouse is inside the form, but enters some form's child control.
        This cases can be filtered our by checking the form hosting tghe control.
        The WM_MOUSELEAVE used internally is posted to the message queue, thus can
        be handeled with message filter


        --
        HTH
        Stoitcho Goutsev (100)

        "ThunderMus ic" <NoSpAmdanlatat hotmaildotcom@N oSpAm.comwrote in message
        news:OtNY$Wc%23 GHA.1196@TK2MSF TNGP02.phx.gbl. ..
        hi, thanks for your answer... unfortunately, it's not exactly what I
        need... Activate and Deactivate are triggered when a user clicks on a
        form (activated) or click on another form or minimize (Deactivate)... The
        behavior I need is when the user move his mouse over the form or out of
        the form...
        >
        I agree that the MouseEnter and MouseLeave of the form are hierarchical,
        that's why I did implement IMessageFilter. ... Now the thing is, I must
        discover how to receive the message (or event) so the program can tell
        when the mouse cursor went out of the form's boundaries.
        >
        Thanks
        >
        ThunderMusic
        >
        "Bryan Phillips" <bphillips@nosp am.crowechizek. com.spammenotwr ote in
        message news:O7NrmmW%23 GHA.4468@TK2MSF TNGP05.phx.gbl. ..
        >Have you tried using the Activated and Deactivated events instead? See
        >this from MSDN help:
        >>
        >The Enter and Leave events are suppressed by the Form class. The
        >equivalent events in the Form class are the Activated and Deactivate
        >events. The Enter and Leave events are hierarchical and will cascade up
        >and down the parent chain until the appropriate control is reached. For
        >example, assume you have a Form with two GroupBox controls, and each
        >GroupBox control has one TextBox control. When the caret is moved from
        >one TextBox to the other, the Leave event is raised for the TextBox and
        >GroupBox, and the Enter event is raised for the other GroupBox and
        >TextBox.
        >>
        >Bryan Phillips
        >MCSD, MCDBA, MCSE
        >Blog: http://bphillips76.spaces.live.com
        >>
        >>
        >>
        >>
        >"ThunderMusi c" <NoSpAmdanlatat hotmaildotcom@N oSpAm.comwrote in message
        >news:eh#7bOT#G HA.3456@TK2MSFT NGP02.phx.gbl:
        >>
        >>Hi,
        >>I'm developping a form that renders differently when hovered and trigger
        >>some processing when not hovered (leaved). The thing is, when I leave my
        >>form and another form from my application is underneath, it works fine,
        >>but
        >>if I leave my form and anything that is not from my application is
        >>underneath, the Leave event does not fire until I hover something from
        >>my
        >>application .
        >>>
        >>Here's my filtered code for the IMessageFilter (I did not pasted the
        >>declaration s, I just pasted my message proc) (at the end of the post)
        >>>
        >>Can someone tell me what's wrong with this code?
        >>>
        >>thanks
        >>>
        >>ThunderMusi c
        >>>
        >>
        Code:
        >>public bool PreFilterMessage(ref Message m)
        >>{
        >>    // Everything is done with WM_MOUSEMOVE
        >>    if (m.Msg == WM_MOUSEMOVE)
        >>    {
        >>        // look if the target is our control or contained by our control
        >>        Control ctrl = Control.FromHandle(m.HWnd);
        >>        if (ctrl != null && (ctrl == this._container ||
        >>this._container.Contains(ctrl)))
        >>        {
        >>            // if this message WM_MOUSEMOVE is the first we get,
        >>            // we must trigger the MouseEnter event
        >>            if (!this._isEntered)
        >>            {
        >>                // trigger MouseEnter
        >>                this.OnMouseEnter();
        >>                this._isEntered = true;
        >>            }
        >>            // Get point (using target control coordinates)
        >>            Point pt = new Point(m.LParam.ToInt32());
        >>            // convert to controls coordinates if necessary
        >>            Point containerPoint;
        >>            if (ctrl != this._container)
        >>                containerPoint =
        >>this._container.PointToClient(ctrl.PointToScreen(pt));
        >>            else
        >>                containerPoint = pt;
        >>            // Trigger MouseMove
        >>            this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0,
        >>containerPoint.X, containerPoint.Y, 0));
        >>        }
        >>        else
        >>        {
        >>            // If the target is not a child and MouseLeaves has not been
        >>triggered
        >>            // we must trigger MouseLeave
        >>            if (this._isEntered)
        >>            {
        >>                // Trigger MouseLeave
        >>                this.OnMouseLeave();
        >>                this._isEntered = false;
        >>            }
        >>        }
        >>    }
        >>    return false;
        >>}
        >>
        >>
        >
        >

        Comment

        • ThunderMusic

          #5
          Re: Hover effects, IMessageFilter not working as expected

          Great, it seems to work fine now by filtering on the WM_MOUSELEAVE message
          in my MessageFilter.

          Thanks a lot

          ThunderMusic

          "Stoitcho Goutsev (100)" <100@100.coma écrit dans le message de news:
          %23jIU3Ef%23GHA .1196@TK2MSFTNG P02.phx.gbl...
          Hi,
          >
          Here is your problem. You are using MouseMove event which is based on
          WM_MOUSEMOVE. This message as any other mouse messages are posted to the
          window under the mouse cursor. Because you use message filter you receive
          this message if the mouse is over any form (control) that belongs to your
          application. However when the mouse moves over window that is not part of
          your application we just stop receiving mouse messages and there is no
          notification when this happens they just stop. Windows have three
          solutions to the problem (at least these are the ones that I can come up
          with at the moment): installing window hook WH_MOUSE_LL, using
          TrackMouseEvent API and setting mouse capture.
          >
          - WH_MOUSE_LL are possible to be implemented in .NET, but it requires
          using PInvoke and I think it is the hardest one to implement
          - Setint the mouse capture means that the mouse message will be dispatched
          to your window even when the mouse cursor is outside of the window. The
          problem is that it works only if mouse button has been pressed when the
          mouse is inside the window is held down while moving the mouse.
          WindowsForms sets the mouse capture when the mouse button is pressed, so
          it should work by itself, but if it doesn't work for you that means you
          want to register mouse leave not only when the mouse button is down.
          - TrackMouseEvent is used internaly by Windows forms and the
          functionality is exposed as MouseLeave and MouseHover events. Why don't
          use these events instead of implementing your own solution?
          The only problem that I see is that you are going to receive mouse leave
          even if the mouse is inside the form, but enters some form's child
          control. This cases can be filtered our by checking the form hosting tghe
          control. The WM_MOUSELEAVE used internally is posted to the message queue,
          thus can be handeled with message filter
          >
          >
          --
          HTH
          Stoitcho Goutsev (100)
          >
          "ThunderMus ic" <NoSpAmdanlatat hotmaildotcom@N oSpAm.comwrote in message
          news:OtNY$Wc%23 GHA.1196@TK2MSF TNGP02.phx.gbl. ..
          >hi, thanks for your answer... unfortunately, it's not exactly what I
          >need... Activate and Deactivate are triggered when a user clicks on a
          >form (activated) or click on another form or minimize (Deactivate)...
          >The behavior I need is when the user move his mouse over the form or out
          >of the form...
          >>
          >I agree that the MouseEnter and MouseLeave of the form are hierarchical,
          >that's why I did implement IMessageFilter. ... Now the thing is, I must
          >discover how to receive the message (or event) so the program can tell
          >when the mouse cursor went out of the form's boundaries.
          >>
          >Thanks
          >>
          >ThunderMusic
          >>
          >"Bryan Phillips" <bphillips@nosp am.crowechizek. com.spammenotwr ote in
          >message news:O7NrmmW%23 GHA.4468@TK2MSF TNGP05.phx.gbl. ..
          >>Have you tried using the Activated and Deactivated events instead? See
          >>this from MSDN help:
          >>>
          >>The Enter and Leave events are suppressed by the Form class. The
          >>equivalent events in the Form class are the Activated and Deactivate
          >>events. The Enter and Leave events are hierarchical and will cascade up
          >>and down the parent chain until the appropriate control is reached. For
          >>example, assume you have a Form with two GroupBox controls, and each
          >>GroupBox control has one TextBox control. When the caret is moved from
          >>one TextBox to the other, the Leave event is raised for the TextBox and
          >>GroupBox, and the Enter event is raised for the other GroupBox and
          >>TextBox.
          >>>
          >>Bryan Phillips
          >>MCSD, MCDBA, MCSE
          >>Blog: http://bphillips76.spaces.live.com
          >>>
          >>>
          >>>
          >>>
          >>"ThunderMusic " <NoSpAmdanlatat hotmaildotcom@N oSpAm.comwrote in message
          >>news:eh#7bOT# GHA.3456@TK2MSF TNGP02.phx.gbl:
          >>>
          >>>Hi,
          >>>I'm developping a form that renders differently when hovered and
          >>>trigger
          >>>some processing when not hovered (leaved). The thing is, when I leave
          >>>my
          >>>form and another form from my application is underneath, it works fine,
          >>>but
          >>>if I leave my form and anything that is not from my application is
          >>>underneath , the Leave event does not fire until I hover something from
          >>>my
          >>>applicatio n.
          >>>>
          >>>Here's my filtered code for the IMessageFilter (I did not pasted the
          >>>declarations , I just pasted my message proc) (at the end of the post)
          >>>>
          >>>Can someone tell me what's wrong with this code?
          >>>>
          >>>thanks
          >>>>
          >>>ThunderMus ic
          >>>>
          >>>
          Code:
          >>>public bool PreFilterMessage(ref Message m)
          >>>{
          >>>    // Everything is done with WM_MOUSEMOVE
          >>>    if (m.Msg == WM_MOUSEMOVE)
          >>>    {
          >>>        // look if the target is our control or contained by our
          >>>control
          >>>        Control ctrl = Control.FromHandle(m.HWnd);
          >>>        if (ctrl != null && (ctrl == this._container ||
          >>>this._container.Contains(ctrl)))
          >>>        {
          >>>            // if this message WM_MOUSEMOVE is the first we get,
          >>>            // we must trigger the MouseEnter event
          >>>            if (!this._isEntered)
          >>>            {
          >>>                // trigger MouseEnter
          >>>                this.OnMouseEnter();
          >>>                this._isEntered = true;
          >>>            }
          >>>            // Get point (using target control coordinates)
          >>>            Point pt = new Point(m.LParam.ToInt32());
          >>>            // convert to controls coordinates if necessary
          >>>            Point containerPoint;
          >>>            if (ctrl != this._container)
          >>>                containerPoint =
          >>>this._container.PointToClient(ctrl.PointToScreen(pt));
          >>>            else
          >>>                containerPoint = pt;
          >>>            // Trigger MouseMove
          >>>            this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0,
          >>>containerPoint.X, containerPoint.Y, 0));
          >>>        }
          >>>        else
          >>>        {
          >>>            // If the target is not a child and MouseLeaves has not
          >>>been
          >>>triggered
          >>>            // we must trigger MouseLeave
          >>>            if (this._isEntered)
          >>>            {
          >>>                // Trigger MouseLeave
          >>>                this.OnMouseLeave();
          >>>                this._isEntered = false;
          >>>            }
          >>>        }
          >>>    }
          >>>    return false;
          >>>}
          >>>
          >>>
          >>
          >>
          >
          >

          Comment

          Working...