Поиск:

Ответ в темуСоздание новой темы Создание опроса
> создание в DLL динамических компонентов 
:(
    Опции темы
mr.Koddy
Дата 27.5.2005, 20:32 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Пример. У меня есть программа. При некоторых событиях должна динамически создаваться форма и все что там на ней мне понадобиться. Если не использовать DLL, то все проходит на ура. Но мне хотелось бы создание формы и всего прочего впихнуть в DLL. DLL-ка у меня VCL-ная, без эмуляции VC.Билдер шестой.

Код DLL:
Код

#include <vcl.h>
#include <windows.h>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#pragma hdrstop
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
        return 1;
}

extern "C" void __export Funk(void)
{
TForm* B=new TForm(Application,1);// динамическая форма
B->ClientHeight=100;
B->ClientWidth=100;
B->Height=100;
B->Left=100;
B->Top=116;
B->Width=100;
B->Caption = "Form";
B->Show();
TLabel *Lab;// = new TLabel(NULL);// метка на ней
Lab->Parent=B;
Lab->Caption = "New";
Lab->Show();
//TRxLabel *Lab1;// = new TRxLabel(this);// еще одна "не 
// стандартная" метка
//Lab1->Parent=B;
//Lab1->Caption = "RX";
//Lab1->Show();
}

При таком верианте форма создается. Но вот когда дело доходит до метки, то мне выдается исключение ну и адреса всякие. Метки ессно нету. Но прога не падает, как ни странно. Если же я напишу
Код

TLabel *Lab = new TLabel(NULL); 

то у меня форма создается, показывается и тут же пропадает. Никакх исключений не генериться.
Если я пытаюсь всунуть еще и метку из RX LIB, то тут вообще фигня какая-то. Не знает что такое TRxLabel не смотря на то, что я добовляю
Код

#pragma link "RXCtrls"

и
Код

#include "RXCtrls.hpp"

При этом компилятор ругается, что во-первых не может найти dxforumlibc6.lib и RXCtrls.hpp тоже не понятно где брать. Если в основной проге добавлю чтонить из этой библы, но ессно все работает. dxforumlibc6.lib и RXCtrls.hpp я и сам не нашел. Нашел только dxforumlibc6.bpl, но от этого мне мало проку.
Ну а из основной проги это вызывается так(из кнопки):
Код

    void (__stdcall *Funk)(void);
    HINSTANCE dllp = LoadLibrary("Project1.dll");
    if (dllp) {
        Funk= (void(__stdcall *)(void))
        GetProcAddress(dllp, "_Funk");
                Funk();
        }
    FreeLibrary(dllp);

Если в DLL написать например для простоты MessageBox, то все и коппилиться и вызывается корректно.
  Вверх
Vyacheslav
Дата 30.5.2005, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Вы создаете форму, показываете ее и тут же выгружаете dll. И что вы после этого хотите получить? Для начала подправте код следующим образом
Код

TForm* B=new TForm(Application,1);// динамическая форма
B->ClientHeight=100;
B->ClientWidth=100;
B->Height=100;
B->Left=100;
B->Top=116;
B->Width=100;
B->Caption = "Form";
//B->Show();   <--- ЗДЕСЬ
TLabel *Lab= new TLabel(NULL);//  <--- ЗДЕСЬ
Lab->Parent=B;
Lab->Caption = "New";
Lab->Show();
B->ShowModal();  // <--- ЗДЕСЬ
delete B; // <--- ЗДЕСЬ



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Guest
Дата 31.5.2005, 22:13 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Все работает.Но теперь появилась другая проблема - вместе с формой появляется лишняя кнопка на панели задач. Как ее убрать?
ShowWindow(B->Handle, SW_HIDE); не помогает.

  Вверх
mr.Koddy
Дата 31.5.2005, 22:14 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











выше я написал
  Вверх
Vyacheslav
Дата 1.6.2005, 09:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Собери оба проекта с включенной опцией Build with rutime package (Project->Options->Вкладка Package)



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
mr.Koddy
Дата 1.6.2005, 20:12 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата
Собери оба проекта с включенной опцией Build with rutime package (Project->Options->Вкладка Package)

Мне это не подходит т.к. прогу я планирую запускать не тока на компе с билдером.
  Вверх
Vyacheslav
Дата 2.6.2005, 10:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



