Вызов меню свойств индикатора. - страница 2

 
Zhunko писал (а) >>

Большое СПАСИБО за пример использования фукций из "user32.dll"!!!

Имел ввиду, как получить коды команд API МТ4?


Всю информацию о запущенных процессах, созданных окнах, потоках можно получить с помощью утилиты Spy++,  которая входит в состав дистрибутива Visual Studio.

Основное достоинство этой программы - возможность логирования Windows сообщений. С помощью этой функции утилиты как раз и определяются параметры таких

WinAPI функций как PostMessageA() и SendMessageA().

В ветке research по теме кодов к PostMessageA  я выкладывал архив с этой утилитой. Научиться с ней работать несложно, но при этом надо иметь представление об окнах,

процессах и о том, как взаимодействуют окна между собой. Ну и знание WinAPI никто не отменял.

P.S. С учетом того, что серьезные изменения в МетаТрейдере не планируются, то набор оконных операций наверняка не изменится. Однако нужно иметь в ввиду, что

всегда существуют такой вариант, что приведенные мной выше коды перестанут работать в новых версиях МетаТрейдера.

 
Zhunko писал (а) >>

Со скриптом разобрался.

Интересно, что подокно в списке индикаторов тоже является элементом списка.

Ilnur, я понял, что способа работать с именем индикатора в этом списке нет?

Однозначно нет или, что-нибудь можно придумать?

Здесь хороший пример (на С++) того, как ищется позиция по имени в списке TreeView элемента. Имя узла возвращается через указатель в структуре TV_ITEM.

В MQL4 нет возможности обратиться по указателю.

Есть конечно же немного корявый способ определения позиции интересуемого индикатора. Необходимо сначала сохранить шаблон текущего графика инструмента.

Затем проанализировать файл шаблона на наличие тегов <window> ... </window>, <indicator> ... </indicator>. Однако такой способ требует больших 
затрат по программированию.

 
Ilnur, БОЛЬШОЕ СПСИБО!!!
 

Ilnur, сделайте доброе дело, допишите, пожалуйста, в скрипт нажатие кнопок ОК и Закрыть.

Получится законченный инструмент для переинициализации индикаторов, и, наконец, прервется череда тем об их обновлении и принудительной компиляции.
 
granit77 писал (а) >>

Ilnur, сделайте доброе дело, допишите, пожалуйста, в скрипт нажатие кнопок ОК и Закрыть.

Получится законченный инструмент для переинициализации индикаторов, и, наконец, прервется череда тем об их обновлении и принудительной компиляции.
 
#include <WinUser32.mqh>
 
#import "user32.dll"
    int GetAncestor(int hWnd, int gaFlags);
    int GetLastActivePopup(int hWnd);
    int GetDlgItem(int hDlg, int nIDDlgItem);
#import
 
#define VK_HOME 0x24
#define VK_DOWN 0x28
 
#define GA_ROOT 2
 
#define TVM_GETCOUNT 0x1105
 
// Вызывает окно "Список индикаторов" и возвращает его дескриптор 
int GetListDialog(int hOwnedWnd)
{
    int hDlgWnd;
 
    PostMessageA(hOwnedWnd,WM_COMMAND,35419,0); //вызываем окно "Список индикаторов"
    Sleep(100);
    hDlgWnd = GetLastActivePopup(hOwnedWnd); //определяем дескриптор
 
    return(hDlgWnd);
}

// Вызывает окно свойств выбранного индикатора и возвращает его дескриптор
int GetPropertyDialog(int hOwnedWnd, int hListDlg)
{
    int hDlgWnd;
 
    PostMessageA(hListDlg,WM_COMMAND,0x48B,GetDlgItem(hListDlg,0x48B)); //вызываем окно свойств
    Sleep(100);
    hDlgWnd = GetLastActivePopup(hOwnedWnd); //определяем дескриптор
 
    return(hDlgWnd);
}
 
//+------------------------------------------------------------------+
//| Основная функция скрипта                                              |
//+------------------------------------------------------------------+
int start()
{
    int hParent, hListDlg, hTree, hDlg;
    int nTreeCount;
 
    hParent = GetAncestor(WindowHandle(Symbol(),Period()),GA_ROOT); //получаем дескриптор основного окна терминала
 
    if(hParent!=0)
    {
        hListDlg = GetListDialog(hParent); //вызываем окно "Список индикаторов"
        hTree = GetDlgItem(hListDlg,0x48C); //находим список индикаторов
 
        nTreeCount = SendMessageA(hTree,TVM_GETCOUNT,0,0); //определяем длину списка
 
        PostMessageA(hTree,WM_KEYDOWN,VK_HOME,0); //верхняя строка списка
        for(int i=1; i<nTreeCount; i++) //перебираем весь список
        {
            PostMessageA(hTree,WM_KEYDOWN,VK_DOWN,0); //смещаемся на следующую позицию списка
            if(IsWindowEnabled(GetDlgItem(hListDlg,0x48B))==0) continue;
 
            hDlg = GetPropertyDialog(hParent,hListDlg); //вызываем окно свойств индикатора
            PostMessageA(hDlg,WM_COMMAND,0x001,GetDlgItem(hDlg,0x001)); //нажимаем кнопку "ОК"
        }
        PostMessageA(hListDlg,WM_COMMAND,0x001,GetDlgItem(hListDlg,0x001)); //закрываем окно "Список индикаторов"
    }
    return(0);
}
 
