Jump to content

Select Items from a TVirtualStringTree Control in delphi application


Press
 Share

Recommended Posts

Hi I am new to AutoIT and I have a scenario in delphi application to interact with a list of items in a list named "Available" and select a particular one and move it to another list named "Current".  On initial look it seemed to be a ListView control but on using the Window info it seems to both controls are VirtualStringTree .

Tried the below code to find and select a particular item from the Treeview but I couldn't. The script doesn't throw any error when ran but doesn't perform any action 

$hWindow = WinGetHandle($TitleBBTSMain, "")

    $hWnd = ControlGetHandle($hWindow, "", "[CLASS:TVirtualStringTree; INSTANCE:2]")
    $iItemCnt = _GUICtrlTreeView_GetCount($hWnd)
    ConsoleWrite("$iItemCnt  " & $iItemCnt  & @CRLF)

    $searchText = "bs bp 1 -no restrictions"
    $hItemFound = _GUICtrlTreeView_FindItem($hWnd, $searchText, True)
    ConsoleWrite("$hItemFound " & $hItemFound & @CRLF)

    While $hItemFound
        _GUICtrlTreeView_SelectItem($hWnd, $hItemFound)
        _GUICtrlTreeView_ClickItem($hWnd, $hItemFound)
        $next = _GUICtrlTreeView_GetNextVisible($hWnd, $hItemFound)
        $hItemFound = _GUICtrlTreeView_FindItem($hWnd, $searchText, True, $next)
        Sleep(5000)
    WEnd

 

o/p : 

$iItemCnt   0

$hItemFound 0

Note that there is no default selection of the item inside the treelist and the itemcount was also returned as zero. Both SelectItem and ClickItem doesn't work either.

The instances for both "Available" and "Current" list doesn't change during runtime and remains constant. Both application and AutoIT are 32bit.

Is there any way to select a particular item from the list and move them to the next   

 

TVirtualStringTree.thumb.PNG.8096a3d40f72f854ac26c44d444ec853.PNG

 

 

Edited by Press
Link to comment
Share on other sites

Hi @FrancescoDiMuro

Thanks for the reply, yes the control handle returns value like this

$hWindow = WinGetHandle($TitleBBTSMain, "")

    $hWnd = ControlGetHandle($hWindow, "", "[CLASS:TVirtualStringTree; INSTANCE:2]")
    ConsoleWrite("$hWnd " & $hWnd & @CRLF)

    $iItemCnt = _GUICtrlTreeView_GetCount($hWnd)
    ConsoleWrite("$iItemCnt  " & $iItemCnt  & @CRLF)

    $searchText = "bs bp 1 -no restrictions"
    $hItemFound = _GUICtrlTreeView_FindItem($hWnd, $searchText, True)
    ConsoleWrite("$hItemFound " & $hItemFound & @CRLF)

    While $hItemFound
        _GUICtrlTreeView_SelectItem($hWnd, $hItemFound)
        _GUICtrlTreeView_ClickItem($hWnd, $hItemFound)
        $next = _GUICtrlTreeView_GetNextVisible($hWnd, $hItemFound)
        $hItemFound = _GUICtrlTreeView_FindItem($hWnd, $searchText, True, $next)
        Sleep($SleepBig)
    WEnd

o/p : 

$hWnd 0x00610450

$iItemCnt   0

$hItemFound 0

Edited by Press
Link to comment
Share on other sites

Try selecting the first item in the list and then put the spy on the control to see if it shows the selected item in the text field.

I've worked with some different non-standard lists and have to do some control send hackery to select the first item, controlgettext to see if it's the one I want, controlsend arrow down, check text, repeat until I get to the one I want, or if the text hasn't changed "bottom of list".

Link to comment
Share on other sites

Hi @Nine

Tried as you suggested with the below code considering it as ListView , but no luck. The script doesn't throw any error but didn't do any action

 

