CreateWindow

 

Привет всем. Я в своей либе создаю окно:

bResCheck = CreateMyWindow(0);

Данный код я вызываю либо в эксперте (init) либо в скрипте (start). Когда вызываю в эксперте то окно успешно создаётся но сразу же пропадает.  если создаю в скрипте  то для того чтобы оно не пропадало юзаю
бесконечный цикл, но он всё тормозин и не рендеоит моё окно.  В итоге вопрос как сделать окно через мою либу что бы оно нормально работало ?
 Вешать создание окна на другой поток не пробовал пока.
 
У меня тоже не создаётся почему то. В длл индикатора можно создать окно говорят (общий оконный поток терминала) а в эксперте и скрипте отдельный порождается поток и видимо поэтому окно создать нельзя. Попробуй создать свой поток и в нём окно своё. Возможно это сработает. Не пробовал но тоже интересно, получится ли. Можно созадать окно в своем exe файле и обмениваться нужной информацией с DLL вызываемой из советника или скрипта. Я пробовал - этот подход работает.
 
elritmo:
У меня тоже не создаётся почему то. В длл индикатора можно создать окно говорят (общий оконный поток терминала) а в эксперте и скрипте отдельный порождается поток и видимо поэтому окно создать нельзя. Попробуй создать свой поток и в нём окно своё. Возможно это сработает. Не пробовал но тоже интересно, получится ли. Можно созадать окно в своем exe файле и обмениваться нужной информацией с DLL вызываемой из советника или скрипта. Я пробовал - этот подход работает.

 


в отдельном потоке тож ничего хорошего не вышло. В итоге взял создал отдельно процесс а из скрипта нужные данные пихаю в файл.  а уже из файла забираю в своё окно. вот. хотя можно как и ты говорил юзать SendMessage из DLL. Или как то можно ещё ? А насчёт индикатора я попробую.
 
Да использую SendMessage(hWnd, WM_COPYDATA, ...) Работает очень надёжно. Данные не теряются, причём идёт обмен данными в обе стороны от длл к моему процессу и обратно.
 
elritmo:
Да использую SendMessage(hWnd, WM_COPYDATA, ...) Работает очень надёжно. Данные не теряются, причём идёт обмен данными в обе стороны от длл к моему процессу и обратно.


Очень интересно. В окно процесса можно отправить, а как назад в dll получить?
 
RickD:
elritmo:
Да использую SendMessage(hWnd, WM_COPYDATA, ...) Работает очень надёжно. Данные не теряются, причём идёт обмен данными в обе стороны от длл к моему процессу и обратно.


Очень интересно. В окно процесса можно отправить, а как назад в dll получить?
Боюсь если расскажу то MQ снова испугаются и вообще DLL запретят :) Ну да ладно поделюсь знаниями
Delphi Dll
 
где нибудь в инициализации
 
Ищем хендлер главного окна из хендлера чарта кторый передаём в DLL из советника скрипта. Хендлер в советнике скрипте получаем через WindowHandler
 
while MTChartWin <> 0 do begin
  MTMainWin := MTChartWin;
  MTChartWin := GetParent(MTChartWin);
end;
 
Затем подставляем вместо терминальной оконной процедуры свою которая дополняет её нашими обработками сообщений.
SetWindowLong(MTMainWin, GWL_USERDATA, SetWindowLong(MTMainWin, GWL_WNDPROC, LongInt(@NewWndProc)));
 
А это пример моей оконной процедуры
function NewWndProc(Wnd: THandle; Msg: Cardinal; wParam, lParam: Integer): Cardinal;
begin
  case Msg of
    WM_COPYDATA: begin // сообщение с данными от нашего приложения
      Inc(PosCnt);
      if Length(Positions) < PosCnt then SetLength(Positions, PosCnt + 1000);
      Positions[PosCnt - 1] := PPosition(PCopyDataStruct(lParam).lpData)^;
      Result := 0;
      Exit;
    end;
    WM_USER + 1: begin // Простое сообщение событие от нашего приложения, чтобы не использовать более сложное WM_COPYDATA
      ZeroMemory(@LastBarCnt, SizeOf(LastBarCnt));
      Result := 0;
      Exit;
    end;
  end;
  Result := CallWindowProc(Pointer(GetWindowLong(Wnd, GWL_USERDATA)),
                           Wnd, Msg, wParam, lParam);
end;
 
 
Так я отсылаю данные в мой процесс exe  Нахожу его по классу окна FeatherWinCaption который передаю в советнике как параметр
И вместе с сообщенеим отсылаю хендлер главного окна терминала. в этом случаем мы можем свободно перегружать терминал не закрывая наше приложение.
Оно получит новый хендлер с новым сообщением.
 
  MTCommWnd := FindWindow(nil, FeatherWinCaption);
  if MTCommWnd = 0 then Exit;
  with CopyDS do begin dwData := TICK_IND; cbData := SizeOf(TTick); lpData := @Tick; end;
  SendMessage(MTCommWnd, WM_COPYDATA, MTMainWin, Integer(@CopyDS));
 
 
Ну а при деинициализации советника надо вызвать функцию в DLL которая вызовет эту функцию чтобы подставить терминалу
её собсвенную оконную процедуру обработки сообщений. В этом случае у нас ничего падать не будет
 
SetWindowLong(MTMainWin, GWL_WNDPROC, GetWindowLong(MTMainWin, GWL_USERDATA));
 
Этого достаточно чтобы обмениваться данными вполне успешно в обе стороны на одном тике.
 

Данные копируются в локальный буфер. А используются в эксперте или скрипте. Верно?

Что будет - если эксперт или скрипт будет использовать данные в тот момент, когда NewWndProc их изменяет?

 
Такого не случается, потому что ты используешь SendMessage для отсылки сообщений и поток скрипта или эксперта замирает пока не обработается посланное сообщение и оконная процедура не вернёт значение. Асинхронно работает PostMessage. Поэтому ты посылаешь сообщение своему приложенияю и поток замерает и ждёт пока это сообщение не обработается. Оконная процедура твоего приложения принимает твоё сообщение, обрабаотывает и в свою очередь может послать сообщение через SendMessage оконной процедуре MetaTrader-а которую ты перегрузил и которая висит в общем оконном потоке МТ а не в потоке советника. На это сообщение ты в DLL советника забираешь и сохраняешь данные в массивах в DLL и выходишь из оконной процедуры. Далее размораживается поток при вызове второго SendMessage в оконной процедуре твоего приложения и происходит выход из этой процедуры, что в свою очеред размораживает поток советника в том месте где ты вызвал SendMessage в DLL советника. Далее ты можешь записать в массив доступный советнику данные полученные от твоего приложения при обмене сообщениями в коде после вызова всех твоих SendMessgae. В итоге не может быть доступа к данным одновременно разными потоками.
Надеюсь ты понял. Если нет то мне уже надо писать статью. :) Возможно меня раскритикуют с доводами, но метод работает и падений не было или порчи данных пока что.
Причина обращения: