Link to home
Start Free TrialLog in
Avatar of crumley
crumleyFlag for United States of America

asked on

How do I find the control under the mouse?

How can I find the control under the mouse? I can't use WindowFromPoint or ChildWindowFromPoint if the window isn't active apparently. At least it doesn't give the right window handle. All I need to do, is get the handle of the control under the cursor. For example, Calculator in Windows. I want to be able to click...say, the "1" button. But I can't do this without having the control handle. I'd appreciate the code, but just the overview on how to do it would be great.
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

WindowFromPoint() works even when the window is not active...you must have done something wrong.

I don't code in C++, but here is an example in VB.Net of a Timer getting the current window under the cursor with WindowFromPoint(), getting the rectangle of that window with GetWinddowRect(), and then drawing that rectangle on the screen.

When I move the mouse over Calculator I get a small rectangle over each button indicating that it is retrieving the handle for just that control:
(and no, Calculator was NOT in focus during the mouse over)
Public Class Form1

    Private prevRC As Rect = Nothing

    Public Structure PointAPI

        Public X As Integer
        Public Y As Integer

        Public Sub New(ByVal x As Integer, ByVal y As Integer)
            Me.X = x
            Me.Y = y
        End Sub

    End Structure

    Public Structure Rect

        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer

        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            Dim otherRect As Rect = DirectCast(obj, Rect)
            Return Me.Left = otherRect.Left AndAlso Me.Top = otherRect.Top AndAlso Me.Right = otherRect.Right AndAlso Me.Bottom = otherRect.Bottom
        End Function

    End Structure

    Public Declare Function WindowFromPoint Lib "user32" (ByVal pt As PointAPI) As IntPtr
    Public Declare Function GetWindowRect Lib "user32" (ByVal handle As IntPtr, ByRef lpRect As Rect) As Integer

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim pt As New PointAPI(Cursor.Position.X, Cursor.Position.Y)
        Dim curHandle As IntPtr = WindowFromPoint(pt)
        Dim curRect As Rect
        GetWindowRect(curHandle, curRect)
        If Not curRect.Equals(Me.prevRC) Then
            If Not IsNothing(Me.prevRC) Then
                ControlPaint.DrawReversibleFrame(New Rectangle(prevRC.Left, prevRC.Top, prevRC.Right - prevRC.Left, prevRC.Bottom - prevRC.Top), Color.Black, FrameStyle.Thick)
            End If
            Me.prevRC = curRect
            ControlPaint.DrawReversibleFrame(New Rectangle(prevRC.Left, prevRC.Top, prevRC.Right - prevRC.Left, prevRC.Bottom - prevRC.Top), Color.Black, FrameStyle.Thick)
        End If
    End Sub

End Class

Open in new window

Avatar of crumley

ASKER

thanks. I actually am going to use Delphi for this project...so I'll work on translating your code. Thanks for the answer!!
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

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
crumbley, you don't have to translate it, his code gets the handle and draws a rectangle around the control, which is according to your question not what you needed. The WindowFromPoint alone should do what you need just fine.
Avatar of crumley

ASKER

@Freddy1990,

I've used WindowFromPoint/ChildWindowFromPoint, and it doesn't work when the parent window is unfocused or slightly underneath an overlapping window. I may have been not implementing in correctly, so if you would give me some example code I would be happy to try.
Avatar of crumley

ASKER

you more or less helped lol...the links you gave me helped a lot more than the code really did. So thanks a lot!!!