А кто Вам мешает сделать как делают все люди, а именно использовать инсталятор , который будет переносить на комп не только твою программу, но и необходимые компоненты. Кроме того, елси при использовании dll, Вы не будете использовать данный совет, очень скоро при более менеее серьезной работе с dll нарветесь на ошибки. Первый признак: получение сообщений что то типа "Can' t assign TFont to TFont"


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
mr.Koddy
Дата 2.6.2005, 20:05 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата
А кто Вам мешает сделать как делают все люди, а именно использовать инсталятор , который будет переносить на комп не только твою программу, но и необходимые компоненты.

Дело в том, что я не знаю как делают все люди т.к. прог сделаных на bcb не видел. Инсталятор конечно будет. Не не хотелось тащить кучу не маленьких файлов. По инету качать лишние пару метров я думаю не всякий захочет.Где-то я читал, что объем exe может привысить bcb_dll+bpl+exe+my_dll. Хотя я в этом сомневаюсь. Не уверен, что bpl можно сжать тем же ASPackом например. А исталяторы не все сжимают хорошо.smile
Цитата

Первый признак: получение сообщений что то типа "Can' t assign TFont to TFont"

Посыпю голову пеплом, не совсем въехал, что это за ошибка.
Но я уверен, что каждую ошибку можно решить.
Сейчас думаю на другой проблемой. В DLL наследовал класс от TForm и пытаюсь традиционным образом создать форму.
В инит dll добавил следующее:
Код

#include "Unit1.h" 
TForm2 *Form2; 

__fastcall TForm2::TForm2(TComponent* Owner) 
        : TForm(Owner) 


void __fastcall TForm2::Button1Click(TObject *Sender) 

MessageBox(NULL,"Test","Test",MB_OK); 

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) 

           Application->CreateForm(__classid(TForm2), &Form2); 
           Form2->Show(); 
           return 1; 


Заголовочный файл dll:
Код

#ifndef Unit1H 
#define Unit1H 
#include <Classes.hpp> 
#include <Controls.hpp> 
#include <StdCtrls.hpp> 
#include <Forms.hpp> 
class TForm2 : public TForm 

typedef TForm inherited; 
__published:   // IDE-managed Components 
        TButton *Button1; 
        void __fastcall Button1Click(TObject *Sender); 
private:   // User declarations 
public:      // User declarations 
        __fastcall TForm2(TComponent* Owner); 
}; 
extern TForm2 *Form2; 
#endif 

DLL компилиться.
В основное приложение засунул следующее:
Код

void __fastcall TForm1::FormPaint(TObject *Sender) 

HINSTANCE dllp = LoadLibrary("Project1.dll");        


Т.е. при прорисовке основной формы загружается DLL, и как я понимаю сначала должен выполняться код, который в DllEntryPoint записан. Ну вот прога на и ругается, что мол чето в DllEntryPoint не то. Аесли точнее то:
Цитата
An exception (0EEDFADE) occured during DllEntryPoint or DllMain in moduleD:\bcb\project1.dll

Если я правильно понимаю, в DllEntryPoint надо, что бы фигрировал свой Application. А как это сделать пока не нашел.Хотя може я и не прав.
  Вверх
Vyacheslav
Дата 3.6.2005, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(mr @ 2.6.2005, 20:05)
Дело в том, что я не знаю как делают все люди т.к. прог сделаных на bcb не видел. Инсталятор конечно будет. Не не хотелось тащить кучу не маленьких файлов. По инету качать лишние пару метров я думаю не всякий захочет.Где-то я читал, что объем exe  может привысить bcb_dll+bpl+exe+my_dll. Хотя я в этом сомневаюсь.

Во-первых, странно, что не видели. С++Builder 6 например.
Во-вторых, будьте последовательным. Вы уже собираетесь разбить свою программу на exe и dll, но почему-то против bpl, хотя эти те же dll. Самая первая ошибка начинающих( а Вы ведь начинающий, иначе не задавали подобных вопросов ) стараются сделать все в одном куске. Если, кстати для создания инсталятора будете использовать InstallShield, поставляемый с Borland, он сам подскажет какие bpl нужно будет включить в пакет

Цитата(mr @ 2.6.2005, 20:05)

Посыпю голову пеплом, не совсем въехал, что это за ошибка.
Но я уверен, что каждую ошибку можно решить.

Блажен кто верует. Если хотите, я могу рассказать про эту "ошибку" подробнее и с удовольствием посмотрю как Вы это попытаетесь исправить. А сейчас лишь намекну, что она связана с тем, что для классов одновременно использующихся в exe и dll при статической прилинковке библиотек создаются две и более копии виртуальные таблиц первая в exe, остальные - в dll-ках. Надеюсь эта фраза прояснила, почему выдается такое странное сообщение.
Цитата(mr @ 2.6.2005, 20:05)

