С Новым годом! Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.95/21: Рейтинг темы: голосов - 21, средняя оценка - 4.95
 Аватар для Sasha
4956 / 2420 / 531
Регистрация: 05.06.2008
Сообщений: 7,518
Записей в блоге: 3

Создать DLL, которая создаст кнопку на форме

08.07.2011, 11:59. Показов 4617. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Ребята можно ли как-нить создать такую DLL - которая создавала бы кнопку на форме или пункт меню в компоненте MainMenu?

Заранее благодарен
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.07.2011, 11:59
Ответы с готовыми решениями:

Файл: Создать программу, которая создаст 10 текстовых файлов
Задача Создать программу, которая создаст 10 текстовых файлов "aaa.txt", "bbb.txt", ... , "jjj.txt" и в каждом файле...

На форме создать кнопку и по нажатию на эту кнопку открыть фотографию
Салют всем форумчанам! Помогите мне! Как реализовать следующую задумку - на форме создать кнопку и по нажатию на эту кнопку окрывается...

Создать на форме электронные часы, при нажатии на кнопку они начинают идти с 0 м : 25 с. До 10 м: 33 с. Добавить кнопку
Добрый день, в шараге учебная практика по Deplhi. В задании указано сделать часы, не могу понять как их делать. Понимаю, что нужен таймер и...

21
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
08.07.2011, 15:39
Лучший ответ Сообщение было отмечено как решение

Решение

Элементарно!

Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// dll
//---------------------------------------------------------------------------
 
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
 
extern "C" __declspec(dllexport)void CreateButton(TForm * OwnerForm);
 
void CreateButton(TForm *OwnerForm) {
    TButton *BtnNew = new TButton(OwnerForm);
    BtnNew->Parent = OwnerForm;
    BtnNew->SetBounds(0, 0, 200, 50);
    BtnNew->Caption = "test";
    OwnerForm->InsertComponent(BtnNew);
}
 
#pragma argsused
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) {
    return 1;
}
//---------------------------------------------------------------------------
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// приложение
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "TestImplement.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
}
 
typedef void(__stdcall*CREATE_BTN)(TForm*);
 
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) {
    HMODULE hMod = LoadLibraryA("DynamicCreator.dll");
    if (!hMod) {
        return;
    }
    CREATE_BTN CreateBtn = reinterpret_cast<CREATE_BTN>(GetProcAddress(hMod,
            "_CreateButton"));
    if (CreateBtn) {
        CreateBtn(this);
    }
    FreeLibrary(hMod);
}
//---------------------------------------------------------------------------
5
 Аватар для Sasha
4956 / 2420 / 531
Регистрация: 05.06.2008
Сообщений: 7,518
Записей в блоге: 3
11.07.2011, 09:30  [ТС]
Твой код работает, только вот почему-то после того как я закрываю форму вылетает такая вот ошибка
Как её можно исправить?
Миниатюры
Создать DLL, которая создаст кнопку на форме  
0
 Аватар для Sasha
4956 / 2420 / 531
Регистрация: 05.06.2008
Сообщений: 7,518
Записей в блоге: 3
11.07.2011, 09:32  [ТС]
И ещё как можно назначить действие той кнопке которая создаёться из DLL-ки
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
11.07.2011, 12:50
У себя проверял ничего не вылетало.

Тут может быть такой момент: я использую метод
Цитата Сообщение от Maluda Посмотреть сообщение
OwnerForm->InsertComponent(BtnNew);
Благодаря этому, форма сама при закрытии очистит память, выделенную под компонент,
поэтому потом delete BtnNew вызывать не нужно.

И наоборот, если этот метод не использовать, тогда надо перед закрытием формы
вызвать delete BtnNew

Но, опять же повторюсь, проверял у себя на CBuilder 2010 - ничего не вылетало.


Цитата Сообщение от Sasha Посмотреть сообщение
И ещё как можно назначить действие той кнопке которая создаёться из DLL-ки
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// dll
//---------------------------------------------------------------------------
 
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
 
#pragma argsused
 
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport)void __stdcall CreateButton(TForm * OwnerForm);
 
//---------------------------------------------------------------------------
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) {
    return 1;
}
 
//---------------------------------------------------------------------------
void __fastcall GlobalClick(void *This, TObject *Sender) {
    TButton *BtnClicked = dynamic_cast<TButton*>(Sender);
    if (BtnClicked) {
        ShowMessage(BtnClicked->Name + " was clicked!");
    }
}
 
