We help IT Professionals succeed at work.

UserControl and Mouse

PedroMVGomes
PedroMVGomes asked
on
Medium Priority
718 Views
Last Modified: 2012-06-27
I've developed a usercontrol that realy needs to know wend the mouse is no longer over it.

I'm using a timer to do so, but as we all know, timers are very hungry for resources.

I've tried hooking the control but no message was received wend the mouse is outside the control, Hooking the parent is no soluction cos it could be a picture or something else of the same size of the control, so no mouse move event will fire!!

HELP!!!
Comment
Watch Question

I think this will help you.


Option Explicit
'When outside the form or...
Private Declare Function GetActiveWindow Lib "user32" () As Long

Private Type tagRect
   lngLeft As Long
   lngTop As Long
   lngRight As Long
   lngBottom As Long
End Type

' Two different declarations for the same API function.
Private Declare Sub ClipCursor Lib "user32" _
 (typRect As tagRect)
Private Declare Sub ClipCursorClear Lib "user32" _
 Alias "ClipCursor" (ByVal param As Any)

Private Declare Sub GetWindowRect Lib "user32" _
 (ByVal hWnd As Long, typRect As tagRect)

Private Sub cmdClip_Click()
   Dim typRect As tagRect
   Static sstrCaption As String
   Dim hWnd As Long
   Dim X
   Dim OldName
   Dim NewName
   Dim MyFile
   Static fClip As Boolean
     
   Name OldName As NewName ' Rename file.
           
   If fClip Then
      Call ClipCursorClear(vbNullString)
      cmdClip.Caption = sstrCaption
   Else
      hWnd = GetActiveWindow()
      sstrCaption = cmdClip.Caption
      cmdClip.Caption = "Free the Mouse!"
      Name NewName As OldName   ' Rename file.
      Call GetWindowRect(hWnd, typRect)
      Call ClipCursor(typRect)
     
   End If
   fClip = Not fClip
End Sub

Private Sub Form_Load()
   Call ClipCursorClear(vbNullString)
   KeyPreview = True
End Sub

shay@hili.com
Correction to some element that not needed in the first code

==============start============

Option Explicit
'When outside the form or...
Private Declare Function GetActiveWindow Lib "user32" () As Long

Private Type tagRect
   lngLeft As Long
   lngTop As Long
   lngRight As Long
   lngBottom As Long
End Type

' Two different declarations for the same API function.
Private Declare Sub ClipCursor Lib "user32" _
 (typRect As tagRect)
Private Declare Sub ClipCursorClear Lib "user32" _
 Alias "ClipCursor" (ByVal param As Any)

Private Declare Sub GetWindowRect Lib "user32" _
 (ByVal hWnd As Long, typRect As tagRect)

Private Sub cmdClip_Click()
   Dim typRect As tagRect
   Static sstrCaption As String
   Dim hWnd As Long
   Static fClip As Boolean
           
   If fClip Then
      Call ClipCursorClear(vbNullString)
      cmdClip.Caption = sstrCaption
   Else
      hWnd = GetActiveWindow()
      sstrCaption = cmdClip.Caption
      cmdClip.Caption = "Free the Mouse!"
     
      Call GetWindowRect(hWnd, typRect)
      Call ClipCursor(typRect)
     
   End If
   fClip = Not fClip
End Sub

 =====================end==============
I am not sure if the above answer is what you are looking for: Try this idea, create an event in your usercontrol call MouseOver. Then in your usercontrol_mousemove event, raiseEvent MouseOver.

In Program, where the control is placed, create the procedure:
private sub Control_MouseOver()
  MouseInControl = true
end sub
private sub form_mouseMove()
  mouseincontrol = false
end sub

MouseInControl is a public variable, that you can test anytime you need to find where the mouse is. If you need more details, let me know. I have this working on a control, and it does work.
Okay I am working on modification and will send you the code ASAP.
Okay here is the mouse over proj.

you need : Label1 and  Timer1 .


=========== start ================

Option Explicit

Dim highlighted As Boolean

Private Type POINTAPI
    x As Long
    y As Long
End Type
Private Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

' Highlight the control.
Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    If highlighted Then Exit Sub
    highlighted = True
    Label1.ForeColor = vbRed
    Timer1.Enabled = True
End Sub

' See if we should unhighlight the control.
Private Sub Timer1_Timer()
Dim pt As POINTAPI

    ' See where the cursor is.
    GetCursorPos pt
   
    ' Translate into window coordinates.
    ScreenToClient hwnd, pt

    ' See if we're still within the control.
    If pt.x < Label1.Left Or pt.y < Label1.Top Or _
       pt.x > Label1.Left + Label1.Width Or _
       pt.y > Label1.Top + Label1.Height _
    Then
        highlighted = False
        Label1.ForeColor = vbBlack
        Timer1.Enabled = False
    End If
End Sub

================ end ===============

shay@hili.com

Again, I question this, since in the question, PedroMVGomes states that he is using a timer. The function I gave doesn't require the amount of resources, and yields the same results.
PedroMVGomes - What are your thoughts?
Again, I question this, since in the question, PedroMVGomes states that he is using a timer. The function I gave doesn't require the amount of resources, and yields the same results.
PedroMVGomes - What are your thoughts?

Author

Commented:
i would like if you explian me what does your answer do cos i'm not uderstanding
By not using a timer control at all, you free up resourses. In main form code body, declare a variable like this:

DIM bMouseInControl as boolean.

Then handle the event MouseOver like this:

private sub Control_MouseOver()
  MouseInControl = true
end sub

Private Sub Form1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    MouseInControl = False
End Sub

Also, handle the event for the forms mousemove, so that when the form is over the form, not the Usercontrol, it sets the varibale to false. You will have to handle this for each control on the form as well


MouseOver is an event that you create in your custom control, and that you call in the controls MouseMove Event.
Ex: (This code goes in custom control)

Private Sub UserControl_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    RaiseEvent MouseMove(Button, Shift, x, y)
    RaiseEvent MouseOver
End Sub



Let me know if you need clarification.

Ronnie

Author

Commented:
I do not consider that as an answer, a user control must be independent, as and ActiveX it can be in many places (including a web Page) and it isn't anyway possible to intruct the user of the control to do such coding, the control must provide itself in a way to detect that the mouse is no longer in it.

I've build it with a timer, and searching a way to do it without the timer, not a way to force the control user to do it

Commented:
You dont need a timer at all.  You can just use the mousemove command with an api call.  If you are not going to give the points to anyone else, I can post this code for you.
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.