Posts Tagged ‘minimized


[VB.Net] Q: Sending Mouseclicks/Keystrokes into minimized window

The question asked “What i want is how do i make a program to be able to send inputs (key clicks) into the application when it is minimized”

The solution:

Imports System.Runtime.InteropServices
Public Class Form1
    ''Minimise the window
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto) >  _
    Private Shared Function ShowWindow(ByVal hwnd As IntPtr, _
                          ByVal nCmdShow As Integer) As Integer
    End Function
    Private Const SW_SHOWMINIMIZED = 2
    ''Finding the Control
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto) >  _
    Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
                          ByVal childAfter As IntPtr, _
                          ByVal lclassName As String, _
                          ByVal windowTitle As String) As IntPtr
    End Function
    ''Sending the click
    Private Declare Auto Function SendMessage Lib "user32" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
    Private Const BM_CLICK = &HF5

    Private Const WM_LBUTTONDOWN = &H201
    Private Const WM_LBUTTONUP = &H202
    Private Const BM_SETSTATE = &HF3
    ''Read the edit control
    Private Declare Auto Function SendMessage Lib "user32" (ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As System.Text.StringBuilder) As IntPtr
    Private Const WM_GETTEXT = &HD
    Private Const WM_GETTEXTLENGTH As Integer = &HE
    ''Keyboard Input
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto) >  _
    Private Shared Function PostMessage( _
                          ByVal hWnd As IntPtr, _
                          ByVal Msg As UInteger, _
                          ByVal wParam As IntPtr, _
                          ByVal lParam As IntPtr) As Boolean
    End Function
    Private Const WM_KEYDOWN = &H100
    Private Const WM_KEYUP = &H101
    Private Const WM_SYSKEYDOWN = &H104
    Private Const WM_SYSKEYUP = &H105

    Private Function GetAnswer(ByVal hWnd As Integer) As String
        ''Get the controls handle
        Dim calc_textHandle As Integer = FindWindowEx(hWnd, IntPtr.Zero, "Edit", vbNullChar)
        ''Get length of the text
        Dim calc_textLen As IntPtr = SendMessage(calc_textHandle, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero)
        ''Create string builder
        Dim calc_textSb As New System.Text.StringBuilder(calc_textLen.ToInt32 + 2)
        ''Get text
        SendMessage(calc_textHandle, WM_GETTEXT, calc_textLen.ToInt32 + 2, calc_textSb)
        If Not calc_textSb.ToString = "" Then
            Return ("Result: " & calc_textSb.ToString)
            Return ("Error Reading Answer")
        End If
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim ProcessFileName As String = "calc"
        Dim p As Process = Process.GetProcessesByName(ProcessFileName)(0)
        '   Instead of using Process.GetProcessByName, you could use:
        '        Private Declare Auto Function FindWindow Lib "user32" (ByVal lpClassName As String,_
        '                                    ByVal lpWindowName As String) As IntPtr
        ' FindWindow('SciCalc', 'Calculator')
        '    or FindWindow('SciCalc', vbNullChar)
        '       or FindWindow(vbNullChar, 'Calculator')
        'To return the handle of the window

        ''Minimise Window
        ShowWindow(p.MainWindowHandle, SW_SHOWMINIMIZED)

        ''Now to do a basic sum on the calculator
        ''Firstly reset the calculator, and then do 1+1="

        Dim calc_CButton As Integer = FindWindowEx(p.MainWindowHandle, IntPtr.Zero, "Button", "C")
        SendMessage(calc_CButton, BM_CLICK, 0, 0)
        Dim calc_1Button As Integer = FindWindowEx(p.MainWindowHandle, IntPtr.Zero, "Button", "1")
        SendMessage(calc_1Button, BM_CLICK, 0, 0)
        Dim calc_plusButton As Integer = FindWindowEx(p.MainWindowHandle, IntPtr.Zero, "Button", "+")
        SendMessage(calc_plusButton, BM_CLICK, 0, 0)
        ''1, instead of using BM_CLICK using Mouse events [BM_CLICK works fine]
        SendMessage(calc_1Button, WM_LBUTTONDOWN, 0, 0)
        SendMessage(calc_1Button, BM_SETSTATE, 1, 0)
        SendMessage(calc_1Button, WM_LBUTTONUP, 0, 0)
        Dim calc_equalButton As Integer = FindWindowEx(p.MainWindowHandle, IntPtr.Zero, "Button", "=")
        SendMessage(calc_equalButton, BM_CLICK, 0, 0)

        ''Now read the results

        ''Now using Keyboard input
        ''Escape Key to clear textbox
        PostMessage(p.MainWindowHandle, WM_KEYDOWN, Keys.Escape, 0)
        PostMessage(p.MainWindowHandle, WM_KEYUP, Keys.Escape, 0)
        PostMessage(p.MainWindowHandle, WM_KEYUP, Keys.D5, 0)
        PostMessage(p.MainWindowHandle, WM_KEYUP, Keys.Multiply, 0)
        PostMessage(p.MainWindowHandle, WM_KEYUP, Keys.D1, 0)
        PostMessage(p.MainWindowHandle, WM_KEYUP, Keys.D0, 0)
        PostMessage(p.MainWindowHandle, WM_KEYUP, &HBB, 0)
    End Sub
End Class

This is an old project demonstrating how to click buttons and send keys to a minimised window.
Use FindWindow/FindWindowEx/EnumChildWindows/etc to get the handle of the button
Then I would use the BM_CLICK message as the Msg param however you could also use WM_LBUTTONDOWN+BM_SETSTATE(1)+WM_LBUTTONUP

The above is an example using Windows Calculator. It clicks the buttons on the form, sends key presses, and gets the answer.