|
Вопрос # 2 370/ вопрос открыт / |
|
Здравствуйте, уважаемые эксперты! Вопрос у меня такой, возможно ли каким-нибудь образом из библиотеки длл вызвать процедуры или функции главного приложения? Например, клик кнопки или надпись лейбла изменить.
 |
Вопрос задал: Phoenix (статус: Посетитель)
Вопрос отправлен: 30 января 2009, 18:09
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, Phoenix!
Да, причём существует несколько способов. От примитивных до хитрых.
наиболее простой на мой взгляд - это через сообщение windows. приложение должно только передать длл хендл окна, которое будет обрабатывать сообщения (это 4 байта).
Теперь в длл надо вставлять код вида
SendMessage(FormHandle, WM_USER, число, число)
или через
PostMessage(FormHandle, WM_USER, число, число)
где "число" - 4 байта, целое. Что там будет записано - ваше личное дело. а вместо WM_USER можно подставлять любую константу, которая равна WM_USER + некое число (вроде не больше 1000, но обычно до сотни хватает).
эти две функции отличаются тем, что вторая отсылает сообщение и не ждет его выполнения. Очень удобно для потоков, которые ведут рассчёты и им не надо ждать, пока там интерфейс всё отрисует.
первая - отсылает сообщение и ждет, пока оно выполниться. И может возвратить результат в виде 4байтового числа. Эта функция потоковобезопасна.
Теперь, как ловить эти сообщения.
в нужной формы добавляем метод в секцию private
procedure MyProc(var msg:TMessage);messsage WM_USER; Жмем Ctrl+Shift+C и есть обработчик.
два переданные параметра - это msg.Wparam и msg.LParam.
вместо WM_USER надо писать свою константу.
Одна форма может поддерживать несколько пользовательских сообщений.
А как трактовать переданные числа - это уже сами решаете, например, передали 1 - нажми вторую кнопку. Конечно, хорошо, если вместо чисел использовать константы.
Если формы с нужным хендлом не будет или она случайно куда то пропадёт :) то ничего плохого не будет.
Можно также работать и по другому. Приложение при старте передает заготовленную структуру, которая содержит адреса процедур с главной формы. Или интерфейс. Но такой способ имеет свои особенности и сложности реализации.
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 30 января 2009, 18:31
Оценка за ответ: 5
Комментарий к оценке: отлично, спасибо, все понятно. я так полагаю в качестве параметра можно передавать и строку? например SendMessage(FormHandle, WM_USER, 1, dword(str)), а получаем в pchar(msg.LParam). отсюда вопрос: насколько длинные строки можно так передатЬ?
|
Мини-форум вопроса
Всего сообщений: 10; последнее сообщение — 3 февраля 2009, 18:01; участников в обсуждении: 3.
|
min@y™ (статус: Доктор наук), 30 января 2009, 20:38 [#1]:
Дополню ответ Вадимки.
Это дополнение, я считаю, не достойно целого ответа, поэтому пишу в камментах.
Он забыл CallBack-функции. ИМХО, это есть самое оно для данных целей. Главное – передать в DLL указатель на функцию, которая ноходится в EXE.
Механизм этот в инете не просто обсосан до костей, но, ИМХО, даже обглодан. Поэтому не буду баянить. Если есть вопросы – милости просю. Адиос!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Phoenix (статус: Посетитель), 30 января 2009, 21:31 [#2]:
если честно не нашел информации по callback-функциям в области своей надобности. что такое и как действует, этогл навалом. если не сложно, прошу объяснить ,почему их использование "самое оно" для данной цели.
|
|
min@y™ (статус: Доктор наук), 30 января 2009, 21:43 [#3]:
Цитата:
Например, клик кнопки или надпись лейбла изменить.
Вот и передавай в DLL указатель на функцию, которая кликает по кнопке или изменяет надпись лейбла. Это и есть CallBack-функция.
Ума не разложу, зачем это надо делать через DLL, думаю, это ты просто утрируешь, а цели — далеко идущие.
Ну шо, пример написать тебе или сам справишься?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Phoenix (статус: Посетитель), 30 января 2009, 21:53 [#4]:
да, если не трудно, рад только буду
|
|
min@y™ (статус: Доктор наук), 30 января 2009, 22:02 [#5]:
Цитата:
да, если не трудно, рад только буду
Я щас спать ложусь. Устал, после работы пол-дня носился по городу, устал, отморозил ноги. Завтра напомни, плиз, а то забуду.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Phoenix (статус: Посетитель), 31 января 2009, 15:05 [#6]:
уважаемый товарищ эксперт, жду примера. что-то типа длл получает текст из едита формы.
|
|
min@y™ (статус: Доктор наук), 1 февраля 2009, 11:42 [#7]:
Цитата:
жду примера. что-то типа длл получает текст из едита формы.
Не понял... Тебе ж надо выполнить код в ЕХЕ при подаче из DLL.
Определись.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Phoenix (статус: Посетитель), 1 февраля 2009, 14:20 [#8]:
благодарю, но это и так можно сделать через сообщения (предложеные Вадимом). шлем из длл, при получении в ехе выполняем, отсылаем результат-число. что еще нужно?
я бы хотел еще узнать, возможно ли этот результат остылать в виде строки?
|
|
Вадим К (статус: Академик), 1 февраля 2009, 19:07 [#9]:
Передать строку можно. Но надо делать это очень аккуратно.
Никто не мешает передавать указатель на данные, например структуру, класс или строку. Но не надо забывать, что у делфи свой менеджер памяти. И если не принять мер, то у длл и основного приложения будут разные менеджеры памяти. И если передать указатель на строку, то эти менеджеры "поссорятся за память". В результате как минимум будет сообщение о ошибке о доступе к памяти. В худшем случае - обычный "расстрел памяти" - то есть, вроде модифицировали строку, а почему то другая переменная изменилась... И если для integer/real это не смертельно, то для строк/интерфесов может быть плачевно.
Можно конечно намекнуть менеджеру памяти, что надо делать, но лучше сделать как положено. Итак варианты такие.
- используем юникодные строки - то есть вместо string используем widestring. преобразование в обычный string осуществляется автоматически самим компилятором. Важно лишь передавать юникодную строку границу "приложение-длл". Правда я не тестировал это в 2009 делфи. для всех остальных это работает чудесно.
передавать строку можно так Integer(s) и точно таким же образом преобразовывать с числа назад.
- второй способ - выделять память самому и управлять её. Главное, что бы удалялась память там, где выделяется. то есть, если в длл выделили память, то в ней и освобождаем.
Что бы особо не выдумывать, просто объявляем массив вида s:array[0..255] of char; делфи умеет такие массивы без специальных указаний приводить к строке. А передавать можно где то так @(s[0])
- третий способ - использовать альтернативный менеджер памяти. Например FastMM. Качать отсюдова http://sourceforge.net/projects/fastmm/, краткое описание например здесь http://timokhov.blogspot.com/2007/03/delphi-2007-iii-fastmm.html. В этом случае (при правильной настройке конечно) можно будет передавать указатели на обычные строки - никаких проблем.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Phoenix (статус: Посетитель), 3 февраля 2009, 18:01 [#10]:
о как получается, что ж, спасибо, буду использовать юникодные строки.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|