c++ - sp6 - Soporte de automatización para Visual Basic 6 ListView
visual basic download (2)
Necesito obtener el valor / texto de control a través de la interfaz de automatización (codificación con C ++ / C #). Intenté con UI Automation API y este es un resultado capturado por Inspect :
La automatización de la interfaz de usuario reconoce estos controles como un pane
y no puedo obtener el elemento de texto de vista de lista ni obtener / establecer el valor del control deslizante de forma normal.
Probado con otra herramienta como MSAA , Automation Spy da el mismo resultado.
Después de investigar, encontré que el control con nombre de clase como ListView20WndClass
, Slider20WndClass
, ... pertenece al control de Visual Basic 6.
Entonces, ¿hay alguna API que pueda soportar este tipo de control también?
Observación 1 : Hay una herramienta llamada Ranorex que puede admitir estos controles (por desgracia, es una licencia comercial de € 3490), y no sé qué API subyacente se utilizó:
Observación 2 Hay otro tipo de control utilizado en la aplicación bajo prueba que la Automatización de UI aún puede obtener valor:
- ThunderRT6FormDC : reconocer como ventana
- ThunderRT6CommandButton : reconocer como botón
- ThunderRT6CheckBox : reconocer como casilla de verificación
- etc ...
- lamentablemente, incorporan ListView20WndClass y Slider20WndClass pero ambos reconocen como panel
Actualización 1 Creo un programa simple para obtener texto pero aún no funciona (compilar como conjunto de caracteres Unicode):
#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;
}
Cuando cuente 5..4..3..2..1 simplemente pase el mouse sobre algún elemento de la pantalla para verificar.
Pero cuando paso el mouse sobre la vista de lista:
- Vista de lista VB6 (ListView20WndClass): devuelve una cadena vacía (se espera que
101
sea mi ejemplo) - Vista de lista MFC / Winform (SysListView32): la aplicación debajo del mouse dejó de funcionar (la aplicación de consola aún se está ejecutando)
El objeto ListView.ListItem no tiene hwnd.
Debería buscar ListView por nombre de clase , luego usar SendMessage () para enviar el mensaje LVM_GETITEM y usar la estructura LVITEM para obtener información sobre los elementos:
Mensaje LVM_GETITEM (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/bb774953(v=vs.85).aspx
Estructura LVITEM (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/bb774760(v=vs.85).aspx
esta página de referencia puede ayudarlo a:
Lista-Control de referencia de control (Windows) https://msdn.microsoft.com/en-us/library/windows/desktop/ff485973(v=vs.85).aspx
EDITAR Sin embargo, su problema no está relacionado con la programación del lenguaje VB6. Por lo tanto, creo que este es el foro equivocado, debe solicitar en el foro relacionado con su idioma para utilizar.
Puede usar pywinauto, que puede automatizar las aplicaciones de VB6 utilizando Win32 API bajo el capó (todos los detalles están ocultos, incluido el mensaje LVM_GETITEM
, etc.). La mayoría de los controles se pueden reconocer como botones, casillas de verificación e incluso listas de visitas. Vea los nombres de clases compatibles para las vistas de lista. Tus casos están aquí.
Y la API de Win32 debería funcionar más rápido que con la automatización de UI si se usan esperas flexibles . Aunque UI Automation también es compatible bajo el capó, en su caso.
La Guía de inicio te ayudará a hacer los primeros pasos y aprender el concepto de alto nivel. También siéntase libre de hacer preguntas con la etiqueta pywinauto
. Soy el mantenedor de la biblioteca.