$hWindow = WinGetHandle($TitleBBTSMain, "")

    $hListView = ControlGetHandle($hWindow, "", "[CLASS:TVirtualStringTree; INSTANCE:2]")
    ConsoleWrite("$hListView " & $hListView & @CRLF)

    $iItemCnt = _GUICtrlListView_GetItemCount($hListView)
    ConsoleWrite("$iItemCnt  " & $iItemCnt  & @CRLF)

    For $i = 0 To $iItemCnt Step +1
        $test= _GUICtrlListView_GetItem($hListView,$i)

        if ($test[3] = $parameterBoardPlan) Then
            _GUICtrlListView_ClickItem($hListView,$i)

        EndIf
    Next

o/p:

$hListView 0x00120268
$iItemCnt  0

Link to comment
Share on other sites

Hi @BigDaddyO,

 Tried as you suggested, by selecting the an item in the list by using arrow keys and highlighting it. Then used the spy to see whether the text field shows the value. But it doesn't and hence the ControlGetText returns null value

Send("{DOWN}")
    ConsoleWrite("Select board Plan" & @CRLF)
    Sleep($SleepBig)
    $hWindow = WinGetHandle($TitleBBTSMain, "")

    $hWnd = ControlGetHandle($hWindow, "", "[CLASS:TVirtualStringTree; INSTANCE:2]")
    ConsoleWrite("$hWnd " & $hWnd & @CRLF)

     $Text = ControlGetText($hWindow, "", "$hWnd")
     ConsoleWrite("$Text  " & $Text  & @CRLF)

o/p

$hListView 0x00120268
$Text  

Text.thumb.PNG.12fa77bb8d3f2298bbe31e55bf3aa7d6.PNG

Link to comment
Share on other sites

Link to comment
Share on other sites

With Delphi, they usually are not usable from AutoIt. I have never seen one work with it. From the info from UISpy I can tell it's available to be used from UIAutomation. I wouldn't waste time with straight up AutoIt on it myself. That's not a standard windows control.

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

Try the tools as mentioned in wiki faq 31 which you already partly are trying with uiaspy

Commercial tools like ranorex and testcomplete are doing this to get some kind of reflection dll injected to get information of these controls.Commercial tools like ranorex and testcomplete are doing this to get some kind of reflection dll injected to get information of these controls.

Handy people can probably fix this with sendmessage and some info from https://github.com/Fr0sT-Brutal/Delphi_MiniRTL/blob/master/CommCtrl.pas

I think for dellphi controls you can only reach them with code injecting a dll and thats probably tough from AutoIt. Libraries like easyhook, mhook, .... 

I never understood why those delphi Txxxcontrols do not behave normally with sendmessge api

Some references for try just to get item count with sendmessage and from there onwards get the messages to retrieve text. (In general then I advice to start using the commercial tooling as thats the reason these tools exist)

{$EXTERNALSYM LVM_FIRST}
LVM_FIRST = $1000; { ListView messages }
const
  {$EXTERNALSYM LVM_GETITEMCOUNT}
  LVM_GETITEMCOUNT        = LVM_FIRST + 4;
IntPtr count = API.SendMessage(child1, API.LVM_GETITEMCOUNT, 0, 0);
PageCount := sendmessage( listview1.handle, LVM_GETCOUNTPERPAGE, 0, 0);

 

Microsoft base: https://social.msdn.microsoft.com/Forums/vstudio/en-US/4a335b85-7a85-4bf9-9079-8f9f1dc45dd0/select-listviewitem-in-a-listview-by-api?forum=windowsuidevelopment  

 

 

Some thoughts references added if maybe someone understands better and maybe we should get some small delphi executable with just a form, textbox, checkbox to experiment with.

0. message explanation delphi

https://doc.lagout.org/programmation/Delphi/Delphi/Delphi - Messages (chapter).pdf

1. Delphi seems just as any other windows app based on the message loop so reachable with sendmessage/postmessage

https://delphidabbler.github.io/delphi-tips/tips/105.html

2. From delphi to other apps just sendmessage

https://stackoverflow.com/questions/6115296/delphi-how-to-send-command-to-other-application

3. Interesting if you prevent apps from processing messages

https://stackoverflow.com/questions/1251678/how-to-prevent-processmessages-in-delphi

 

 

Edited by junkew
enhanced delphi information
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...