AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
DAX
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 17.05.2022, 13:23   #1  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
? Dax 2012 получить путь к Treenode (Toolbar, tabax)
Привет всем.

А кто-нибудь делал такую штуку:
Есть окно AOT с одним открытым элементом, например полученным через "Открыть новое окно".
В ax4 его заголовок был например таким
"\Data dictionary\Tables\SalesTable"

а в 2012-й все скупо:
"AOT - \Data dictionary\Tables"

соответственно в 4-ке всякие самописные оконные менеджеры (DEV_ToolBar, Tabax, Sidax) корректно распознавали вид окна и в ярлычке окна было видно название объекта AOT (в данном примере стояло имя таблички SalesTable).

А в 12-ке (и кажется в 2009-й то же самое) это не работает.

Не очень удобно пользоваться. Ярлычки окон есть, имени объекта в тексте ярлыка нет.

Кто-нибудь смог в окне AOT добраться до корневого узла и выцепить его имя ?

Например, есть hwnd окошка AOT. Можно по нему как-то вытащить текст первого узла в дереве элементов ?

Последний раз редактировалось Logger; 17.05.2022 в 13:47.
Старый 17.05.2022, 14:01   #2  
DSPIC is offline
DSPIC
Боец
 
1,077 / 1234 (44) ++++++++
Регистрация: 11.04.2008
А так не работает?

TreeNode treeNode = new LastAotSelection().first();
Старый 17.05.2022, 16:49   #3  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Работает.
Но проблема не в этом.

Работает тулбар. Перебирает окошки в аксапте, чтоб обновить список ярлыков в панели. Открыто 5 окон AOT. В каждом своя табличка открыта.
Раньше в ax4 в заголовке каждого окна был полный путь до таблички, в общем, было x++ имя таблички в названии окна.
(например
"\Data dictionary\Tables\SalesTable"
"\Data dictionary\Tables\SalesTable_RU"
"\Data dictionary\Tables\SalesTable_W"
"\Data dictionary\Tables\PurchTable"
...
)

И оно было доступно тулбару. Удобно. Видишь ярлыки в панели и видно какой ярлык к какому объекту X++ ведет.

А теперь в заголовке все 5 разных окон имеют один и тот же текст:
"AOT - \Data dictionary\Tables"

Соответственно ярлычки в тулбаре все выглядят одинаково. Не различить их.
Вот задача понять по окошку AOT - какой там объект спрятан. Хотя бы его название как строку вытащить.
Старый 17.05.2022, 17:04   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
В случае 2012-й аксапты проблемные места обвел красной рамочкой.
Наверно так будет понятно в чем проблема.

В случае ax2012 все заголовки окон AOT одинаковые. Поэтому и в тулбаре ярлыки для них одинаковые.

Как бы вытащить текст из корня дерева с объектом AOT чтобы сделать в тулбаре нормальные ярлыки с информативным текстом как в ax4

Иногда при рефакторинге приходится много объектов смотреть и сверять. Начинается путаница.

Нажмите на изображение для увеличения
Название: ax4_Toolbar.png
Просмотров: 29
Размер:	67.8 Кб
ID:	13381
Нажмите на изображение для увеличения
Название: ax2012_Toolbar.png
Просмотров: 28
Размер:	79.2 Кб
ID:	13382

Последний раз редактировалось Logger; 17.05.2022 в 17:08.
Старый 17.05.2022, 17:22   #5  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Посмотрел структуру в Spy++
Особой разницы не видно.
Просто разные Caption у окон в случае ax4 и ax2012

Название: Spy_ax4.png
Просмотров: 518

Размер: 12.7 Кб
Название: Spy_ax2012.png
Просмотров: 524

Размер: 16.6 Кб
Старый 18.05.2022, 00:59   #6  
Товарищ ♂uatr is offline
Товарищ ♂uatr
Участник
Аватар для Товарищ ♂uatr
MCBMSS
 
265 / 808 (27) +++++++
Регистрация: 23.10.2012
Привет.
Есть там наименование, только смотреть его у ребёнка нужно:

Ну и не новость, через простые WinAPI::findWindowEx и WinApi::getWindowText оно не выводится.

Видно, что это структура, она реализует интерфейс IAccessible.
Получение объекта реализующего данный интерфейс можно осуществить через функцию AccessibleObjectFromWindow библиотеки oleacc.
Ну а там уже вызвать get_accName
На шарпе проверил - работает.

