How do I inject click and combo box select event into windows application using vbscript RRS feed

  • Question

  • Hi,

     I am new to, I need to do sample 5+6=11 operation in calculator windows application. I have the class attributes for respective data as num5Button(5), plusbutton(+), num6Button(6) and equalButton(=). I did  up to this:

    Set WshShell = WScript.CreateObject("WScript.Shell")

    WshShell.Run "calc"

    HWND = WshShell.WinGetHandle("Calculator") // this line is throwing error

    but  i did this in autoit script as 

    Open up Calculator

    Get the handle for Calculator
    $hWnd = WinGetHandle('Calculator') ;
    click 5
    ControlClick($hWnd, "", "[CLASSNN:num5Button]");

    click +

    click 6

    click =

    How should do the same process in VBScript instead of using sendkeys in VBScript? Is anyone knows please help me to resolve this

    • Moved by Bill_Stewart Wednesday, November 1, 2017 12:25 PM Move to more appropriate forum
    Wednesday, November 1, 2017 5:50 AM

All replies

  •  Your question is not clear as to weather you want to do this in VB.Net or if you want to do this in VBScript.  You say you are new to VB.Net but,  you are asking how to do it in VbScript.  Please clarify what language you are using.

     If it is VB.Net that you are using and you want to do in Vb.Net what you have shown VbScript for then the below example will let you send a String array or List of the buttons to calculator and get the result back too.  It will work if calculator is minimized,  in the background,  or in the foreground.  It is only set up for Calculator set to the Basic mode as shown in the animated image at the bottom of this post.

     I have only tested it with Windows 7 so,  not sure if it will work with calculator in Windows 8, 9, and 10.

     In Windows 7,  you can not get the text from the buttons to identify which is which so,  the only way to identify them is getting the handles of each button in the order that they where added to calculator.  The array of the buttons text (BtnTxt) at the top of the code is in the order they are retrieved,  the same way they where added to calculator in the basic mode.

    Imports System.Runtime.InteropServices
    Public Class Form1
        Private BtnTxt() As String = {"MC", "BackSpace", "7", "4", "1", "0", "MR", "CE", "8", "5", "2", "MS", "C", "9", "6", "3", ".", "M+", "ChangeSign", "/", "*", "-", "+", "M-", "SquareRoot", "%", "1/x", "="}
        Private BasicCalcButtons As New Dictionary(Of String, IntPtr)
        Private hDisplay As IntPtr = IntPtr.Zero
        Private CalcProcess As Process = Nothing
        Private Sub Button_GetCalcButtons_Click(sender As Object, e As EventArgs) Handles Button_GetCalcButtons.Click
            CalcProcess = Process.GetProcessesByName("Calc").FirstOrDefault 'try getting the first instance of calculator that may be running
            If CalcProcess Is Nothing OrElse CalcProcess.HasExited Then
                CalcProcess = Process.Start("calc.exe")
                Threading.Thread.Sleep(2000) 'wait a second or two for calculator to open
            End If
            Dim hCalcFrame As IntPtr = FindWindowExW(CalcProcess.MainWindowHandle, IntPtr.Zero, "CalcFrame", Nothing)
            Dim hDialog As IntPtr = FindWindowExW(hCalcFrame, IntPtr.Zero, "#32770", Nothing)
            hDisplay = FindWindowExW(hDialog, IntPtr.Zero, "Static", Nothing)
            hDisplay = FindWindowExW(hDialog, hDisplay, "Static", Nothing)
            hDisplay = FindWindowExW(hDialog, hDisplay, "Static", Nothing)
            hDialog = FindWindowExW(hCalcFrame, hDialog, "#32770", Nothing)
            Dim ButtonIndex As Integer = 0
            Dim hButton As IntPtr = FindWindowExW(hDialog, IntPtr.Zero, Nothing, Nothing) 'try getting the first button's handle
            While hButton <> IntPtr.Zero 'while there is a button found, keep iterating through the buttons and get their handles
                BasicCalcButtons.Add(BtnTxt(ButtonIndex), hButton)
                ButtonIndex += 1
                hButton = FindWindowExW(hDialog, hButton, Nothing, Nothing)
            End While
        End Sub
        Private Function GetCalculatorDisplayText() As String
            Dim sb As New System.Text.StringBuilder(256)
            GetWindowTextW(hDisplay, sb, sb.Capacity)
            Return sb.ToString
        End Function
        Private Sub Button_SendButtons_Click(sender As Object, e As EventArgs) Handles Button_SendButtons.Click
            If CalcProcess IsNot Nothing AndAlso Not CalcProcess.HasExited Then
                Dim BtnsToSend As String() = {"5", "+", "6", "="} 'add each button's text in the order you want to click them. You can see each button text to use in the (BtnTxt) array.
                For Each btn As String In BtnsToSend
                    SendMessageW(BasicCalcButtons(btn), BM_CLICK, 0, 0)
                Label1.Text = GetCalculatorDisplayText()
            End If
        End Sub
    #Region "Win32Apis"
        Private Const BM_CLICK As Integer = &HF5
        <DllImport("user32.dll", EntryPoint:="SendMessageW")>
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer
        End Function
        <DllImport("user32.dll", EntryPoint:="FindWindowExW")>
        Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
        End Function
        <DllImport("user32.dll", EntryPoint:="GetWindowTextW")>
        Private Shared Function GetWindowTextW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpString As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    #End Region
    End Class

     Here is the above example....  You only need to get the calculator buttons once,  then do however many sends as you want.  However,  if calculator is closed while the app is running,  you will need to get the buttons again.

    If you say it can`t be done then i`ll try it

    Wednesday, November 1, 2017 11:01 PM
  • How should do the same process in VBScript instead of using sendkeys in VBScript?

    In VBScript instead of ... VBScript ?

    In VB.NET on Windows 10, use UIAutomation (UWP app) with the Automation Ids that you quoted ("num5Button", etc...)

    • Edited by Castorix31 Thursday, November 2, 2017 12:04 AM
    Thursday, November 2, 2017 12:03 AM
  • thanks, @IronRazerz, but I need this click event to be done by using its automation id attribute and I am sorry actually I need the solution in VBScript
    Friday, November 3, 2017 5:48 AM
  • @Castorix31 thanks for your response. Do you know any sample code to pass the controls using UIAutomation?
    Friday, November 3, 2017 5:50 AM
  • Sunitha,

    In Windows every app runs in its own window. 

    What is a window: just something through which you see the program.(Also grammatically)

    Can you come behind the window: only if there is something made to do that.

    If your app has no inter-op functions for that, then you are just pushing against the glass.  

    Most things are simple as long as you don't make them difficult. 


    Friday, November 3, 2017 6:21 AM