Скачать MetaTrader 5

Автоматизация с перехватом нажатия кнопок и мыши. - страница 11

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Alexey Navoykov
4919
Alexey Navoykov  
DKeN:
cm=GetDlgItem(hdlg,ID_SYMBOL);
int pos=SendMessageA(cm,CB_GETCOUNT,0,0);//получим количество в списке
//найдем пару
string fs="";
for(int l=0;l<pos;l++){
int ll=SendMessageA(cm,CB_GETLBTEXT,l,fs);
Print(ll," ",fs);
}

подскажите как правильно получить список инструментов в окне Ордер (F9)?

я получаю количество элементов, но получить именно строки по номеру не удается, возвращает -1.

#define ID_SYMBOL 0x053E //имя символа для выбора

cm хандл ComboBox

Прежде чем получать какой-либо текст, нужно сначала подготовить буфер достаточного размера для приёма этого текста. А у тебя строка fs имеет вообще нулевую длину. Странно что терминал у тебя не падает из-за такого безобразия. Поэтому fs нужно заранее проинициализировать достаточно длинной строкой. Если рассматривать общий случай, когда длина получаемой строки может быть вообще какой угодно большой, то надо сначала узнать эту длину с помощью сообщения CB_GETLBTEXTLEN, чтобы знать какой размер буфера требуется.
Alexey Navoykov
4919
Alexey Navoykov  
lasso:

Алексей, спасибо, ф-ция работает, но..


Как раз ID потока нужен, т.к. у меня задействованы два терминала.

Я выкрутился через идентификацию заголовка, но хотелость бы всё таки знать, как ID потока определить из-под тестера?

ID текущего потока можно получить с помощью функции GetCurrentProcessId()
Vitaliy
1136
Vitaliy  
Meat:
Прежде чем получать какой-либо текст, нужно сначала подготовить буфер достаточного размера для приёма этого текста. .......

КСТАТИ!!!

Когда адаптировал под свои нужды Вашу ф-цию

int FindWindow(string class, string caption, bool captionexactly=false)

столкнулся с тем, что строковый буфер string textbuf объявленый локально на уровне функции, инициализируется всего лишь один раз при первом вызове,

и в дальнейшем ведет себя как статическая переменная.

string textbuf="Абвгдежзийклмнопрсту";   // В_ЭТОЙ_СТРОКЕ_255_СИМВОЛОВ
Print("textbuf после инициализации =",textbuf);
Не могли бы прокомментировать данную ситуацию?
Alexey Navoykov
4919
Alexey Navoykov  
lasso:

КСТАТИ!!!

Когда адаптировал под свои нужды Вашу ф-цию

столкнулся с тем, что строковый буфер string textbuf объявленый локально на уровне функции, инициализируется всего лишь один раз при первом вызове,

и в дальнейшем ведет себя как статическая переменная.

Не могли бы прокомментировать данную ситуацию?

Понял о чём речь. Вы имели ввиду что в буфере хранится старое значение, полученное из GetText. Помню раньше тоже меня это удивляло. Но это особенности MQL. Где-то на форуме разработчики говорили, что все константные строки, заданные на уровне компилятора, хранятся в памяти постоянно в отдельном месте, и при выходе из функции не теряются (не затираются). Их адрес изначально известен и не меняется в процессе работы программы. Поэтому при повторном вызове функции, когда идёт обращение к этой же константной строке, то она берётся с того же самого адреса. Но там у нас уже другой текст, который был помещён функцией GetText.
Аналогично можно сделать просто Print("Абвгдежзийклмнопрсту") и там тоже получишь другой текст :) Т.е. дело не в переменной textbuf, а дело в константной строке. На этапе компиляции проверяются все константные строки и помещаются как бы в базу данных, причём только уникальные строки. Если обнаруживаются одинаковые строки, то для них создаётся только один общий экземпляр в базе данных. Соответсвенно если ты запортишь этот экземпляр в процессе работы, то все вызовы такой строки из любого места программы также вернут испорченный результат.

Если тебя это не устраивает, то можно создать буфер программно:

string textbuf="";
for (int i=0; i<255; i++)
  textbuf=textbuf+" ";

Тогда подобной проблемы не будет. Правда я уже не помню, можно ли так делать. Не возникнет ли ошибки доступа к памяти... Попробуй.

Vitaliy
1136
Vitaliy  
Meat:
Тогда подобной проблемы не будет. Правда я уже не помню, можно ли так делать. Не возникнет ли ошибки доступа к памяти... Попробуй.

Я как только прочитал, про то "что 255 символов не вмещается в экран и вид форума портится" - сразу так и сделал.

Но такой вариант не сработал, АПИшная ф-ция ничего не вернула... Поэтому оставил ваш вариант.

......

Все равно, большое спасибо, за очередной обстоятельный ответ.

Alexey Navoykov
4919
Alexey Navoykov  
lasso:

