foreground form interaction

mcfly

Well-known member
Joined
Jun 15, 2009
Messages
54
Programming Experience
Beginner
Hi all,

I have a small program I have designed to be able to sit in the background on my desktop, and whenever a new form is given focus (foreground) it's title and thread are recorded.

However, I would like the program to also report to me the X and Y coordinates of the foreground form. Could be any form NOT one that is attached to my program.

Here's what I have thus far:



VB.NET:
Imports System.Text
Imports System.Runtime.InteropServices

Public Class Form1

    'gets x and y coordinates
    Dim xloc, yloc As Integer

    Private Declare Auto Function GetForegroundWindow Lib "user32" () As IntPtr
    Private Const WM_GETTEST As Integer = &HD

    <DllImport("User32")> _
    Private Shared Function GetWindowText(ByVal hwnd As IntPtr, <Out()> ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
    End Function

    <DllImport("User32", SetlastError:=True)> _
    Private Shared Sub SendMessage(ByVal hwnd As IntPtr, ByVal messageId As Integer, ByVal wparam As Integer, <Out()> ByVal lpString As System.Text.StringBuilder)
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'used for making the form appear at the lower left hand corner
        'Me.Top = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height - Me.Height
        'aligns form at the top right hand side
        Me.Left = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width - Me.Width
    End Sub

    Private Sub txtGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtGo.Click
        If txtGo.Text = "Stop" Then
            brain.Enabled = False
            txtGo.Text = "Go"
            Exit Sub
        Else
            brain.Enabled = True
            txtGo.Text = "Stop"
        End If
    End Sub

    Private Sub brain_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles brain.Tick
        'get x, y coordinates
        xloc = Me.Location.X
        txtX.Text = xloc

        yloc = Me.Location.Y
        txtY.Text = yloc

        'get thread pointer
        Dim formPointer As IntPtr = GetForegroundWindow

        TextBox1.Text = formPointer

        Dim valueToRetrive As New StringBuilder(100)
        Dim remoteHandle As IntPtr = New IntPtr(Convert.ToInt32(TextBox1.Text))

        'GetWindowText(remoteHandle, valueToRetrive, 100)
        SendMessage(remoteHandle, WM_GETTEST, 100, valueToRetrive)

        TextBox2.Text = valueToRetrive.ToString()
        'MessageBox.Show(valueToRetrive.ToString())
    End Sub
End Class

Currently only set to give the coordinates of the form I have created, I need it to show the coordinates of any form on the foreground.

Hope this makes sense. Any ideas!
 
Thanks for your response, this works on the windows form thats in my application but I would like the coorindates of any foreground form, which currently my code doesn't seem to grab. Have I missed something simple:confused: at the moment it will get all information from the form that I created in visual studio but wont gather the coorindates from foreign forms like mspaint, ms word etc, it display there process id and name but that appears to be it, any ideas :)


VB.NET:
Option Explicit On
Imports System.Text
Imports System.Runtime.InteropServices

Public Class Form1

    Private Declare Auto Function GetForegroundWindow Lib "user32" () As IntPtr

    Private Const WM_GETTEXT As Integer = &HD

    <DllImport("User32", SetlastError:=True)> _
    Private Shared Sub SendMessage(ByVal hwnd As IntPtr, ByVal messageId As Integer, ByVal wparam As Integer, <Out()> ByVal lpString As System.Text.StringBuilder)
    End Sub

    Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Int32, ByRef lpRect As RECT) As Int32

    Structure RECT
        Public Left As Int32
        Public Top As Int32
        Public Right As Int32
        Public Bottom As Int32
    End Structure

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'aligns form at the top right hand side 
        Me.Left = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width - Me.Width
    End Sub

    Private Sub txtGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtGo.Click
        If txtGo.Text = "Stop" Then
            brain.Enabled = False
            txtGo.Text = "Go"
            Exit Sub
        Else
            brain.Enabled = True
            txtGo.Text = "Stop"
        End If
    End Sub

    Private Sub brain_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles brain.Tick
        'get thread pointer
        Dim formPointer As IntPtr = GetForegroundWindow
        TextBox1.Text = formPointer

        Dim valueToRetrive As New StringBuilder(100)
        Dim remoteHandle As IntPtr = New IntPtr(Convert.ToInt32(TextBox1.Text))

        'get form name
        SendMessage(remoteHandle, WM_GETTEXT, 100, valueToRetrive)
        txtName.Text = valueToRetrive.ToString()

        'get RECT coordinates
        Dim r As RECT
        GetWindowRect(Handle, r)
        Dim rct As Rectangle = Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom)

        txtL.Text = Left
        txtR.Text = Right
        txtT.Text = Top
        txtB.Text = Bottom
    End Sub
End Class
 
The handle parameter (hWnd) is the window handle of the window you want to get rectangle for. Currently you're using the Handle property of your form, so that is the rectangle you get. Use the handle returned by GetForegroundWindow function instead. :)
 
i have tried the code below which is just inserting the word "formPointer" as I think this is the pointer but as you can tell i am sort of clutching at straws, it still only gets the current form so i know i haven't done it right :confused:


VB.NET:
    Private Sub brain_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles brain.Tick
        'get thread pointer
        Dim formPointer As IntPtr = GetForegroundWindow
        TextBox1.Text = formPointer

        Dim valueToRetrive As New StringBuilder(100)
        Dim remoteHandle As IntPtr = New IntPtr(Convert.ToInt32(TextBox1.Text))

        'get form name
        SendMessage(remoteHandle, WM_GETTEXT, 100, valueToRetrive)
        txtName.Text = valueToRetrive.ToString()

        'get RECT coordinates
        Dim r As RECT
        'GetWindowRect(Handle, r)
        GetWindowRect(formPointer, r)
        Dim rct As Rectangle = Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom)

        txtL.Text = Left
        txtR.Text = Right
        txtT.Text = Top
        txtB.Text = Bottom
    End Sub

