Results 1 to 5 of 5

Thread: [RESOLVED] Trouble extracting Checkbox State from external application

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2007
    Posts
    523

    Resolved [RESOLVED] Trouble extracting Checkbox State from external application

    I am trying to determine the state of a checkbox in an external program from a VB.Net WinForm application. I used Spy++ to get the handle of the checkbox. I convert the handle from hex to decimal, and enter it into a textbox (I automatically extract the handle in my full application). I can toggle the checkbox from my program, so I know i have the correct handle. However I can not seem to GETSTATE or GETCHECK using SendMessage. I was not sure which I should be using, but they both always return 0. Here is my module code:


    Code:
    Imports System.Runtime.InteropServices
    Module Module1
    
        Public Const BM_CLICK = &HF5
        Public Const BM_GETCHECK = &HF0
        Public Const BM_GETSTATE = &HF2
    
        <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        End Function
    
        Sub toggle(hwnd As IntPtr)
            SendMessage(hwnd, BM_CLICK, 0, 0)
        End Sub
    
        Function GetCheck(hwnd As IntPtr) As Integer
            Return SendMessage(hwnd, BM_GETCHECK, 0, 0)
        End Function
    
        Function GetState(hwnd As IntPtr) As Integer
            Return SendMessage(hwnd, BM_GETSTATE, 0, 0)
        End Function
    End Module
    and my form code

    Code:
    Public Class Form1
        Private Sub btnToggle_Click(sender As Object, e As EventArgs) Handles btnToggle.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            toggle(hwnd)
        End Sub
    
        Private Sub btnGetStatus_Click(sender As Object, e As EventArgs) Handles btnGetStatus.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            lblState.Text = GetState(hwnd).ToString
        End Sub
    
        Private Sub btnGetChk_Click(sender As Object, e As EventArgs) Handles btnGetChk.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            lblCheck.Text = GetCheck(hwnd).ToString
        End Sub
    End Class
    Any help would be appreciated

  2. #2
    Frenzied Member
    Join Date
    Feb 2003
    Posts
    1,807

    Re: Trouble extracting Checkbox State from external application

    Quote Originally Posted by John_SC View Post
    I am trying to determine the state of a checkbox in an external program from a VB.Net WinForm application. I used Spy++ to get the handle of the checkbox. I convert the handle from hex to decimal, and enter it into a textbox (I automatically extract the handle in my full application). I can toggle the checkbox from my program, so I know i have the correct handle. However I can not seem to GETSTATE or GETCHECK using SendMessage. I was not sure which I should be using, but they both always return 0. Here is my module code:


    Code:
    Imports System.Runtime.InteropServices
    Module Module1
    
        Public Const BM_CLICK = &HF5
        Public Const BM_GETCHECK = &HF0
        Public Const BM_GETSTATE = &HF2
    
        <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        End Function
    
        Sub toggle(hwnd As IntPtr)
            SendMessage(hwnd, BM_CLICK, 0, 0)
        End Sub
    
        Function GetCheck(hwnd As IntPtr) As Integer
            Return SendMessage(hwnd, BM_GETCHECK, 0, 0)
        End Function
    
        Function GetState(hwnd As IntPtr) As Integer
            Return SendMessage(hwnd, BM_GETSTATE, 0, 0)
        End Function
    End Module
    and my form code

    Code:
    Public Class Form1
        Private Sub btnToggle_Click(sender As Object, e As EventArgs) Handles btnToggle.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            toggle(hwnd)
        End Sub
    
        Private Sub btnGetStatus_Click(sender As Object, e As EventArgs) Handles btnGetStatus.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            lblState.Text = GetState(hwnd).ToString
        End Sub
    
        Private Sub btnGetChk_Click(sender As Object, e As EventArgs) Handles btnGetChk.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            lblCheck.Text = GetCheck(hwnd).ToString
        End Sub
    End Class
    Any help would be appreciated
    Not sure whether this is useful in your case, but I generally always check for errors after calling an API function. Try calling the System.Runtime.InteropServices.Marshal.GetLastWin32Error() function immediately after calling the PostMessage API function to get the error code of any error that might have occurred. You can get a description for the error code as follows:

    Code:
    Dim Message As String = New System.ComponentModel.Win32Exception(error code).Message
    Hope this helps.
    Last edited by Peter Swinkels; Jan 3rd, 2017 at 09:38 AM.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2007
    Posts
    523

    Re: Trouble extracting Checkbox State from external application

    Thanks for the suggestion. When I checked for any errors, it came back saying it completed successfully, but still had values of zero in all cases.
    So I went looking for another checkbox to test this on, and found one in the Windows File Manager. When I ran the same code on that GetChecked came back with 1 for checked and 0 for unchecked. GetState came back with 9 for checked and 8 for unchecked. So the code works.

    Note, the target application was created in visual Basic specifically to test this functionality. Apparently, GetChecked and GetState don't work with the checkbox in VS 2013 v 4 with .Net Framework 4.6. This is odd since BM_Click does work.

    According to https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx, BM_Check will only work with "button created with the BS_AUTOCHECKBOX, BS_AUTORADIOBUTTON, BS_AUTO3STATE, BS_CHECKBOX, BS_RADIOBUTTON, or BS_3STATE style. ... If the button has a style other than those listed, the return value is zero." So I am guessing the checkbox I am trying to automate is not one of these.

    Any suggestions as to how I can determine the check state? I have seen a number of posts about Windows UI Automation, but I have not invested the time to figure that out yet.

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2007
    Posts
    523

    Re: Trouble extracting Checkbox State from external application

    I got something to work, but it is a bit odd.

    * As written in VB, I was unable to toggle either a checkbox or a radio button in my test application.
    * I went in a set the button style to one of the button styles that are supported. I specified that the control should be redrawn, but nothing obvious changed when I did this.
    * When I changed a checkbox style to BS_CHECKBOX, I still was unable to retrieve its value.
    * When I changed either the radio button or the check box to BS_RADIOBUTTON, I was able to extract the check state.
    * The check box still looked and worked like a checkbox (Very ODD)
    * The radio button still looked and worked like a radio button.

    Here is the module code I used:

    Code:
    Imports System.Runtime.InteropServices
    Module Module1
    
    
        Public Const BM_GETCHECK = &HF0
        Public Const BM_SETCHECK = &HF1
        Public Const BM_GETSTATE = &HF2
        Public Const BM_SETSTATE = &HF3
        Public Const BM_SETSTYLE = &HF4
        Public Const BM_CLICK = &HF5
    
    
        Private Const BST_UNCHECKED = &H0&
        Private Const BST_CHECKED = &H1&
        Private Const BST_INDETERMINATE = &H2&
        Private Const BST_PUSHED = &H4&
        Private Const BST_FOCUS = &H8&
    
        Private Const BS_CHECKBOX = &H2
        Private Const BS_RADIOBUTTON = &H4
    
        <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        End Function
    
        Sub toggle(hwnd As IntPtr)
            SendMessage(hwnd, BM_CLICK, 0, 0)
        End Sub
    
        Function GetCheck(hwnd As IntPtr) As Integer
            Dim x, y As Integer
            x = SendMessage(hwnd, BM_GETCHECK, 0, 0)
            y = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Dim Message As String = New System.ComponentModel.Win32Exception(y).Message
            Return x
        End Function
    
        Function GetState(hwnd As IntPtr) As Integer
            Dim x, y As Integer
            x = SendMessage(hwnd, BM_GETSTATE, 0, 0)
            y = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Dim Message As String = New System.ComponentModel.Win32Exception(y).Message
            Return x
        End Function
    
        Function Setstate(hwnd As IntPtr) As Integer
            Dim x, y As Integer
            x = SendMessage(hwnd, BM_SETSTATE, BST_UNCHECKED, 0)
            y = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Dim Message As String = New System.ComponentModel.Win32Exception(y).Message
            Return x
        End Function
    
        Function Setcheck(hwnd As IntPtr) As Integer
            Dim x, y As Integer
            x = SendMessage(hwnd, BM_SETCHECK, BST_UNCHECKED, 0)
            y = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Dim Message As String = New System.ComponentModel.Win32Exception(y).Message
            Return x
        End Function
    
    
        Function MakeCheckbox(hwnd As IntPtr) As Integer
            Dim x, y As Integer
            x = SendMessage(hwnd, BM_SETSTYLE, BS_CHECKBOX, CInt(True))
            y = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Dim Message As String = New System.ComponentModel.Win32Exception(y).Message
            Return x
        End Function
    
    
    
        Function MakeRadiobutton(hwnd As IntPtr) As Integer
            Dim x, y As Integer
            x = SendMessage(hwnd, BM_SETSTYLE, BS_RADIOBUTTON, CInt(True))
            y = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Dim Message As String = New System.ComponentModel.Win32Exception(y).Message
            Return x
        End Function
    
    End Module
    And here is the Class Code
    Code:
    Public Class Form1
        Private Sub btnToggle_Click(sender As Object, e As EventArgs) Handles btnToggle.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            toggle(hwnd)
        End Sub
    
        Private Sub btnGetStatus_Click(sender As Object, e As EventArgs) Handles btnGetStatus.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            lblState.Text = GetState(hwnd).ToString
        End Sub
    
        Private Sub btnGetChk_Click(sender As Object, e As EventArgs) Handles btnGetChk.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            lblCheck.Text = GetCheck(hwnd).ToString
        End Sub
    
        Private Sub Load_Click(sender As Object, e As EventArgs) Handles Load.Click
            TextBox1.Text = Val("&H" & TextBox2.Text.Trim).ToString
        End Sub
    
        Private Sub btnSet_Click(sender As Object, e As EventArgs) Handles btnSet.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            lblset.Text = SetCheck(hwnd).ToString
    
        End Sub
    
        Private Sub btnMakeCBX_Click(sender As Object, e As EventArgs) Handles btnMakeCBX.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            Dim s As String = MakeCheckbox(hwnd).ToString
    
        End Sub
    
        Private Sub btnMakeRBN_Click(sender As Object, e As EventArgs) Handles btnMakeRBN.Click
            Dim hwnd As IntPtr = CType(TextBox1.Text, IntPtr)
            Dim s As String = MakeRadiobutton(hwnd).ToString
    
        End Sub
    End Class

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2007
    Posts
    523

    Re: [RESOLVED] Trouble extracting Checkbox State from external application

    I thought I would make it easier for anyone interested and uploaded the application. See the attached zip file.
    I added some instructions on the form and cleaned up the code a little, so it is slightly different that what I posted earlier (added ability to SetCheck either on or off, and changed the name of the Load button to eliminate a warning).
    I hope you find this useful.
    Attached Files Attached Files

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width