Listing the main menu items through UIAutomation using Delphi

I am trying to get a list of menu subtypes from a standard Windows application using the UIAutomationCore library imported as TLB in Delphi - i.e.

File -> New | Exit
Help -> About

I can get the application menu, and then the top-level items to the list (ie, in the example above, “File” and “Help”), but I can’t get a list of ANY controls under these menu items. My code is as follows: FElement represents the actual menu item that I am checking.

The length of the collection returned by FindAll is always 0. I tried to extend the menu item to this code, but it doesn't seem to be affected.

 UIAuto.CreateTrueCondition(condition);

 FItems := TObjectList<TAutomationMenuItem>.create;

 self.Expand;
 sleep(3000);

 // Find the elements
 self.FElement.FindAll(TreeScope_Descendants, condition, collection);

 collection.Get_Length(length);

 for count := 0 to length -1 do
 begin
   collection.GetElement(count, itemElement);
   itemElement.Get_CurrentControlType(retVal);

   if (retVal = UIA_MenuItemControlTypeId) then
   begin
     item := TAutomationMenuItem.Create(itemElement);
     FItems.Add(item);
   end;
 end;

I see examples of this in C #, and they really are nothing different from the code above (as far as I can see)

Thanks in advance

: question

Update2. Delphi. , (), .

Update3: Inspect ( ), ...

= Ancestors = () Form1 ()

(), ( ).

+4
1

, :

  • ,
  • , .

:

// Careful: the code might not be 100% threadsafe, but should work for the purpose of demonstration
const
  UIA_MenuItemControlTypeId =   50011;
  UIA_ControlTypePropertyId =   30003;
  UIA_NamePropertyId    =   30005;
  UIA_ExpandCollapsePatternId   =   10005;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(procedure begin CoInitializeEx(nil, 2); FindItems(true); CoUninitialize; end).Start;
end;

procedure TForm1.FindItems(Recurse: Boolean);
var
  UIAuto: TCUIAutomation;
  condition: IUIAutomationCondition;
  collection: IUIAutomationElementArray;
  Length: Integer;
  Count: Integer;
  itemElement: IUIAutomationElement;
  retVal: Integer;
  val: WideString;

  ExpandCollapsePattern: IUIAutomationExpandCollapsePattern;
  FElement: IUIAutomationElement;
begin
  UIAuto := TCUIAutomation.Create(nil);   

  UIAuto.CreateTrueCondition(condition);

  // Find the elements
  UIAuto.ElementFromHandle(Pointer(Handle), FElement);

  FElement.FindAll(TreeScope_Descendants, condition, collection);

  collection.Get_Length(length);

  for Count := 0 to length - 1 do
  begin
    collection.GetElement(Count, itemElement);
    itemElement.Get_CurrentControlType(retVal);

    if (retVal = UIA_MenuItemControlTypeId) then
    begin
      ItemElement.Get_CurrentName(val);
      TThread.Synchronize(nil,
        procedure
        begin
          memo1.lines.Add(val);
        end);

      itemElement.GetCurrentPattern(UIA_ExpandCollapsePatternId, IInterface(ExpandCollapsePattern));
      if Assigned(ExpandCollapsePattern) then
      begin
        ExpandCollapsePattern.Expand;
        if Recurse = True then
          FindItems(False);
      end;
    end;
  end;
  UIAuto.Free;
end;
+2

All Articles