Сейчас думаю на другой проблемой. В DLL наследовал класс от TForm и пытаюсь традиционным образом создать форму.

Да вроде Вам на Borland X Portal все уже прописали. Повторить что ли?
DLL
Код

extern "C" TForm* __declspec(dllexport) CreateMyForm(TForm* Owner)
{
      return new TForm2(Owner);
}

EXE
Код

void __fastcall TForm1::Button1Click(TObject *Sender) 

  if (HINSTANCE DLLInstance = LoadLibrary("MDIChild.dll"))
  {
     typedef TForm* (__cdecl* TCreateMyForm)(TForm*);
     if( TCreateMyForm CreateMyForm = (TCreateMyForm)GetProcAddress(DLLInstance,"_CreateMyForm")) {
      TForm* form = CreateMyForm(this);
      form->Show();  
    } 
  }       




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Guest
Дата 3.6.2005, 20:01 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата
А сейчас лишь намекну, что она связана с тем, что для классов одновременно использующихся в exe и dll при статической прилинковке библиотек создаются две и более копии виртуальные таблиц первая в exe, остальные - в dll-ках. Надеюсь эта фраза прояснила, почему выдается такое странное сообщение.

smile Не прояснила.Я в таких дебрях не копался.
Цитата
Да вроде Вам на Borland X Portal все уже прописали.

Видимо там(и тут?) меня не так поняли.
Класс, описывающий форму я делаю в DLL. Т.е. unit.h(класс формы) я добовляю к проекту с DLL и в unit.cpp просто его "инклюдю". И в DLL-ке создаю форму.Нафик мне часть кода по созданию в ехе и часть в DLL пихать. smile Тогда уж проще все в ехе сделать - "все в одном куске". smile Ну все обработчики тоже в DLL засунуть.
  Вверх
Vyacheslav
Дата 6.6.2005, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



И здесь и тут Вас правильно поняли и дали конкретный ответ. Вы просили: форма в dll, созданная с помощью дизайнера совсеми своими обработчиками должна использоваться в основном приложении exe. Вам это и дали. Вы бы для начала хотя бы попробовали выполнить то, что Вам советуют отвечая на Ваши вопросы. А затем уж можно давать свои оценки.


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
mrKoddy
Дата 6.6.2005, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.6.2005

Репутация: нет
Всего: нет



Цитата
Вы бы для начала хотя бы попробовали выполнить то, что Вам советуют отвечая на Ваши вопросы.

Да пробовал конечно. Сейчас попробую объяснить, чего бы мне хотелось.
Это приведеный выше код в ЕХЕ
Код

void __fastcall TForm1::Button1Click(TObject *Sender) 

  if (HINSTANCE DLLInstance = LoadLibrary("MDIChild.dll"))
  {
     typedef TForm* (__cdecl* TCreateMyForm)(TForm*);
     if( TCreateMyForm CreateMyForm = (TCreateMyForm)GetProcAddress(DLLInstance,"_CreateMyForm")) {
      TForm* form = CreateMyForm(this);
      form->Show();  //зачем мне отображение формы в ехе?
    } 
  }       
}

Я же ясно написал - в dll_h содержиться унаследованый класс от Tform, а в dll_cpp реализация его методов.
При таком раскладе в ехе мне надо написать примерно следующее:
Код

void __fastcall TForm1::Button1Click(TObject *Sender) 

  if (HINSTANCE DLLInstance = LoadLibrary("MDIChild.dll"))
  {
     typedef void (__cdecl* CreateMyForm)(void);
     if( (void)CreateMyForm = (void)GetProcAddress(DLLInstance,"_CreateMyForm")) 
      CreateMyForm();
 }       
}

Т.е. как бы получается DLL-ка в определенной степени сама по себе. А наилучшим вариантом было бы конечно, что бы формы creatились в DllEntryPoint и тогда бы возможно пришлось бы переопределить метод TForm Create.
Можно конечно так, как тут предлагают. Но тогда, в частности, придется обрабатывать OnClick от кнопки так:
Код

     TButton* MyButton = dynamic_cast<TButton*>(Sender);
     if (MyButton) 
     {
              if (MyButton->Parent) delete MyButton->Parent;
     } 

А это мне кажется не очень изящно. Хотя может быть я от этого никуда и не денусь.
PM MAIL   Вверх
Vyacheslav
Дата 7.6.2005, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата

//зачем мне отображение формы в ехе?

Странная фраза. Какая разнмца, где вызывать Show. Или под "отображение" Вы понимаете что-то другое. Зато Вы получаете указатель на объект-форму, с которой можете обходится как хотите. Учтите, что файла *.h для TForm2 все равно не нужен в exe. Возвращаем TForm*, так что и exe и dll полностью развязаны.
Ну а если все таки не хотите так, неужели трудно додумать?
Вариант, когда при вызове будет создаваться новая форма каждый раз. Уничтожаться они будут, если будет уничтожен Owner или при их закрытии, если задан соответсвующим образом обработчик OnClose
Код

extern "C" void  __declspec(dllexport) CreateMyForm(TForm* Owner)
{
      (new TForm2(Owner))->Show();
}

Вот так если нужно каждый раз вызывать одну и туже форму
Код

extern "C" void  __declspec(dllexport) CreateMyForm(TForm* Owner)
{
      static TForm2* form = new TForm2(Owner);
      form->Show();
}

С этим надеюсь разобрались

Цитата

Т.е. как бы получается DLL-ка в определенной степени сама по себе. А наилучшим вариантом было бы конечно, что бы формы creatились в DllEntryPoint и тогда бы возможно пришлось бы переопределить метод TForm Create.
Можно конечно так, как тут предлагают. Но тогда, в частности, придется обрабатывать OnClick от кнопки так:

Это я совсем не понял. Каким образом создание форм DllEntryPoint связано с TForm Create, тем более что мы работаем в С++. А здесь рекомендуется(в том числе и Borland ) использоватьтело конструктора
И с кнопкой тоже не понял.

Итак. Создаем проект dll. В нем форму. Назначаем ей все обработчики. Дописываем там же CreateMyForm. И все. Используем ее в exe. Что не так? Я просто не могу понять. Если хотите получить конкретный совет, напишите РАБОТАЮЩИЙ код, который Вас не устраивает. Просто еще раз прошу, не нужно приводить здесь Ваши домыслы и предположения. Иначе я просто не смогу ничем помочь.


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
mrKoddy
Дата 7.6.2005, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.6.2005

Репутация: нет
Всего: нет



Цитата
Какая разнмца, где вызывать Show.

Ну как.smile Если я ее вызывать буду в ехе, то и назначать обработчики тоже.Если вызвать Show в ехе, а назначать обработчики в DLL, то я вообще-то не представляю себе как это можно организовать. smile
Цитата
С этим надеюсь разобрались

Нет Я не совсем понял, что передавать в качестве параметра Owner. Я пытаюсь передать Form1(главная форма приложения). Однако видимо не то передаю.
Цитата
Это я совсем не понял. Каким образом создание форм DllEntryPoint связано с TForm Create, тем более что мы работаем в С++. А здесь рекомендуется(в том числе и Borland ) использоватьтело конструктора
И с кнопкой тоже не понял.

Создаем проект dll. В нем форму. Назначаем ей все обработчики. Дописываем там же CreateMyForm. И все.
А что с кнопкой не понятно. Создать ее и Назначить ей обработчик(и) там же, в DLL.
PM MAIL   Вверх
Vyacheslav
Дата 8.6.2005, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(mrKoddy)

Цитата
Какая разнмца, где вызывать Show.

Ну как.smile Если я ее вызывать буду в ехе, то и назначать обработчики тоже.Если вызвать Show в ехе, а назначать обработчики в DLL, то я вообще-то не представляю себе как это можно организовать. smile


С какой стати.
Код

form->Show() ;

Это все, что с формой нужно сделать. Где я тут приводил код по назначению каких либо обработчиков? Хотя доступ к указателю объекта позволяет в принципе подменить ее обрабочики на другие, если в этом есть необходимость.
Еще раз: создаете форму в дизане в проекте dll, там же определяете обработчики. И пишите код ее показа где хотите : в exe или dll. Это безразлично. Я просто не могу уяснить, какие здесь проблемы. Эти два вопроса совершенно независимы

Цитата(mrKoddy)

Цитата
С этим надеюсь разобрались

Нет Я не совсем понял, что передавать в качестве параметра Owner. Я пытаюсь передать Form1(главная форма приложения). Однако видимо не то передаю.

Обычно передается главная форма но можно и ничего не передавать(NULL). Это зависит от того как собираетесь уничтожать созданную форму. А что с передачей не так? Код абсолютно прозрачен. Как Вы определили, что указатель на форму не передается?

Цитата(mrKoddy)

А что с кнопкой не понятно. Создать ее и Назначить ей обработчик(и) там же, в DLL.

Ну и ради бога. Создавайте и назначайте. Здесь то какие проблемы?




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0851 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.