|
Вопрос # 5 999/ вопрос решён / |
|
Приветствую, уважаемые эксперты!
Нужно при возникновении события в моей длл породить событие в моей программе(желательно с передачей значений переменных в длл).
Сначала рыл в сторону сообщений, но не понял как добавить обработчик моего события в оконную функцию.
Потом рыл в сторону вызова функции которая написана в моей программе из длл(это было бы идеальным событием).
Подскажите в каком направлении рыть.
 |
Вопрос задал: 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 (статус: Посетитель), 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™ (статус: Доктор наук), 15 марта 2012, 14:54 [#2]:
Цитата (QWERYTY):
После всего этого я так понял можно использовать SendHandle в любом месте длл.
Ну как-то так, вроде. Только есть одна хрень, которую я заметил: var Handle: CARDINAL - в одном месте, и без var в остальных. Это принципиально! Переделай.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
QWERYTY (статус: Посетитель), 15 марта 2012, 17:08 [#3]:
Спасибо.
Попробую в новом проекте реализовать.
Тут уже по моему не работать не чему.
Пока не смог проверить по тому что вызываю SendHandle в обработчике хука, и приложение на котором хук тут же вылетает.
Моя прога в этот момент не сообщает ни о каких ошибках но и должное окошко не появляется.
В общем буду дальше ковыряться.
На вопрос ответ получен. Я пытался с начала как с длл, но с экзехой не проканало.
ВЕРИТЬ ВО ВНЕЗЕМНЫЕ ЦИВИЛИЗАЦИИ НЕ ОЗНАЧАЕТ ВЕРИТЬ В ИНОПЛАНЕТЯН.
|
15 марта 2012, 17:11: Статус вопроса изменён на решённый (изменил автор вопроса — 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) пока не извлекал, но думаю тут не должно быть напрягов.
ВЕРИТЬ ВО ВНЕЗЕМНЫЕ ЦИВИЛИЗАЦИИ НЕ ОЗНАЧАЕТ ВЕРИТЬ В ИНОПЛАНЕТЯН.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|