Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 5 999

/ вопрос решён /

Приветствую, уважаемые эксперты!
Нужно при возникновении события в моей длл породить событие в моей программе(желательно с передачей значений переменных в длл).
Сначала рыл в сторону сообщений, но не понял как добавить обработчик моего события в оконную функцию.
Потом рыл в сторону вызова функции которая написана в моей программе из длл(это было бы идеальным событием).

Подскажите в каком направлении рыть.

QWERYTY Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: QWERYTY (статус: Посетитель)
Вопрос отправлен: 14 марта 2012, 20:57
Состояние вопроса: решён, ответов: 1.

Ответ #1. Отвечает эксперт: min@y™

Цитата (QWERYTY):

Потом рыл в сторону вызова функции которая написана в моей программе из длл(это было бы идеальным событием).

Это называется Callback-функции. Пишешь тип в модуле, который компилится и с exe, и с dll:
type
  TMyCallback = function (параметры): тип_результата; stdcall;
Дальше в exe:
// функция, которая будет вызываться из dll
function MyCallBack(параметры): тип_результата; stdcall;
begin
  // тут всякий разный кривой код
end;
Далее в dll:
var
  CallbackFunction: TMyCallback; // глобальная переменная
 
procedure Init(ACallbackFunction: TMyCallback); stdcall; export;
begin
  CallbackFunction:= ACallbackFunction; 
end;
 
// где-то в коде, где нужно вызвать функцию из exe:
if Assigned(CallbackFunction)
  then результат:= CallbackFunction(параметры);
При загрузке dll из ехе нужно проинициализировать указатель в dll, передав его в процедуру Init(). Этот код писать не буду, задолбался.

Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 15 марта 2012, 08:22
Оценка за ответ: 5


Мини-форум вопроса

Всего сообщений: 4; последнее сообщение — 15 марта 2012, 22:54; участников в обсуждении: 2.
QWERYTY

QWERYTY (статус: Посетитель), 15 марта 2012, 14:15 [#1]:

1. Я написал следующее и в ехе и в dll:
type
TGetHWND = procedure(var Handle: CARDINAL); stdcall;
Это Правильно?

2. В ехе написана функция которую нужно вызвать:
implementation
 
{$R *.dfm}
 
procedure GetHWND(Handle: CARDINAL); stdcall;
begin
  ShowMessage('ОК. Всё норм!!!');
end;

3. В dll я пишу:
var
  ....
  ....
  SendHandle: TGetHWND;
 
 
{$R *.res}
 
procedure Init(MyFunk: TGetHWND); stdcall; export;
begin
  SendHandle := MyFunk;
end;
Это правильно?

Если выше всё верно то начинается самое интересное.
Как я понял мне нужно из ехе вызвать Init передав параметром указатель на процедуру GetHWND.
Делаю я это так:
var
  ....
  ....
  Init: procedure(var MyFunk: TGetHWND); stdcall;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.FormCreate(Sender: TObject);
var
....
....
begin
   // здесь определяется путь к длл
  if CopyDllState = TRUE then
  begin
    HModule := LoadLibrary(PWideChar(DllPath));
    if HModule = 0 then
    begin
      ShowMessage('Не удаётся загрузить модуль(...). Перезапустите программу.');
    end
    else
    begin
      @Init := GetProcAddress(HModule, PWideChar('Init'));
      MyFunk := @GetHWND;
      Init(MyFunk);
    end;
  end;
end;
Ну компилятор это успешно хавает.

После всего этого я так понял можно использовать SendHandle в любом месте длл.
Или я вообще ничерта не понял?
ВЕРИТЬ ВО ВНЕЗЕМНЫЕ ЦИВИЛИЗАЦИИ НЕ ОЗНАЧАЕТ ВЕРИТЬ В ИНОПЛАНЕТЯН.
min@y™

min@y™ (статус: Доктор наук), 15 марта 2012, 14:54 [#2]:

Цитата (QWERYTY):

После всего этого я так понял можно использовать SendHandle в любом месте длл.

Ну как-то так, вроде. Только есть одна хрень, которую я заметил: var Handle: CARDINAL - в одном месте, и без var в остальных. Это принципиально! Переделай.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
QWERYTY

QWERYTY (статус: Посетитель), 15 марта 2012, 17:08 [#3]:

Спасибо.
Попробую в новом проекте реализовать.
Тут уже по моему не работать не чему.

Пока не смог проверить по тому что вызываю SendHandle в обработчике хука, и приложение на котором хук тут же вылетает.
Моя прога в этот момент не сообщает ни о каких ошибках но и должное окошко не появляется.
В общем буду дальше ковыряться.
На вопрос ответ получен. Я пытался с начала как с длл, но с экзехой не проканало.
ВЕРИТЬ ВО ВНЕЗЕМНЫЕ ЦИВИЛИЗАЦИИ НЕ ОЗНАЧАЕТ ВЕРИТЬ В ИНОПЛАНЕТЯН.

15 марта 2012, 17:11: Статус вопроса изменён на решённый (изменил автор вопроса — QWERYTY): Инопланетяне приказали.

QWERYTY

QWERYTY (статус: Посетитель), 15 марта 2012, 22:54 [#4]:

Минай, чтото мы перемудрили по моему. Немного повозился и оказалось что никакой type в ехе не нужен.
1. В длл:
uses
  SysUtils,
  Classes,
  Windows,
  Messages,
  Dialogs;
 
type
  TGetHWND = procedure(var Handle: CARDINAL); stdcall;
 
var
SendHandle: TGetHWND;
Handle: CARDINAL;
 
{$R *.res}
 
procedure Init(var PGetHWND: POINTER); stdcall; export;
begin
   SendHandle := PGetHWND;
   Handle := 1234567;
   SendHandle(Handle);
   ShowMessage('Была вызвана процедура из dll');
end;
 
 
exports
       Init;
 
begin
end.

2. В ехе:
...
var
  Form1: TForm1;
  HModule: CARDINAL;
  PGetHWND: POINTER;
  Init: procedure(var PGetHWND: POINTER); stdcall;
 
implementation
 
{$R *.dfm}
 
procedure GetHWND(var Handle: CARDINAL); stdcall; export;
begin
  ShowMessage('ОК. Всё норм!!!');
end;
 
 
procedure TForm1.Button1Click(Sender: TObject);
begin
    PGetHWND := @GetHWND;
    if Assigned(PGetHWND) then
    Init(PGetHWND) else
    ShowMessage('Бл*!');
end;
 
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  HModule := LoadLibrary(PWideChar('DLL\MyDll.dll'));
  @Init := GetProcAddress(HModule, PWideChar('Init'));
end;
 
 
end.

Ну проще я уже не вижу.
Тот вариант который я написал изначально в главном проекте при вызове функции модулем длл из ехе ссылался на нулевую память(в итоге происходил ахтунг).
А вот так вроде проканывает, появляются оба сообщения. Параметр(Handle) пока не извлекал, но думаю тут не должно быть напрягов.
ВЕРИТЬ ВО ВНЕЗЕМНЫЕ ЦИВИЛИЗАЦИИ НЕ ОЗНАЧАЕТ ВЕРИТЬ В ИНОПЛАНЕТЯН.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 2 апреля 2020, 04:10
Выполнено за 0.03 сек.
Рейтинг@Mail.ru