//---------------------------------------------------------------------------
void __stdcall CreateButton(TForm *OwnerForm) {
    TButton *BtnNew = new TButton(OwnerForm);
    BtnNew->Parent = OwnerForm;
    BtnNew->SetBounds(0, 0, 200, 50);
    BtnNew->Name = "BtnDynamic";
    BtnNew->Caption = "test";
    OwnerForm->InsertComponent(BtnNew);
 
    TMethod Method;
    Method.Data = OwnerForm;
    Method.Code = GlobalClick;
 
    BtnNew->OnClick = *(TNotifyEvent*) & Method;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// cpp
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "TestImplement.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
}
 
typedef void(__stdcall*CREATE_BTN)(TForm * OwnerForm);
 
HMODULE hMod = NULL;
 
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender) {
    hMod = LoadLibraryA("DynamicCreator.dll");
    if (!hMod) {
        return;
    }
    CREATE_BTN CreateBtn = reinterpret_cast<CREATE_BTN>(GetProcAddress(hMod,
            "CreateButton"));
    if (CreateBtn) {
        CreateBtn(this);
    }
}
 
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender) {
    if (hMod) {
        FreeLibrary(hMod);
    }
}
 
//---------------------------------------------------------------------------
Вот добавляю скомпиленный екзешник и длл-ку, чтобы доказать, что никаких вылетов нет
Вложения
Тип файла: rar TestImplement.rar (16.4 Кб, 43 просмотров)
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
11.07.2011, 13:03
П.С. Только екзешник и длл-ку надо распаковать и только потом запускать,
иначе екзешник длл-ку в архиве не увидит.
0
 Аватар для Sasha
4956 / 2420 / 531
Регистрация: 05.06.2008
Сообщений: 7,518
Записей в блоге: 3
11.07.2011, 13:35  [ТС]
Угу и не запускается, требует файлы с расширением bpl

Добавлено через 1 минуту
Перекомпиль проект и вылржи заново
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
11.07.2011, 13:59
Кстати, самое главное, чтобы использовать добавление компонентов из длл-ки,
проект должен быть с ДИНАМИЧЕСКИМ RTL

П.С. Добросил нужные длл-ки, проверял на виртуальной машине, на чистой винде - всё пашет.
Вложения
Тип файла: rar TestImplement.rar (1.64 Мб, 56 просмотров)
1
 Аватар для Sasha
4956 / 2420 / 531
Регистрация: 05.06.2008
Сообщений: 7,518
Записей в блоге: 3
11.07.2011, 14:08  [ТС]
Да спасибо работает.

У меня к тебе ещё вопрос.

У меня к примеру есть скомпилированный екзешник. Так вот можно ли его заставить увидеть мою DLL-ку. Может быть его можно как-нить про патчить.

Собственно с этого вопроса всё и начиналось

Спасибо.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
11.07.2011, 16:02
В уже скомпилированном билдеровском екзешнике единственное,
что можно сделать из хакерских вещей - это управлять ресурсом формы.
То есть можно убрать, например, обработчик события, или поменять на какой-то другой.

Или, если екзешник использует какую-то длл-ку, можно заменить эту длл-ку своей
с такими же прототипами функций, но не факт, что тогда прога вообще заработает.
Всё зависит от профессионализма программиста-разработчика программы.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
object pmBindingsM: TAdvPopupMenu
    Version = '2.5.3.5'
    Left = 280
    Top = 328
    object Addbinding1: TMenuItem
      Caption = 'Add binding'
      OnClick = Addbinding1Click
    end
  end
  object ColorDialog1: TColorDialog
    Left = 660
    Top = 40
  end
П.С. А свою просто так втулить нельзя.
0
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
11.07.2011, 17:16
Цитата Сообщение от Maluda Посмотреть сообщение
А свою просто так втулить нельзя.
Sasha, о чём я собственно тебе и говорил. Всё описанное выше - это практически отработанный механизм расширения функционала программы через плагины. Но для этого само приложение должно быть готово к взаимодействию.
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.07.2012, 17:57
Можно ли эту dll использовать например Visual Studio? Думаю что-нет...
Тогда смысл этой либы?
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
03.07.2012, 20:52
C++
1
OwnerForm->InsertComponent(BtnNew);
Благодаря этому, форма сама при закрытии очистит память, выделенную под компонент,
поэтому потом delete BtnNew вызывать не нужно.
Во первых благодоря не этому,а благодоря заданию Owner.
Во вторых как она очистит если dll выгружается раньше, чем вызывается деструктор формы?
вызвать delete BtnNew
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
03.07.2012, 22:13
Цитата Сообщение от Avazart Посмотреть сообщение
Во вторых как она очистит если dll выгружается раньше, чем вызывается деструктор формы?
Выгрузка библиотеки никак не скажется на динамически созданных ею объектах, так как они располагаются в адресном пространстве динамической памяти. Форма, владеющая созданными таким образом компонентами, очень даже успешно их уничтожит при любом раскладе.

Не по теме:

А с чего это вдруг такой нарочитый интерес к старой теме?:)

0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
03.07.2012, 22:44
Цитата Сообщение от BRcr Посмотреть сообщение
Выгрузка библиотеки никак не скажется на динамически созданных ею объектах, так как они располагаются в адресном пространстве
Да согласен...
Но повторить приведнный код не удалось.
Миниатюры
Создать DLL, которая создаст кнопку на форме  
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
03.07.2012, 22:45
А с чего это вдруг такой нарочитый интерес к старой теме?
При выгрузке библиотеки(ДЛЛ) возникает возникает ошибка
Написать Dll
0
Я Фоюмчанин ? дааааа)
 Аватар для ivan.-94
213 / 204 / 23
Регистрация: 02.06.2012
Сообщений: 1,424
Записей в блоге: 12
04.07.2012, 20:38
Maluda,
Залей пожалуйсто проект программы и проект DLL.
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
11.07.2012, 01:21
Нашел на другом форуме...
Доброго времени суток всем!

Помогите плз, проблема такая:
создаю DLL а в ней опмсан класс в конструкторе которого создается объект класса TRichEdit.
И тестирующее приложение с формой на которой и должен рисоваться этот RichEdit.
Если в опциях проэктов не сняты галочки с Use dynamic RTL и Build with runtime packages то все ОК! Но как только я их снимаю то линкер выдает немыслимое количество ошибок Unresolved external...
Можно ли это как-то побороть?
18.10.2002
Можно то можно, но путем проб и ошибок, потому как шибко многое синхронизировать придется, а потом код получиться в сумме больший, так как все придется линковать и в хост и в длл.
Вот тебе для размышления:
Q: Я разделил свою программу на основной Exe и Dll. после этого все стало
глючить.
(Возможные симптомы: программа отображается на линейке 2 раза, появляются
загадочные сообщения типа "Cannot assign TFont to TFont", базы данных спрашивают
пароль 2 раза(один раз для dll и один раз для exe), происходят загадочные Access
Violation
)

Вы неправильно скомпоновали вашу dll. Для того чтобы все заработало нужно
скомпилить и Exe и Dll c dynamic rtl и runtime packages. Проверьте так же что
все Packages перечислены в списке RP. Т.е. может быть такая ситуация,
что RP включены, но какой нибудь из них в списке пропущен и используется
статически.

Многим людям лень искать какие dll нужны поэтому они все линкуют
в свои exe и dll. Я категорически рекомендую не делать этого.
Уже если вы разделили прогу на exe dll то используйте все остальное
тоже в dll

Несколько причин последовать этому совету:

Причина 1.
Вы все наверняка работали с чужими dll. Хотя бы вызывая функции Windows.
Вы обратили внимание что все строки в них передаются с помощью char*.
Кроме того когда вы например вызываете функцию GetComputerName,
то она не просто возвращает строку, а заставляет вас передать указатель
на буфер и его длину. Это сделано для того чтобы не было таких вещей
чтобы память выделялась в одном модуле а стиралась в другом. Потому как
это некорректно.
В каждом модуле есть такая штука как memory manager которая
выделяет память, освобождает ее и ведет список свободных и занятых блоков.
Так вот когда у вас exe и dll скомпилены без dynamic rtl то получается что у вас
2 разных memory manager-а. Как вы думаете что будет если вы попросили у одного
из них память, а потом попросили другого его стереть?
Я думаю ничего хорошего не получится. Можно конечно дать совет не делать
так. Но учтите что при передаче AnsiString в качестве параметра память
выделяется в вызывающей функции, а уничтожается в вызваной.
Таким образом получается, что нельзя вызывать из dll функции с
параметром AnsiString.

Как это лечится.
1) Достаточно включить use dynamic rtl и у вас получится один менеджер
памяти в специальной dll borlndmm.dll
2) Можно не включать, а сделать как написано в большом комментарии в начале
новосозданной dll. Там рекомендуют включить в проект MEMMGR.LIB. Но в этом
случае все равно будет использоваться borlndmm.dll.
Легче сделать как сказано в пункте 1.

Причина 2.
Вы знаете о существовании глобальных переменных Application, Session и т.п?
А знаете где они объявлены? Соответственно в Forms и Dbtables. А догадываетесь
что будет если подключить эти unit-ы статистически к exe и dll? Правильно у вас
будет по 2 копии этих переменных, одна в одном модуле другая в другом.
Именно из-за этого появляются такие эффекты как двойное название приложения
в линейке задач (чего вы удивляетесь, у вас на самом деле 2 приложения) и
то что пароли к базе данных(имеется ввиду BDE)спрашиваются 2 раза
(у вас 2 сессии, один раз введите пароль для одной и один для другой.
Кстати соединений с БД у вас тоже будет 2).

Как это лечится.
Ну например в случае раздвоения на линейке задач можно передать в dll
Application->Handle из exe и присвоить его местному Application->Handle.
Для Session это наверное тоже как нибудь лечится. Но самый простой
путь это включить Runtime Packages. Тогда у вас будет только одна
копия переменных в отдельном Bpl

Причина 3.
Вы не задумывались как работают операции динамического определения типа.
dynamic_cast в C++ и is/as в Pascal? Они сравнивают указатель на виртуальную
таблицу. Что будет если один и тот же компонент есть в 2 модулях? Правильно,
у него будет 2 виртуальные таблицы. Что будут делать операторы определения
типа когда определяют тип компонента из другого модуля пытаясь сравнить его
vptr с vptr который должен быть в этом модуле? Правильно, они скажут что это
разные компоненты. Отсюда всякие извраты типа Cannot assign TFont to TFont.
Кроме того например Toolbar2000 будучи пристыкован статически не опознает
свои собственные Toolbar-ы из другого модуля и отказывается их пристыковывать.
Есть информация что IBX в таком состоянии просто глючит. Некоторые компоненты
все таки ведут себя вполне прилично, но вы готовы рисковать работоспособностью
программы чтобы выяснить что тот компонент который вы используете именно такой?

Как лечить. Те классы которые не наследуются от TObject определяется
правильно ( Magic! ). С наследниками TObject сделать ничего нельзя.
Единственный выход это включить Runtime Packages.

Причина 4.
При всем этом суммарный объем кода увеличивается т.к. один и тот же код
содержится и в dll и в exe.

Мораль.
Либо не используйте dll вообще либо делайте их с dynamic rtl и
runtime packages.
Обычно эти опции отключают чтобы не искать какие
dll и bpl еще нужны. Но поверьте это ничто по сравнению с тем количеством
проблем которые вас ожидают если вы не воспользуетесь этим советом.
1
Я Фоюмчанин ? дааааа)
 Аватар для ivan.-94
213 / 204 / 23
Регистрация: 02.06.2012
Сообщений: 1,424
Записей в блоге: 12
11.07.2012, 13:22
Я зделал как писал Maluda вначале. У меня поевляеться кнопка на форме, но Очень много всяких ошибок.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
11.07.2012, 14:30
ivan.-94, именно этот проект у меня не сохранился. Но здесь всё элементарно: создаёшь длл мастером и VCL forms application. На форму бросаешь кнопку. И вставляешь тот код, который я приводил. Я тестировал на CBuilder 2010, у меня никаких ошибок не было.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.07.2012, 14:30
Помогаю со студенческими работами здесь

В форме создать кнопку, которая будет изменять текст в определенной строке Excel с "неоплачено" на "оплачено"
Добрый вечер, необходимо в форме создать кнопку которая будет изменять текст в ячейке экселя с неоплачено на оплачено. Поиск есть. Т.е у...

Создать на форме кнопку очистки элементов управления Label от старых данных и кнопку заполнения этих элементов с
Создать на форме кнопку очистки элементов управления Label от старых данных и кнопку заполнения этих элементов с испол-ием функции InputBox

Экспортировать из dll функцию которая создает кнопку
Экспортировать из dll функцию которая создает кнопку Как должна выглядеть функция?

Как сделать кнопку в форме которая перезапустит программу?
Как сделать в C# кнопу в форме которая перезапустит программу?

Как создать Создать страницу со скриптом, которая выводила бы сообщение « Нажмите кнопку для замены текста
Создать страницу со скриптом, которая выводила бы сообщение « Нажмите кнопку для замены текста страницы». В скрипте опишите тег...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru