0

im currently working with IAccessible and try to automatically click and do some stuff.

It works fine for several Pushbuttons, Splitbutton and other elements.

The last element is a Windows Systemsetting which is a ROLE_SYSTEM_PUSHBUTTON.

accDoDefaultAction is ignored, same as SendMessage and PostMessage to the Window Handle.

Dummy Code:

private void SetAutoSettingTest()
{
  var RootWindowses = GetWindowsByName("Settings", "ApplicationFrameWindow");
  foreach (var RootWindows in RootWindowses) {
      var AccessableChild = MSAA.GetAccessibleObjectFromHandle(RootWindows.windowHandle);
      var IAccessibleLinkList = new List<IAccessible>();
      MSAA.GetAccessibleObjectListByRole(AccessableChild, "PushButton", ref IAccessibleLinkList, true);
      foreach (var IAccessibleCheckButton in IAccessibleLinkList) {
         AppendLog("Item in Settings AccessableButtonList (found)");
         if (IAccessibleCheckButton.get_accName(0).Equals("MySetting"))
            // it found the proper IAccessible Object. Verified 
            {
            Thread.Sleep(1000); // Just waited if the dialog was not finished WM_PAINT
            IAccessibleCheckButton.accSelect(0); // Was just a try, but didnt help
            IAccessibleCheckButton.accDoDefaultAction(0); // Is ignored
            var MyHandle = MSAA.GetHandle(IAccessibleCheckButton);
            AppendLog("HWND=" + MyHandle );  // It was a IntPtr (HWND)
            int IAccessibleLeft = 0, IAccessibleTop = 0, IAccessibleWidth = 0, IAccessibleHeight = 0;
            IAccessibleCheckButton.accLocation(out IAccessibleLeft, out IAccessibleTop, out IAccessibleWidth, out IAccessibleHeight, 0);
            Win.ShowWindow(RootWindows.windowHandle, Win.SW_SHOW); // just in cae it was minimized
            Win32.BringWindowToTop(MyHandle ); // just in case the Element to toggle was somehow in background
            Win.SetCursorPos(IAccessibleLeft, IAccessibleTop); // Used Mousepos and clicks which works, but not a clean solution
            Win.mouse_event(Win.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
            Win.mouse_event(Win.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
            AppendLog(String.Format("Location Left {0} Top {1} Width {2} Height {3}", IAccessibleLeft, IAccessibleTop, IAccessibleWidth, IAccessibleHeight)); // valid data
            }
         }
     }
} 

It returns a HWND but even PostMessage to the HWND are ignored.

The Role is ROLE_SYSTEM_PUSHBUTTON, State STATE_SYSTEM_FOCUSABLE and the childId CHILDID_SELF. That means it can be accessed and usually toggled. Its not Readonly.

Emanuel
  • 8,027
  • 2
  • 37
  • 56
  • 1
    IAccessible is legacy. Why don't you use UI Automation? https://learn.microsoft.com/en-us/windows/win32/winauto/microsoft-active-accessibility-and-ui-automation-compared and then use UIA patterns instead of using raw handles – Simon Mourier Apr 06 '20 at 10:08
  • There are several ways to do that. But its not a question of "how can i get this working". Its question of "why does it not work the way i do that". Its nothing important, but interesting to know why it blocks the default action and postmessage/sendmessage calls to the hwnd. Maybe ROLE_SYSTEM_PUSHBUTTON must be treated different. ROLE_PUSHBUTTON works flawlessly. – Emanuel Apr 06 '20 at 10:24
  • Edit: Just checked it with another ROLE_SYSTEM_PUSHBUTTON (not ROLE_PUSHBUTTON, my fault). Same State, but defaultaction works.. Mabye it's a security breach to modify windows settings using MSAA. – Emanuel Apr 06 '20 at 10:32
  • 1
    Maybe it doesn't work because it's not supposed to. Using window handles or mouse position is not the good way to automate an app. MSAA is legacy for reasons. I can perfectly write a win32 app you will never manage to automate like this but be able to automate using UIA. Windows 10 settings (if this what you're talking about) work fine with UI Automation AFAIK. You can use the inspect tool before any coding to see what is possible and what is not. – Simon Mourier Apr 06 '20 at 11:24
  • Yes. That is exactly what i wrote. Mouse Clicks and PostMessage/SendMessage is not what i want to do. I just figured out what you ment. It may be accessable using IAccessibleEx, but there is absolutly no tutorial in the web how to query the service to get an IAccessibleEx from an IAccessible. Could you provide a sample? – Emanuel Apr 06 '20 at 11:35
  • You don't need IAccessibleEx either with UI Automation. When using C#, there are .NET classes ready to use for that, for example: https://stackoverflow.com/a/30877933/403671 or https://stackoverflow.com/a/29963741/403671 – Simon Mourier Apr 06 '20 at 13:02

0 Answers0