GUID интерфейса 618736E0-3C3D-11CF-810C-00AA00389B71

Последний раз редактировалось Товарищ ♂uatr; 18.05.2022 в 01:24.
За это сообщение автора поблагодарили: Logger (93).
Старый 25.10.2022, 13:23   #7  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,158 / 1286 (47) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Добрый день.
Получилось решить проблему?
Тоже надоело в ToolBar видеть малоинформативные заголовки вкладок.
Старый 25.10.2022, 17:06   #8  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
У меня так и не дошли руки сделать. Как будет время - сделаю. Намного удобнее работать с заголовками.
Думаю что все должно получиться.
Если из консольного приложения получилось, то почему в аксапте не получится ?
Кстати в 2009-й та же проблема. С нее все и началось.

Последний раз редактировалось Logger; 25.10.2022 в 17:08.
Старый 27.11.2022, 20:05   #9  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Попробовал я набросать проект и не получилось.

Взял пример от Товарищ ♂uatr
запихнул его в C# проект (консольное приложение) - все работает (правда запускать надо debug версию, ну не суть)

Запускаем проект, он спрашивает hwnd окна
Даем ему hwnd в десятичном виде (в моем примере 67552) в ответ текст
Цитата:
Waiting for HWND input (in decimal format):
67552
HWND hex:107E0; Name:SalesTable; HWND:67552
HWND hex:107E0; Description:\Data Dictionary\Tables\SalesTable: 7; HWND:67552
т.е. он для окна может прочитать имя объекта АОТ и полный путь к нему в свойствах Name и Description. Только к полному пути еще добавляет через двоеточие число дочерних узлов. Но это нестрашно.

Оговорюсь что нужно скармливать не hwnd окна АОТ (с ClassName AxMDIChildWindow) а hwnd дочернего к нему окна (с ClassName AxPaneWnd)

Текст проекта
X++:
// [url=http://axforum.info/forums/showthread.php?p=434649#post434649]Dax 2012 получить путь к Treenode (Toolbar, tabax)[/url]
// Товарищ ♂uatr
using System;
using System.Runtime.InteropServices;
using System.Security;
using Accessibility;

namespace AotInspectWindows
{