Zhunko писал (а) >>

Со скриптом разобрался.

Интересно, что подокно в списке индикаторов тоже является элементом списка.

Ilnur, я понял, что способа работать с именем индикатора в этом списке нет?

Однозначно нет или, что-нибудь можно придумать?

При демонстрации примера представленного выше пришла идея реализации скрипта, вызывающего свойства конкретного индикатора.

Для этого скрипт необходимо дополнить функцией считывания заголовка окна свойств. Если строка заголовка содержит имя интересуемого

индикатора, то прерываем цикл. Правда есть одно неудобство: при поиске на экране будут мелькать вызываемые окна.


 
Ilnur писал (а) >>

При демонстрации примера представленного выше пришла идея реализации скрипта, вызывающего свойства конкретного индикатора.

Для этого скрипт необходимо дополнить функцией считывания заголовка окна свойств. Если строка заголовка содержит имя интересуемого

индикатора, то прерываем цикл. Правда есть одно неудобство: при поиске на экране будут мелькать вызываемые окна.


Здорово! Может попробуете сделать?

 
// Вызов окна свойств конкретного индикатора.
 
#property show_inputs
 
#include <WinUser32.mqh>
 
extern string sIndicatorName = "iButterworth"; //имя индикатора
 
#import "user32.dll"
    int GetAncestor(int hWnd, int gaFlags);
    int GetLastActivePopup(int hWnd);
    int GetDlgItem(int hDlg, int nIDDlgItem);
#import
 
#define VK_HOME 0x24
#define VK_DOWN 0x28
 
#define GA_ROOT 2
 
#define TVM_GETCOUNT 0x1105
 
// Вызывает окно "Список индикаторов" и возвращает его дескриптор 
int GetListDialog(int hOwnedWnd)
{
    int hDlgWnd;
 
    PostMessageA(hOwnedWnd,WM_COMMAND,35419,0); //вызываем окно "Список индикаторов"
    Sleep(100);
    hDlgWnd = GetLastActivePopup(hOwnedWnd); //определяем дескриптор
 
    return(hDlgWnd);
}

// Вызывает окно свойств выбранного индикатора и возвращает его дескриптор
int GetPropertyDialog(int hOwnedWnd, int hListDlg)
{
    int hDlgWnd;
 
    PostMessageA(hListDlg,WM_COMMAND,0x48B,GetDlgItem(hListDlg,0x48B)); //вызываем окно свойств
    Sleep(100);
    hDlgWnd = GetLastActivePopup(hOwnedWnd); //определяем дескриптор
 
    return(hDlgWnd);
}
 
//+------------------------------------------------------------------+
//| Основная функция скрипта                                              |
//+------------------------------------------------------------------+
int start()
{
    int hParent, hListDlg, hTree, hDlg;
    int nTreeCount;
    string lpString = "";
 
    hParent = GetAncestor(WindowHandle(Symbol(),Period()),GA_ROOT); //получаем дескриптор основного окна терминала
 
    if(hParent!=0)
    {
        hListDlg = GetListDialog(hParent); //вызываем окно "Список индикаторов"
        hTree = GetDlgItem(hListDlg,0x48C); //находим список индикаторов
 
        nTreeCount = SendMessageA(hTree,TVM_GETCOUNT,0,0); //определяем длину списка
 
        PostMessageA(hTree,WM_KEYDOWN,VK_HOME,0); //верхняя строка списка
        for(int i=1; i<nTreeCount; i++) //перебираем весь список
        {
            PostMessageA(hTree,WM_KEYDOWN,VK_DOWN,0); //смещаемся на следующую позицию списка
            if(IsWindowEnabled(GetDlgItem(hListDlg,0x48B))==0) continue;
 
            hDlg = GetPropertyDialog(hParent,hListDlg); //вызываем окно свойств индикатора
            GetWindowTextA(hDlg,lpString,GetWindowTextLengthA(hDlg)+1); //считываем заголовок окна
 
            if(StringFind(lpString,sIndicatorName,0)>=0)
                break; //если нашли нужный индикатор, прерываем цикл
 
            PostMessageA(hDlg,WM_COMMAND,0x001,GetDlgItem(hDlg,0x001)); //нажимаем кнопку "ОК"
        }
        PostMessageA(hListDlg,WM_COMMAND,0x001,GetDlgItem(hListDlg,0x001)); //закрываем окно "Список индикаторов"
    }
    return(0);
}
 
Огромное спасибо! Все работает. Неплохо бы и в CodeBase поместить.
 

Офигеть!!!

Ilnur, Вы съэкономили уйму времени!

Спасибо!!!