trouble is i find i insert code statements like this and they don't really make much sense to me

VB.NET:
    Private Declare Auto Function GetForegroundWindow Lib "user32" () As IntPtr

    Private Const WM_GETTEXT As Integer = &HD

    <DllImport("User32", SetlastError:=True)> _
    Private Shared Sub SendMessage(ByVal hwnd As IntPtr, ByVal messageId As Integer, ByVal wparam As Integer, <Out()> ByVal lpString As System.Text.StringBuilder)
    End Sub

    Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Int32, ByRef lpRect As RECT) As Int32

    Structure RECT
        Public Left As Int32
        Public Top As Int32
        Public Right As Int32
        Public Bottom As Int32
    End Structure
 
tried this line also but still no luck, this is rather confusing :(

GetWindowRect(remoteHandle, r)
 
finally...

'get thread pointer
Dim formPointer As IntPtr = GetForegroundWindow
TextBox1.Text = formPointer

Dim valueToRetrive As New StringBuilder(100)
Dim remoteHandle As IntPtr = New IntPtr(Convert.ToInt32(TextBox1.Text))

'get form name
SendMessage(remoteHandle, WM_GETTEXT, 100, valueToRetrive)
txtName.Text = valueToRetrive.ToString()

'get RECT coordinates
Dim r As RECT
GetWindowRect(remoteHandle, r)

Dim rct As Rectangle = Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom)

txtL.Text = r.Left
txtR.Text = r.Right
txtT.Text = r.Top
txtB.Text = r.Bottom

:) :) :)

thanks for all the Help :)
 
Why are you converting the IntPtr handle, first to String, then to Integer, then to IntPtr? You already have the IntPtr handle returned from GetForegroundWindow to be used directly in the other API calls.
 
to be honest, I am at the learning stage where I just play round with the code and if it works then I quickly don't touch it lol, not a good way I know but any other ideas I would be more than happy to take onboad :D

Below is now what I have, works accept it's not picking out the cursor location?

VB.NET:
Option Explicit On
Imports System.Text
Imports System.Runtime.InteropServices

Public Class Form1

    Private Declare Auto Function GetForegroundWindow Lib "user32" () As IntPtr

    Private Const WM_GETTEXT As Integer = &HD

    <DllImport("User32", SetlastError:=True)> _
    Private Shared Sub SendMessage(ByVal hwnd As IntPtr, ByVal messageId As Integer, ByVal wparam As Integer, <Out()> ByVal lpString As System.Text.StringBuilder)
    End Sub

    Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Int32, ByRef lpRect As RECT) As Int32

    Structure RECT
        Public Left As Int32
        Public Top As Int32
        Public Right As Int32
        Public Bottom As Int32
    End Structure

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'aligns form at the top right hand side 
        Me.Left = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width - Me.Width
    End Sub

    Private Sub txtGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGo.Click
        If btnGo.Text = "Stop" Then
            brain.Enabled = False
            btnGo.Text = "Go"
            Exit Sub
        Else
            brain.Enabled = True
            btnGo.Text = "Stop"
        End If
    End Sub

    'API Functions, Subs and Constants
    Public Declare Auto Function SetCursorPos Lib "User32.dll" (ByVal X As Integer, ByVal Y As Integer) As Long
    Public Declare Auto Function GetCursorPos Lib "User32.dll" (ByRef lpPoint As Point) As Long
    Public Declare Sub mouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
    Public Const MOUSEEVENTF_LEFTDOWN = &H2 ' left button down
    Public Const MOUSEEVENTF_LEFTUP = &H4 ' left button up
    Public Const MOUSEEVENTF_MIDDLEDOWN = &H20 ' middle button down
    Public Const MOUSEEVENTF_MIDDLEUP = &H40 ' middle button up
    Public Const MOUSEEVENTF_RIGHTDOWN = &H8 ' right button down
    Public Const MOUSEEVENTF_RIGHTUP = &H10 ' right button up

    Private Sub brain_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles brain.Tick
        'get thread pointer
        Dim formPointer As IntPtr = GetForegroundWindow
        TextBox1.Text = formPointer

        Dim valueToRetrive As New StringBuilder(100)
        Dim remoteHandle As IntPtr = New IntPtr(Convert.ToInt32(TextBox1.Text))

        'get form name
        SendMessage(remoteHandle, WM_GETTEXT, 100, valueToRetrive)
        txtName.Text = valueToRetrive.ToString()

        'get RECT coordinates to thread called remoteHandle
        Dim r As RECT
        GetWindowRect(remoteHandle, r)

        Dim rct As Rectangle = Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom)

        txtL.Text = r.Left
        txtR.Text = r.Right
        txtT.Text = r.Top
        txtB.Text = r.Bottom

        If txtName.Text = "Databases" Then

            'call move cursor
            moveCursor()

        End If

        Dim tempPos As Point
        Dim cursorLoc As Long = GetCursorPos(tempPos) ' get your location in TempPos

        txtCursor.Text = cursorLoc

    End Sub

    Public Sub moveCursor()
        'move the cusor
        SetCursorPos(10, 10) ' Where X and Y are in pixel
        'MsgBox("Moved cursor")

        'turn off the timer
        brain.Enabled = False
        btnGo.Text = "Go"
    End Sub
End Class

the next stage of the program is too actually analize parts of the form to determine whats shown and then perform clicks on buttons on the screen :)
 
Back
Top