    class Program
    {
        [DllImport("oleacc.dll")]
        private static extern int AccessibleObjectFromWindow(IntPtr hwnd, uint id, ref Guid iid,
        [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);

        static void Main(string[] args)
        {
            object accessibleObj = null;
            string name;
            string description;
            Guid guid = new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");
            Console.WriteLine("Waiting for HWND input (in decimal format):"); 
            string ptr = Console.ReadLine(); // вводить в десятичном формате
            IntPtr handle = new IntPtr(Convert.ToInt32(ptr));
            // int result = AccessibleObjectFromWindow(handle, (uint)OBJID.OBJID_WINDOW, ref guid, ref accessibleObj); // для такого вызова будет пустым get_accDescription() но непустым get_accName()
            int result = AccessibleObjectFromWindow(handle, (uint)OBJID.OBJID_CLIENT, ref guid, ref accessibleObj); // а для такого все ок - и get_accDescription() и get_accName() - непустые

            name = ((IAccessible)accessibleObj).get_accName(0);
            Console.WriteLine($"HWND hex:{handle.ToString("X")}; Name:{name}; HWND:{handle}");

            description = ((IAccessible)accessibleObj).get_accDescription(0);
            Console.WriteLine($"HWND hex:{handle.ToString("X")}; Description:{description}; HWND:{handle}");

            Console.ReadKey();
        }
        public enum OBJID : uint
        {
            OBJID_WINDOW = 0x00000000,
            OBJID_SYSMENU = 0xFFFFFFFF,
            OBJID_TITLEBAR = 0xFFFFFFFE,
            OBJID_MENU = 0xFFFFFFFD,
            OBJID_CLIENT = 0xFFFFFFFC,
            OBJID_VSCROLL = 0xFFFFFFFB,
            OBJID_HSCROLL = 0xFFFFFFFA,
            OBJID_SIZEGRIP = 0xFFFFFFF9,
            OBJID_CARET = 0xFFFFFFF8,
            OBJID_CURSOR = 0xFFFFFFF7,
            OBJID_ALERT = 0xFFFFFFF6,
            OBJID_SOUND = 0xFFFFFFF5,
        }
    }
}
Вложения
Тип файла: rar AotInspectWindows.rar (320.8 Кб, 37 просмотров)

Последний раз редактировалось Logger; 27.11.2022 в 20:07.
Старый 27.11.2022, 20:13   #10  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
т.е. в целом все работает.
А из аксапты у меня не получилось.
Вот джоб
X++:
static void AotInspectWindows(Args _args)
{
    HWND            hwnd = 67552;
    // HWND            hwnd = 0;
    DLL             dllOleacc;
    DLLFunction     dllFuncAccessibleObjectFromWindow;
    Binary          guidBinary;
    // guid            guidXpp;
    Binary          ptrIAccessibleBinary;
    int             hResult;
    COM             comIAccessible;
    COMDispFunction comFunc;
    COMVariant      varChild;
    COMVariant      pszString;
    
    #define.OBJID_WINDOW    (0x00000000)
    #define.OBJID_SYSMENU   (0xFFFFFFFF)
    #define.OBJID_TITLEBAR  (0xFFFFFFFE)
    #define.OBJID_MENU      (0xFFFFFFFD)
    #define.OBJID_CLIENT    (0xFFFFFFFC)
    #define.OBJID_VSCROLL   (0xFFFFFFFB)
    #define.OBJID_HSCROLL   (0xFFFFFFFA)
    #define.OBJID_SIZEGRIP  (0xFFFFFFF9)
    #define.OBJID_CARET     (0xFFFFFFF8)
    #define.OBJID_CURSOR    (0xFFFFFFF7)
    #define.OBJID_ALERT     (0xFFFFFFF6)
    #define.OBJID_SOUND     (0xFFFFFFF5)
    
    Binary guid2Binary(str _guidStr)
    {
        guid    guidVar;
        System.Guid guidNet;
        System.Byte[]  buffer;
        System.IO.MemoryStream  stream;
        Binary  ret;
        ;
        
        guidVar = str2guid(_guidStr);
        stream = new System.IO.MemoryStream();
        // stream.Write(guidVar);
        guidNet = guidVar;
        buffer = guidNet.ToByteArray();
        // infoCon(["length", CLRInterop::getAnyTypeForObject(buffer.get_Length())]);
        
        stream.Write(buffer, 0, 16);
        // info(ClrMethod_MRC::toString(stream));
        // info(ClrMethod_MRC::toString(stream.get_Length()));
        
        ret = Binary::constructFromMemoryStream(stream);
        /*
        // info(ret.xml());
        info(int2Hex(ret.byte(0), 2));
        info(int2Hex(ret.byte(1), 2));
        info(int2Hex(ret.byte(2), 2));
        info(int2Hex(ret.byte(3), 2));
        info(int2Hex(ret.byte(4), 2));
        info(int2Hex(ret.byte(5), 2));
        info(int2Hex(ret.byte(6), 2));
        info(int2Hex(ret.byte(7), 2));
        info(int2Hex(ret.byte(8), 2));
        info(int2Hex(ret.byte(9), 2));
        info(int2Hex(ret.byte(10), 2));
        info(int2Hex(ret.byte(11), 2));
        info(int2Hex(ret.byte(12), 2));
        info(int2Hex(ret.byte(13), 2));
        info(int2Hex(ret.byte(14), 2));
        info(int2Hex(ret.byte(15), 2));
        info('');
        */
        stream.Close();
        
        return ret;
    }
    ;
    
    dllOleacc = new DLL('oleacc.dll');
    dllFuncAccessibleObjectFromWindow = new DLLFunction(dllOleacc, 'AccessibleObjectFromWindow');
    // [url]https://learn.microsoft.com/en-us/windows/win32/api/oleacc/nf-oleacc-accessibleobjectfromwindow[/url]
    // HRESULT AccessibleObjectFromWindow(
    // [in]  HWND   hwnd,
    // [in]  DWORD  dwId,
    // [in]  REFIID riid,
    // [out] void   **ppvObject
    // );
    
    dllFuncAccessibleObjectFromWindow.arg(
        ExtTypes::DWord,   // [in]  HWND   hwnd,
        ExtTypes::DWord,   // [in]  DWORD  dwId,
        ExtTypes::Pointer, // [in]  REFIID riid, // TO DO
        ExtTypes::Pointer  // [out] void   **ppvObject  // TO DO
        );
    
    guidBinary = guid2Binary('{618736E0-3C3D-11CF-810C-00AA00389B71}'); // IAccessible Interface // [url]https://learn.microsoft.com/en-us/dotnet/api/accessibility.iaccessible?view=windowsdesktop-7.0[/url]
    // guidXpp    = str2guid('{618736E0-3C3D-11CF-810C-00AA00389B71}');
    /*
    ptrIAccessibleBinary = new Binary(8);
    ptrIAccessibleBinary.qWord(0, 0);
    */
    ptrIAccessibleBinary = new Binary(4);
    ptrIAccessibleBinary.dWord(0, 0);
    infoCon(["ptrIAccessibleBinary = ", ptrIAccessibleBinary.dWord(0)]);
    
    dllFuncAccessibleObjectFromWindow.returns(ExtTypes::DWord); // HRESULT 
    hResult = dllFuncAccessibleObjectFromWindow.call(
        hwnd, 
        #OBJID_WINDOW, 
        guidBinary, 
        // guidXpp,
        ptrIAccessibleBinary
        );
    infoCon(["hResult = ", hResult]);
    if (hResult)
    {
        infoCon(["LastError = ", WinAPI::getLastError()]);
    }
    // infoCon(["ptrIAccessibleBinary = ", ptrIAccessibleBinary.qWord(0)]);
    infoCon(["ptrIAccessibleBinary = ", ptrIAccessibleBinary.dWord(0)]);
    
    comIAccessible = COM::createFromInterface(ptrIAccessibleBinary.dWord(0));
    // comFunc = new COMDispFunction(comIAccessible, "get_accName", COMDispContext::PropertyGet);
    
    varChild  = COMVariant::createFromInt(0, COMVariantInOut::In); // CHILDID_SELF
    info(any2str_MRC(varChild.variantType()));
    // pszString = COMVariant::createFromStr('', COMVariantInOut::Out_retVal);
    
    pszString  = new COMVariant( 
        COMVariantInOut::Out_retVal,  
        COMVariantType::VT_BSTR); 
    
    // comFunc = new COMDispFunction(comIAccessible, "accName", COMDispContext::PropertyGet);
    // hResult = comFunc.call(varChild, pszString); Метод "accName" в COM-объекте класса "IAccessible" возвратил код ошибки 0x8002000E (DISP_E_BADPARAMCOUNT), который означает: Число аргументов, указанных в вызове функции, отличается от числа аргументов в объявлении метода.
    
    // comFunc = new COMDispFunction(comIAccessible, "get_accName", COMDispContext::Method); // Метод "get_accName" не поддерживается интерфейсом Automation COM-объекта класса "IAccessible".
    // hResult = comFunc.call(varChild, pszString);
    
    comFunc = new COMDispFunction(comIAccessible, "accName", COMDispContext::Method);
    hResult = comFunc.call(varChild, pszString); // Метод "accName" в COM-объекте класса "IAccessible" возвратил код ошибки 0x80020003 (DISP_E_MEMBERNOTFOUND), который означает: Запрошенный метод не существует или во время вызова была осуществлена попытка присвоить некоторое значение свойству, доступному только для чтения.
    
    // comIAccessible.accName(varChild, pszString); // пустая строка
    // comIAccessible.get_accName(varChild, pszString); // ошибка
    
    info(pszString.toString());
    info(pszString.bStr());
}
Вызываю AccessibleObjectFromWindow
получаю интерфейс IAccessible
дальше непонятно как из аксапты вызвать на нем метод.
Попробовал через Com - он даже его видит, но что-то с числом параметров ругается.

Натравил на oleacc.dll мастер оберток com объектов в аксапте. А он видит интерфейс IAccessible но обертку делает пустую - т.е. не видит ничего в нем, нет свойств и методов. И это странно.

Последний раз редактировалось Logger; 27.11.2022 в 20:28.
Старый 28.11.2022, 02:48   #11  
Товарищ ♂uatr is offline
Товарищ ♂uatr
Участник
Аватар для Товарищ ♂uatr
MCBMSS
 
265 / 808 (27) +++++++
Регистрация: 23.10.2012
Привет.
X++:
CLRObject IAccessibleObject = System.Runtime.InteropServices.Marshal::GetObjectForIUnknown(new System.IntPtr(ptrIAccessibleBinary.dWord(0)));
System.String accName = IAccessibleObject.get_accName();

Последний раз редактировалось Товарищ ♂uatr; 28.11.2022 в 03:08.
За это сообщение автора поблагодарили: Logger (10).
Старый 28.11.2022, 12:13   #12  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Товарищ ♂uatr Посмотреть сообщение
Привет.
X++:
CLRObject IAccessibleObject = System.Runtime.InteropServices.Marshal::GetObjectForIUnknown(new System.IntPtr(ptrIAccessibleBinary.dWord(0)));
System.String accName = IAccessibleObject.get_accName();
Работает, спасибо.

Но почему то не всегда.

Подправил джоб
Основная проблема вот в чем :
1. При первых запусках метод iAccessibleObject.get_accName();
почему-то возвращает null
А потом когда и так и сяк покрутил, вдруг раз, - его "пробило" и стал не null возвращать. Как-то это стремно. То работает то нет. словно изначально не все подгрузилось и проинициализировалось.

2. Если при вызове dllFuncAccessibleObjectFromWindow.call()
передавать не #OBJID_WINDOW, а #OBJID_CLIENT то возвращаются null и для iAccessibleObject.get_accName() и для iAccessibleObject.get_accDescription(). В то время как в консольном приложении на C# возвращаются непустые значения. Для get_accName - имя AOT объекта а для get_accDescription полный путь в AOT. И именно этот вариант и хотелось задействовать.


X++:
static void AotInspectWindows(Args _args)
{
    HWND            hwnd = 67552;
    // HWND            hwnd = 0;
    DLL             dllOleacc;
    DLLFunction     dllFuncAccessibleObjectFromWindow;
    Binary          guidBinary;
    // guid            guidXpp;
    Binary          ptrIAccessibleBinary;
    int             hResult;
    COM             comIAccessible;
    COMDispFunction comFunc;
    COMVariant      varChild;
    COMVariant      pszString;
    CLRObject       iAccessibleObject;
    System.String   accName;
    System.String   accDescription;
    int64           obj_clientUint = 0xFFFFFFFC;
    
    #define.OBJID_WINDOW    (0x00000000)
    #define.OBJID_SYSMENU   (0xFFFFFFFF)
    #define.OBJID_TITLEBAR  (0xFFFFFFFE)
    #define.OBJID_MENU      (0xFFFFFFFD)
    #define.OBJID_CLIENT    (0xFFFFFFFC)
    #define.OBJID_VSCROLL   (0xFFFFFFFB)
    #define.OBJID_HSCROLL   (0xFFFFFFFA)
    #define.OBJID_SIZEGRIP  (0xFFFFFFF9)
    #define.OBJID_CARET     (0xFFFFFFF8)
    #define.OBJID_CURSOR    (0xFFFFFFF7)
    #define.OBJID_ALERT     (0xFFFFFFF6)
    #define.OBJID_SOUND     (0xFFFFFFF5)
    
    Exception infoCon(container _con, str _delimiter = " ", URL helpUrl = '', SysInfoAction _sysInfoAction = null)
    {
        SysInfoLogStr   txt = con2Str(_con, _delimiter);
        ;

        return infolog.add(Exception::Info, getPrefix()+txt, helpUrl, _sysInfoAction, false);
    }
    
    Binary guid2Binary(str _guidStr)
    {
        guid    guidVar;
        System.Guid guidNet;
        System.Byte[]  buffer;
        System.IO.MemoryStream  stream;
        Binary  ret;
        ;
        
        guidVar = str2guid(_guidStr);
        stream = new System.IO.MemoryStream();
        // stream.Write(guidVar);
        guidNet = guidVar;
        buffer = guidNet.ToByteArray();
        // infoCon(["length", CLRInterop::getAnyTypeForObject(buffer.get_Length())]);
        
        stream.Write(buffer, 0, 16);
        // info(ClrMethod_MRC::toString(stream));
        // info(ClrMethod_MRC::toString(stream.get_Length()));
        
        ret = Binary::constructFromMemoryStream(stream);
        /*
        // info(ret.xml());
        info(int2Hex(ret.byte(0), 2));
        info(int2Hex(ret.byte(1), 2));
        info(int2Hex(ret.byte(2), 2));
        info(int2Hex(ret.byte(3), 2));
        info(int2Hex(ret.byte(4), 2));
        info(int2Hex(ret.byte(5), 2));
        info(int2Hex(ret.byte(6), 2));
        info(int2Hex(ret.byte(7), 2));
        info(int2Hex(ret.byte(8), 2));
        info(int2Hex(ret.byte(9), 2));
        info(int2Hex(ret.byte(10), 2));
        info(int2Hex(ret.byte(11), 2));
        info(int2Hex(ret.byte(12), 2));
        info(int2Hex(ret.byte(13), 2));
        info(int2Hex(ret.byte(14), 2));
        info(int2Hex(ret.byte(15), 2));
        info('');
        */
        stream.Close();
        
        return ret;
    }
    ;
    
    dllOleacc = new DLL('oleacc.dll');
    dllFuncAccessibleObjectFromWindow = new DLLFunction(dllOleacc, 'AccessibleObjectFromWindow');
    // [url]https://learn.microsoft.com/en-us/windows/win32/api/oleacc/nf-oleacc-accessibleobjectfromwindow[/url]
    // HRESULT AccessibleObjectFromWindow(
    // [in]  HWND   hwnd,
    // [in]  DWORD  dwId,
    // [in]  REFIID riid,
    // [out] void   **ppvObject
    // );
    
    dllFuncAccessibleObjectFromWindow.arg(
        ExtTypes::DWord,   // [in]  HWND   hwnd,
        ExtTypes::DWord,   // [in]  DWORD  dwId,
        ExtTypes::Pointer, // [in]  REFIID riid, // TO DO
        ExtTypes::Pointer  // [out] void   **ppvObject  // TO DO
        );
    
    guidBinary = guid2Binary('{618736E0-3C3D-11CF-810C-00AA00389B71}'); // IAccessible Interface // [url]https://learn.microsoft.com/en-us/dotnet/api/accessibility.iaccessible?view=windowsdesktop-7.0[/url]
    // guidXpp    = str2guid('{618736E0-3C3D-11CF-810C-00AA00389B71}');
    /*
    ptrIAccessibleBinary = new Binary(8);
    ptrIAccessibleBinary.qWord(0, 0);
    */
    ptrIAccessibleBinary = new Binary(4);
    ptrIAccessibleBinary.dWord(0, 0);
    infoCon(["ptrIAccessibleBinary = ", ptrIAccessibleBinary.dWord(0)]);
    
    dllFuncAccessibleObjectFromWindow.returns(ExtTypes::DWord); // HRESULT 
    hResult = dllFuncAccessibleObjectFromWindow.call(
        hwnd, 
        #OBJID_WINDOW, 
        // #OBJID_CLIENT, 
        // obj_clientUint,
        guidBinary, 
        // guidXpp,
        ptrIAccessibleBinary
        );
    infoCon(["hResult = ", hResult]);
    if (hResult)
    {
        infoCon(["LastError = ", WinAPI::getLastError()]);
    }
    // infoCon(["ptrIAccessibleBinary = ", ptrIAccessibleBinary.qWord(0)]);
    infoCon(["ptrIAccessibleBinary = ", ptrIAccessibleBinary.dWord(0)]);
    
    iAccessibleObject = System.Runtime.InteropServices.Marshal::GetObjectForIUnknown(new System.IntPtr(ptrIAccessibleBinary.dWord(0)));
    accName         = iAccessibleObject.get_accName();
    // accDescription  = iAccessibleObject.get_accDescription();
    // accName         = iAccessibleObject.accName();
    // accDescription  = iAccessibleObject.accDescription();
    // System.Runtime.InteropServices.Marshal::GetComInterfaceForObject(
    /*
    try
    {
        info(ClrMethod_MRC::toString(iAccessibleObject));
    }
    catch
    {
        info(AifUtil::getClrErrorMessage());
        return;
    }
    */
    if (CLRInterop::isNull(accName))
    {
        infoCon(["accName = ", "null"]);
    }
    else
    {
        infoCon(["accName = ", CLRInterop::getAnyTypeForObject(accName)]);
    }
    
    if (CLRInterop::isNull(accDescription))
    {
        infoCon(["accDescription = ", "null"]);
    }
    else

    infoCon(["accDescription = ", CLRInterop::getAnyTypeForObject(accDescription)]);
    
return;
    /*
    comIAccessible = COM::createFromInterface(ptrIAccessibleBinary.dWord(0));
    // comIAccessible = new COM();
    // comIAccessible.attach(ptrIAccessibleBinary.dWord(0));
    
    // comFunc = new COMDispFunction(comIAccessible, "get_accName", COMDispContext::PropertyGet);
    
    varChild  = COMVariant::createFromInt(0, COMVariantInOut::In); // CHILDID_SELF
    info(any2str_MRC(varChild.variantType()));
    // pszString = COMVariant::createFromStr('', COMVariantInOut::Out_retVal);
    
    pszString  = new COMVariant( 
        COMVariantInOut::Out_retVal,  
        COMVariantType::VT_BSTR); 
    
    // comFunc = new COMDispFunction(comIAccessible, "accName", COMDispContext::PropertyGet);
    // hResult = comFunc.call(varChild, pszString); Метод "accName" в COM-объекте класса "IAccessible" возвратил код ошибки 0x8002000E (DISP_E_BADPARAMCOUNT), который означает: Число аргументов, указанных в вызове функции, отличается от числа аргументов в объявлении метода.
    
    // comFunc = new COMDispFunction(comIAccessible, "get_accName", COMDispContext::Method); // Метод "get_accName" не поддерживается интерфейсом Automation COM-объекта класса "IAccessible".
    // hResult = comFunc.call(varChild, pszString);
    
    comFunc = new COMDispFunction(comIAccessible, "accName", COMDispContext::Method);
    hResult = comFunc.call(varChild, pszString); // Метод "accName" в COM-объекте класса "IAccessible" возвратил код ошибки 0x80020003 (DISP_E_MEMBERNOTFOUND), который означает: Запрошенный метод не существует или во время вызова была осуществлена попытка присвоить некоторое значение свойству, доступному только для чтения.
    
    // comIAccessible.accName(varChild, pszString); // пустая строка
    // comIAccessible.get_accName(varChild, pszString); // ошибка
    
    info(pszString.toString());
    info(pszString.bStr());
    */
}
Старый 28.11.2022, 15:42   #13  
Товарищ ♂uatr is offline
Товарищ ♂uatr
Участник
Аватар для Товарищ ♂uatr
MCBMSS
 
265 / 808 (27) +++++++
Регистрация: 23.10.2012
Попробуй так значения получать:
X++:
accName         = iAccessibleObject.get_accName(0);
accDescription  = iAccessibleObject.get_accDescription(0);
За это сообщение автора поблагодарили: Logger (30).
Старый 28.11.2022, 15:47   #14  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
да, так работает.
Круто.

Как же я про индекс то не заметил )
Старый 22.01.2023, 14:32   #15  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Оформил в нормальном виде.

Сделан класс AxWindowInfo
В нем метод getWindowText
нужно использовать этот метод вместо WinApi::getWindowText
(для получения заголовка окна)
в
Tabax
Sidax
Dev_Toolbar
итп утилитах.

Тогда заголовки в тулбаре ведут себя также как в ax3-ax4, имеют информативный вид.
Проверено в 2012 и 2009 версиях.
Вложения
Тип файла: zip AxWindowInfo.zip (38.0 Кб, 44 просмотров)

Последний раз редактировалось Logger; 22.01.2023 в 14:40.
За это сообщение автора поблагодарили: Raven Melancholic (10), S.Kuskov (10), sukhanchik (20), Товарищ ♂uatr (4), gl00mie (10), DarkSpirit22 (3).
Теги
aot, sidax, tabax, toolbar

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
DAX 2012 и шаблоны проектирования db DAX: Программирование 31 24.07.2014 12:40
DAX: Enabling Power View on Multidimensional Models for Microsoft Dynamics AX 2012 R2 Blog bot DAX Blogs 0 27.06.2013 06:16
DAX: How to gain additional value from the Microsoft application platform with Microsoft Dynamics AX 2012 R2 Blog bot DAX Blogs 3 21.06.2013 15:16
dax-lessons: Display Barcode in SSRS report [Dynamics AX 2012, X++] Blog bot DAX Blogs 0 15.05.2012 18:11
dax-lessons: Get list of printers in Dynamics AX 2012 for SSRS reports [Using X++] Blog bot DAX Blogs 0 14.05.2012 23:13
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 16:47.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.