Delphi DLL в Visual C++

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Borys
Сообщения: 18
Зарегистрирован: 09 июл 2004, 17:25
Откуда: Киев

У меня такая проблема.
Есть длл на Делфи. Необходимо динамически подключить ее к проге на вижуале. Проблема в том, что я не могу передать правильно параметры. До длл на Делфи они доходят неправильно (я писал длл на С++ там все нормально). По видимому прблема в cflling conventions.
Пытался использовать stdcall и WINAPI результатов не дало.
Вот часть на делфи:
function ShowForm(c: LPCSTR; h: HWND; d: LPCSTR):HWND;
begin
Form1:=TForm1.Create(Application);
Form1.Edit1.Text:=c;
Form1.Edit2.Text:=inttostr(h);
form1.Edit3.Text:=d;
Form1.Show;
ShowForm:=Form1.WindowHandle;
ShowMessage(c+', '+d);
end;

Вот вызов на вижуале:
typedef HWND (* PTShowForm)(LPCSTR, HWND, LPCSTR);
PTShowForm TShow;
hDLL=LoadLibrary(dllname);
if (hDLL!=0)
{
TShow = (PTShowForm)GetProcAddress(hDLL,"ShowForm");
dllhwnd=TShow((LPCSTR)str1, GetSafeHwnd(), (LPCSTR)str2);
}

Вообще я пытаюсь вставить диалог на Делфи (длл) в прогу на вижуале. Получается довольно скверно. Постоянно приходиться обходить всякие пакости. Может кто-то подобное делал и может подсказать решение.
Аватара пользователя
AiK
Сообщения: 2287
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

Borys, есть такое мнение, что параметры надо передавать не по значению, а по ссылке.
Даже самый дурацкий замысел можно воплотить мастерски
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

AiK, нет, это здесь не при чем.

Borys, конкретно, в чем ошибка?
Аватара пользователя
AiK
Сообщения: 2287
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

Eugie, да, ты наверное прав. Это в случае var переменной на одну звёздочку требуется больше :)
Даже самый дурацкий замысел можно воплотить мастерски
Borys
Сообщения: 18
Зарегистрирован: 09 июл 2004, 17:25
Откуда: Киев

Ошибка в следующем:
Я в вижуале вызываю функцию:
TShow((LPCSTR)str1, GetSafeHwnd(), (LPCSTR)str2);
Открывается окно делфийского приложения. Оно получает параметры не так как нужно. Например в вижуале str1--"7006", HWND -- число и str2--"Не выбран".
В делфи-диалоге пулучается:
str1="Um'j"
HWND--число, но не то которое было.
str2="7006"(=str1)
Если использовать stdcall(Delphi) и WINAPI(C++) то параметры вроде передаются правильно(по крайней мере строки), но приложение падает.
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Во-первых, при использовании в программе модулей, написанных на разных языках, calling convention в любом случае должны быть согласованы - здесь не может быть сомнений. Не обязательно это должен быть stdcall, можно cdecl, также допустимый в обоих языках (в даннном случае VC++ и Delphi). Но stdcall все же удобнее, т.к. в настоящее время является стандартом для API функций.

Во-вторых, в VC-части лучше использовать явно __stdcall вместо макроса WINAPI, значение которого может меняться в зависимости от платформы и версии компилятора.

Вот пример согласованного объявления ShowForm:

Код: Выделить всё

[VC++]

typedef HWND (__stdcall * PTShowForm)(LPCSTR, HWND, LPCSTR); 

[Delphi]
function ShowForm(c: LPCSTR; h: HWND; d: LPCSTR): HWND; stdcall;
...
exports ShowFrom;
Если это не поможет, сообщи, когда происходит ошибка (с точностью до строки кода, под отладчиком) и ее текст.

PS. Еще пара советов: 1) вместо Form1.Show -> Form1.ShowModal, тогда не нужен будет ShowMessage для задержки формы; 2) вместо Form1.WindowHandle лучше Form1.Handle (последний гарантированно инициализирован).
Borys
Сообщения: 18
Зарегистрирован: 09 июл 2004, 17:25
Откуда: Киев

Eugie, спасибо. Вроде помогло.
Осталась одна проблема:
как связать окна (окно Делфи должно быть дочернее по отношению к окну вижуал си++). Я передаю даскриптор окна С++. И тут начинаются прблемы. Мне необходимо, чтоб окно делфи было немодальным. Когда запускаю приложение, окно показывается, все как надо, но судя по всему оно не реагирует на некоторые сообщения. Например: при нажатии на "таб" фокус не перескакивает на следующий компонент. Если навести фокус на компонент, в который ничего нельзя ввести (например кнопка) и нажать клавишу, то приложение виснет.
Частично проблему решает такое изменение кода (ShowMessage не играет никакой роли, оно было для проверки):

function ShowForm(c: PChar; h: HWND; d: PChar):HWND;
begin
Application.Initialize; //добавлено
Application.Handle:=h; //добавлено
Form1:=TForm1.Create(Application);
Application.DialogHandle:=Form1.Handle; //добавлено
Form1.Edit1.Text:=c;
Form1.Edit2.Text:=inttostr(h);
Form1.Edit3.Text:=d;
Form1.Show;
ShowForm:=Form1.Handle;
end;

В этом случае приложение не виснет, но фокус всеравно не перескакивает.
Я также пытался использовать CreateParanted и CreateParantedControl. Тогда окно делфи вообще не появляется и выскакивает ошибка, короче все падает.
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Добавь в цикл обработки сообщений вызов IsDialogMessage (должен всегда присутствовать при наличии в приложении немодальных диалоговых окон):

Код: Выделить всё

// Main message loop:
  while (GetMessage(&msg, NULL, 0, 0)) 
  {
    if (!IsDialogMessage(hwndForm, &msg))
    {
      if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
     {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
     }
    }
  }
Borys
Сообщения: 18
Зарегистрирован: 09 июл 2004, 17:25
Откуда: Киев

У меня приложение на MFC поетому я добавил код в PreTranslateMessage(MSG* pMsg), помоему - единственное подходящее место где можно получить MSG а не (UINT message, WPARAM wParam, LPARAM lParam). Но всеравно не работает.
Интересно то, что согласно Spy++ форма на делфи не имеет Parent Window(=null). Хотя Owner Window -- как и нужно, окно С++.
Потом, если в делфи вызвать ShowMessage(), то у окошка с сообщением и Parent и Owner - окно С++.
И еще если смотреть сообщения, которые идут на окно С++, когда что-то происходит с окном на делфи (нажатия на кдавиши, движение мышки), то мы видим только одно сообщение: WM_KICKIDLE.
На окно на делфи сообщения не поступают при нажатии на "tab" или "enter".
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

У меня приложение на MFC поетому я добавил код в PreTranslateMessage(MSG* pMsg), помоему - единственное подходящее место где можно получить MSG а не (UINT message, WPARAM wParam, LPARAM lParam). Но всеравно не работает.
К сожалению, это так. В чем причина - не знаю.
Интересно то, что согласно Spy++ форма на делфи не имеет Parent Window(=null). Хотя
Родительское (parent) окно определено только для дочерних (child) окон, а Delphi-форма является окном верхнего уровня и может иметь только владельца (owner window).
Ответить