phibao37
phibao37

Reputation: 2350

Automation support for Visual Basic 6 ListView

I need to get value/text of control via automation interface (coding with C++/C#). I tried with UI Automation API and this is some result captured by the Inspect: Inspect Listview

Inspect slider UI Automation recognize these control as pane and I can't get list view text item or get/set slider value as normal.
Tried with other tool like MSAA, Automation Spy give the same result.

After researching, I found that control with class name like ListView20WndClass, Slider20WndClass, ... belong to Visual Basic 6 control.
So, Is there any API can support these type of control as well?

Remark 1: There is a tool named Ranorex can support these control (sadly, it is €3490 commercial license), and I don't know which underlying API was used:
enter image description here

enter image description here


Remark 2 There are some other control type used in the application under test that UI Automation still can get value:


Update 1 I create a simple program to get text but still not working (compile as Unicode Character Set):

#include <iostream>
using namespace std;

#include <UIAutomation.h>
#include <atlstr.h>
#include <Commctrl.h>

CString getListViewItemText(HWND hwnd, int nItem, int nSubItem) {
    LVITEM item;
    memset(&item, 0, sizeof(LVITEM));
    item.iSubItem = nSubItem;
    CString string;
    int Length = 64; //initial reasonable string length
    int ReturnCode;

    do {
        Length *= 2; //resize the string buffer
        item.cchTextMax = Length;
        item.pszText = string.GetBufferSetLength(Length);

        ReturnCode = (int)::SendMessage(hwnd, LVM_GETITEMTEXT,
            (WPARAM)nItem, (LPARAM)&item);
        printf("len = %d \n", ReturnCode);

    } while (ReturnCode == Length - 1); //if could not get all chars, try again

    string.ReleaseBuffer();
    return string;
}

void UI_Spy() {

    // Init COM
    CoInitialize(NULL);

    // Init UIAutomation instance
    IUIAutomation *pAuto;
    CoCreateInstance(CLSID_CUIAutomation, NULL,
        CLSCTX_INPROC_SERVER, IID_IUIAutomation, reinterpret_cast<void**>(&pAuto));

    if (pAuto) {

        IUIAutomationElement *pElm;
        POINT p;

        for (int i = 0; i < 10; i++) {
            for (int j = 5; j > 0; j--) {
                Sleep(1000);
                printf("%d ", j);
            }
            GetCursorPos(&p);
            if (pAuto->ElementFromPoint(p, &pElm) == S_OK) {
                wprintf(L"\nPOSITION x = %d, y = %d\n", p.x, p.y);

                BSTR str;
                pElm->get_CurrentName(&str);
                wprintf(L"-Name = %s\n", str);
                SysFreeString(str);

                pElm->get_CurrentLocalizedControlType(&str);
                wprintf(L"-Type = %s\n", str);
                SysFreeString(str);

                CONTROLTYPEID typeId;
                pElm->get_CurrentControlType(&typeId);

                switch (typeId) {

                    // Process checkbox
                case UIA_CheckBoxControlTypeId:
                    IUIAutomationTogglePattern  *toggle;
                    pElm->GetCurrentPattern(UIA_TogglePatternId, (IUnknown**)&toggle);
                    ToggleState state;
                    toggle->get_CurrentToggleState(&state);
                    printf("-Checkbox = %s\n", state == ToggleState::ToggleState_On ? "TRUE"
                        : (state == ToggleState::ToggleState_Off ? "FALSE" : "INTER"));
                    break;

                    // Process VB6 listview
                case UIA_PaneControlTypeId:
                    pElm->get_CurrentClassName(&str);
                    if (str != nullptr && wcscmp(str, L"ListView20WndClass") == 0) {
                        HWND hwnd;
                        pElm->get_CurrentNativeWindowHandle((UIA_HWND*)&hwnd);
                        printf("-VB6 Listview: %p\n", hwnd);

                        CString txt = getListViewItemText(hwnd, 0, 0);
                        //txt = "Test";
                        printf("-[0,0] = %S\n", (const wchar_t*)txt);
                    }
                    SysFreeString(str);
                    break;

                    // Process normal listview
                case UIA_ListControlTypeId:
                    HWND hwnd;
                    pElm->get_CurrentNativeWindowHandle((UIA_HWND*)&hwnd);
                    printf("-Normal Listview: %p\n", hwnd);

                    CString txt = getListViewItemText(hwnd, 0, 0);
                    //txt = "Test";
                    printf("-[0,0] = %S\n", (const wchar_t*)txt);
                    break;
                }

                wprintf(L"\n");
                pElm->Release();
            }
            printf("\n");
        }

        // Release UIAutomation instance
        pAuto->Release();
    }

    // Release COM
    CoUninitialize();
}

int main()
{
    UI_Spy();

    cin.get();
    return 0;
}


When it count 5..4..3..2..1 just mouse over some element on the screen to check.
But when I mouse over the list view:

Upvotes: 4

Views: 1391

Answers (2)

Giorgio Brausi
Giorgio Brausi

Reputation: 414

ListView.ListItem object has not hwnd.

You should search ListView by class name, next use SendMessage() to send the message LVM_GETITEM and using the LVITEM structure to get info about items:

LVM_GETITEM message (Windows)

https://msdn.microsoft.com/en-us/library/windows/desktop/bb774953(v=vs.85).aspx

LVITEM structure (Windows)

https://msdn.microsoft.com/en-us/library/windows/desktop/bb774760(v=vs.85).aspx

this reference page may help you:

List-View Control Reference (Windows) https://msdn.microsoft.com/en-us/library/windows/desktop/ff485973(v=vs.85).aspx

EDIT However, your problem is not related to VB6 language programming. So, I think that this is the wrong forum, you should ask on forum related to Your language to use for.

Upvotes: 1

Vasily Ryabov
Vasily Ryabov

Reputation: 9991

You can use pywinauto which can automate VB6 apps using Win32 API under the hood (all details are hidden including LVM_GETITEM message etc.). Most of the controls can be recognized as buttons, check boxes and even list views! See supported class names for list views. Your cases are here.

And Win32 API should work faster than with UI Automation if using flexible waits. Though UI Automation is also supported under the hood if any.

The Getting Started Guide will help you to do first steps and to learn the high level concept. Also feel free to ask questions with tag pywinauto. I'm the library maintainer.

Upvotes: 1

Related Questions