0

I am writing an application to interface two other existing applications. I'm new to C# so this is quite the challenge for me. My current issue that I have yet to find an answer for is whether a checkbox is checked or not. I was trying to use UIAutomation but I couldn't figure out how to get it working. When I check the checkbox using UISpy it indicates that the checkbox is a pane. after much searching over 2 days I couldn't find out how to get the information for a checkbox as a pane. I was thinking that pInvoke would do the trick but I haven't had any luck with that either. Here is what I have tried:

var ischecked = NativeMethods.SendMessage(variables.allCNumbers[29].Hwnd,BM_GETSTATE, IntPtr.Zero, IntPtr.Zero);
MessageBox.Show(variables.allCNumbers[29].Hwnd.ToString()); // This has a value
MessageBox.Show(ischecked.ToString()); // This always shows 0 whether the checkbox is checked or not

Here is the UIAutomation I have tried:

    AutomationElement rootElement = AutomationElement.RootElement;

            Automation.Condition condition = new PropertyCondition(AutomationElement.ClassNameProperty,"TMainForm_ihm" );
        AutomationElement appElement = rootElement.FindFirst(TreeScope.Children, condition);
        AutomationElement workspace = appElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Workspace"));

        AutomationElement card = workspace.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Card"));

        AutomationElement pagecontrol = card.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "TRzPageControl"));
        AutomationElement cardnumber = pagecontrol.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Card number"));

        if(cardnumber != null)
        {
            Automation.Condition usecardCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, "25232366");
            AutomationElement usecard = cardnumber.FindFirst(TreeScope.Children, usecardCondition);

            MessageBox.Show("usecard: " + usecard.Current.ControlType.ProgrammaticName); // This returns "ControlType.Pane"

            //TogglePattern tp1 = usecard.GetCurrentPattern(TogglePattern.Pattern) as TogglePattern; <- This throws an error: An unhandled exception of type 'System.InvalidOperationException' occurred in UIAutomationClient.dll  Additional information: Unsupported Pattern.
            //MessageBox.Show(tp1.Current.ToggleState.ToString());
        }

Any help is greatly appreciated.

NewToC
  • 1
  • 4
  • Isn't there a proper API available? I would find this code.. interesting, if I would find this in my codebase. – Caramiriel Nov 19 '15 at 12:34
  • no API available. Like I said I am new to all of this. I'm sure "interesting" isn't exactly a compliment, but I don't take as an insult either. I really do want to learn the right way to do things but at this point I'm just trying to make things work. I have learned a lot over the past several weeks (I just started working with C# in September) and have re-written a lot since learning how wrong I was. – NewToC Nov 19 '15 at 12:37
  • It's not meant as an insult. Usually what happens is that data is made available indirectly through an API (either the application is extended, or another application is made to retrieve this data). This way the UI can still change of the originating application(s), but your application will still work. I'm not exactly sure how this other application works, so I'm afraid I can't give you more details with the information that you have provided. – Caramiriel Nov 19 '15 at 12:44
  • Try Winapi. .. check this link: https://bytes.com/topic/net/answers/637107-how-find-out-if-check-box-checked – K-Dawg Nov 19 '15 at 12:53
  • Automation framework isn't supported by Windows controls so try the link I sent you above – K-Dawg Nov 19 '15 at 12:54
  • thank you for your reply anyway. I just don't know enough to provide the proper information I guess. Basically from what I think I am seeing using spy is that everything on the form is dynamically created. there are 20 checkboxes on the same form all with the same class name and no window text. I used windowscrape to drill down the tree and get to the object that I need information from using "GetChildren". That's why variables.allCNumbers[29] (the checkbox / pane I am looking for information from is the 29th item in the array) I call it an array because I don't know any different. – NewToC Nov 19 '15 at 12:55
  • @Prime By Design Thank you for that. I've used pInvoke for a lot of things on this project like moving buttons and changing text. Would that work for this as well? I read the link you posted and I'm trying to get it figured out but I'm not sure how to get the guid of the control yet. – NewToC Nov 19 '15 at 13:37
  • I have a project somewhere that does this – K-Dawg Nov 19 '15 at 14:15
  • At work right now will have a look this evening when I get home – K-Dawg Nov 19 '15 at 14:16
  • What is the ClassName property on the check box and what is it after it has changed to a pane? I just double checked a couple check boxes in various applications made with various frameworks and none of them switched to a pane when toggled on. – Max Young Nov 24 '15 at 20:00
  • @Max Young It doesn't change to a pane. When I inspect it using UISpy it shows as being a pane. When I inspect it using Spy++ it has a class name but no text. There are 30 children of the same window and 20 of these children are all checkboxes (or at least look like checkboxes). All of the checkboxes have the same class name of "TCheckBoxFd" and all have the same properties. No tag, no text, and no name. They each have their own handle. I can move them, change their appearance, or whatever else I want to do to them but I can't seem to figure out how to tell if they are checked or not. – NewToC Nov 26 '15 at 14:28

1 Answers1

0

I used this post https://bytes.com/topic/net/answers/637107-how-find-out-if-check-box-checked as inspiration:

using Accessibility;

[DllImport("oleacc.dll", PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern object AccessibleObjectFromWindow(IntPtr hwnd, uint dwId, ref Guid riid);

public static Nullable<bool> isCheckBoxChecked(IntPtr checkBoxHandle)
{
    const UInt32 OBJID_CLIENT = 0xFFFFFFFC;
    const int UNCHECKED       = 1048576;
    const int CHECKED         = 1048592;
    Guid uid = new Guid("618736e0-3c3d-11cf-810c-00aa00389b71");

    IAccessible accObj = (IAccessible)AccessibleObjectFromWindow(checkBoxHandle, OBJID_CLIENT, ref uid);
    object o2 = accObj.get_accState(0);
    if ((int)o2 == UNCHECKED)
    {
        return false;
    }
    else if ((int)o2 == CHECKED)
    {
        return true;
    }
    else
    {
        return null;
    }
}
arnold_w
  • 59
  • 9