Я как только прочитал, про то "что 255 символов не вмещается в экран и вид форума портится" - сразу так и сделал.

Но такой вариант не сработал, АПИшная ф-ция ничего не вернула... Поэтому оставил ваш вариант.

......

Все равно, большое спасибо, за очередной обстоятельный ответ.


Всегда пожалуйста.

Насколько я понимаю, причина в том, что в данном случае в функцию передаётся ссылка не на оригинальный текстовый буфер принадлежащий переменной, а на его копию, т.е. временный буфер, который создаётся перед вызовом функции. Соответственно даже если функция и меняет текст в этом буфере, то это ничего не даёт, поскольку оригинальный то буфер остаётся неизменным. А ссылка на временный буфер теряется при выходе из функции. Я в своё время мучился из-за этого с передачей строки в DLL. Но решение есть. Нужно передавать в функцию элемент строкового массива. При этом никакой промежуточный буфер не создаётся, и функция получает ссылку на оригинальный буфер.

string buffer[1]={""};
for (int i=0; i<500; i++)
  buffer[0]=buffer[0]+" ";

GetWindowTextA(h,buffer[0],500);

Так должно работать.

Alexandr Gavrilin
38817
Alexandr Gavrilin  
void SetSymbol(int hdlg,string symbol,int len){
   int cm=GetDlgItem(hdlg,ID_SYMBOL);
   int pos=SendMessageA(cm,CB_GETCOUNT,0,0);//получим количество в списке
   string fs,ff;
   
   for(int l=0;l<pos;l++){
       //SendMessageA(cm,CB_SETCURSEL,l,0);
       int len_text=SendMessageA(cm,CB_GETLBTEXTLEN,l,0);
       fs=" ";
       for(int m=0;m<len_text+1;m++) fs=StringConcatenate(fs," ");
       int ll=SendMessageA(cm,CB_GETLBTEXT,l,fs);
       Print(len_text," = ",fs); //пусто!!! длину получает.

          
       ff=StringSubstr(fs,0,len);
      // Print(symbol);
       if(ff==symbol) {
            SendMessageA(cm,CB_SETCURSEL,l,0);
            break;
       }
   }
}

длину получаю нормально, однако текст получить никак :-(

объясните как правильно инициализировать строку, и вообще возможно ли это реализовать без внешней dll ?

это надо чтобы найти символ в списке инструментов и его выбрать.


Alexey Navoykov
4919
Alexey Navoykov  
DKeN:

длину получаю нормально, однако текст получить никак :-(

объясните как правильно инициализировать строку, и вообще возможно ли это реализовать без внешней dll ?

это надо чтобы найти символ в списке инструментов и его выбрать.

Насчёт инициализации строки я как-раз объяснял в предыдущем сообщении товарищу lasso. Нужно либо использовать элемент строкового массива, либо просто инициализировать строковую переменную константой достаточной длины. В вашем случае проще использовать константу, поскольку заранее известно, что размер получаемой строки не превысит 78 байт:

12 байт (тикер инструмента) + 2 байта (запятая и пробел) + 64 байт (полное название инструмента) . Это максимально возможная длина строки. Ну можно округлить до 80.

Но если вам нужно просто ВЫБРАТЬ определённый инструмент в списке, то вам незачем получать его название. Нужно просто использовать сообщение CB_SELESTRING. Там в качестве строкового параметра достаточно отправить лишь начальную часть названия ("EURUSD,") и он сам найдёт и выделит подходящий элемент из списка.

Igor Kuzmin
205
Igor Kuzmin  

API советник Million Dollar Robot близкого будущего: Сам рисует в терминале кучу прибыльных сделок... :) и когда через месяц-другой новоиспеченный миллионер пытается снять прибыль у брокера, то узнает что не было ни одной сделки... однако срок возврата денег за советник кончился... :))))))))

Mikaiel Israielian
168
Mikaiel Israielian  

Ребята, помогите, пожалуйста, определить хэндл кнопок Бай/Селл в окошке Ордер. Хэндл от окошка Ордер я нашел:

int chart_handle = WindowHandle(Symbol(), Period());
int MT_handle = GetAncestor(chart_handle, GA_ROOT); // GA_ROOT 2
PostMessageA(MT_handle, WM_KEYDOWN, VK_F9, 0); // открываем окошко Ордер
Sleep(1000); // Wait. This is important!
int Order_handle = GetLastActivePopup(MT_handle); // хэндл от Ордер-а

Дальше пытаюсь определить хэндл кнопки (например, Бай), но в ответ получаю 0.

int Buy_handle = GetDlgItem(Order_handle, 0x40C); // 0x40C найдено с помощью WinSpy++

Самое интересное, что не получается найти хэндл ни от одного элемента в боксе "Немедленное исполнение". И от самого Немедленного исполнения тоже не удается найти. Хотя WinSpy++ видит его как отдельный элемент и показывает для него ID 0xFFFF.

Прошу строго не судить, я начинающий.

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий