C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Dll + Form1->Show() ==глюк, Вызов формы внутри Dll
Guest
Отправлено: 01.11.2005, 23:26


Не зарегистрирован







Имеется Dll которая постоянно весит в памяти, в ней при определенных условиях происходит вызов функции F() в которой происходит вызов форты которая находиться в этой Dll .
CODE

F()  
{
Application->CreateForm(__classid(TForm1), &Form1);
Form1->Show();
}

Вызов формы происходит без проблем но при событии закрыть вызванную форму, которое происходит в нутрии созданной формы, окно не исчезает а при повторном вызове F() комп вообще зависает, что не так ?
CODE

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{Form1->Close();
}

Rius
Отправлено: 02.11.2005, 06:46


Мастер участка

Группа: Участник
Сообщений: 321



пример (24кБ):

User Attached Image Скачать файл
PluginForm.rar


Guest
Отправлено: 02.11.2005, 16:11


Не зарегистрирован







В данном примере имеются для моего случая одно узкое место, а именно :
Нельзя обращаться к свойствам TFormDLL внутри события той же TFormDLL например
CODE

void __fastcall TFormDLL:: FormDLLCreate(TObject *Sender)
{
FormDLL->Handle;
}

А при попытки написать сой обработчик уже внутри UnitMain модуля у объекта f вообще отсутствует такой параметр как OnCreate; Как быть в этом случаи т.е как вообще обрабатывать события FormDLL формы. И вообще почему я не могу просто вызвать свою форму в нутрии UnitPlugin т.е есть я могу это сделать
CODE

Application->CreateForm(__classid(TForm1), &Form1);
Form1->Show();

А вот корректно закрыть не получается , и вообще как я писал выше форма вызывается не из exe файла с подкаченной Dll, а из Dll- интерфейса и поэтому нужно что бы создание и разрушение формы производилось внутри Dll- интерфейса
AVC
Отправлено: 02.11.2005, 16:41


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

Вызов формы происходит без проблем но при событии закрыть вызванную форму, которое происходит в нутрии созданной формы, окно не исчезает а при повторном вызове F() комп вообще зависает, что не так ?

Ситуация очень напоминает случай, кода приложение и библиотека используют разные экземпляры TApplication. Если это так, то можно либо передавать библиотеке текущий экземпляр Application, либо строить библиотеку и приложение специальным образом.
gvg
Отправлено: 02.11.2005, 16:57


Машинист паровоза

Группа: Участник
Сообщений: 222



QUOTE (Guest @ 01/11/2005, 23:26)
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{Form1->Close();
}

Странно. В обработке события закрытия формы вызывается метод, инициирующий это событие?
Guest
Отправлено: 02.11.2005, 17:08


Не зарегистрирован







Насчет
CODE

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
Form1->Close();
}

я прогнал беса, событие для закрытия вообще то другое
Guest
Отправлено: 02.11.2005, 19:39


Не зарегистрирован







QUOTE
либо строить библиотеку и приложение специальным образом.


AVC если Вас не затруднит можно чуть подробней
AVC
Отправлено: 03.11.2005, 09:36


Ветеран

Группа: Модератор
Сообщений: 1583



И приложение и библиотека должны динамически подключать vcl?.bpl. Вот отвечал на подобный вопрос.

Отредактировано AVC — 03/11/2005, 08:38
Guest
Отправлено: 03.11.2005, 18:09


Не зарегистрирован







QUOTE

И приложение и библиотека должны динамически подключать vcl?.bpl.

Я так и сделал но проблему с обработкой сообщений решить не как не удается
AVC
Отправлено: 04.11.2005, 09:32


Ветеран

Группа: Модератор
Сообщений: 1583



Значит причина не в этом. Может напишите модель кода (минимум строк, ошибка на месте) и покажите здесь?
Guest
Отправлено: 04.11.2005, 14:43


Не зарегистрирован







CODE

MyDll.cpp

#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#include "Unit2.h"
//---------------------------------------------------------------------------
extern "C" void __declspec(dllexport) CreateForm(TApplication*);
//---------------------------------------------------------------------------

#pragma argsused
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
       return 1;
}
//---------------------------------------------------------------------------

void CreateForm(TApplication* pApp)
{
int x,y;
Application = pApp;
TForm2 *f = new TForm2(Application);
f->Show();
}



CODE

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
       : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm2::FormPaint(TObject *Sender)
{
RECT r,t;
HWND h,d;
d=GetDesktopWindow();
h=FindWindow("Shell_TrayWnd",NULL);
GetWindowRect(d,&r);
GetWindowRect(h,&t);
x=r.right-Form2->Width;
y=r.bottom-Form2->Height-(t.bottom- t.top);
MoveWindow(Form2->Handle,x,y,Form2->Width,Form2->Height,false);        
}

CODE

void __fastcall TForm1::Button1Click(TObject *Sender)
{
HINSTANCE Dll=LoadLibrary("MyDll.dll");
if(Dll) {
 typedef void __declspec(dllimport) GetAdr();
 GetAdr *CreateForm = (GetAdr *)GetProcAddress(Dll, "_CreateForm");
 if(CreateForm) CreateForm();
 FreeLibrary(Dll);
}
else ShowMessage("Не удается загрузить MyDll.dll");
}


Ошибка возникает в событии Paint при попытки обратиться к свойствам Form2.
Я все же подозреваю, что я по-прежнему использую разные экземпляры TApplication

AVC
Отправлено: 07.11.2005, 10:48


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

Ошибка возникает в событии Paint при попытки обратиться к свойствам Form2

Это закономерно. Вы создаете экземпляр класса указуемый f а пытаетесь работать через "мусорный" Form2. И еще нескольколько подобных замечаний.
Если все сделать аккуратно, то все работает нормально. Вот основные куски работающего кода
App
CODE

// FMain.h
private: HINSTANCE FDll;
public:
__fastcall  TForm1(TComponent* Owner);
__fastcall ~TForm1(void);

//FMain.cpp
//typedef void __declspec(dllimport) GetAdr(TApplication*, TScreen*);
// Эксперимент показал, что дешевле подключить vcl??.bpl в оба проекта
// чем руками заполнять общие переменные
typedef void __declspec(dllimport) TOpenForm2(void);

void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(FDll) {
  TOpenForm2 *OpenForm2 = (TOpenForm2 *)GetProcAddress(FDll, "_OpenForm2");
  if(OpenForm2) OpenForm2();
}

}


Dll
CODE

//extern "C" void __declspec(dllexport) OpenForm2(TApplication*, TScreen*);
extern "C" void __declspec(dllexport) OpenForm2(void);

void OpenForm2()
{
TForm2 *f = new TForm2(Application);
f->Show();
}

//---------------------------------------------------------------------------

void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
Action = caFree;
}

//---------------------------------------------------------------------------

void __fastcall TForm2::FormPaint(TObject *Sender)
{
/*
Из-за страшной смеси vcl и чистого api
на экране творится чер-те что
Хотя ошибок не вызывает
*/
return;
}


А вот и сам проект.


User Attached Image Скачать файл
DllForm.rar



Вернуться в Вопросы программирования в C++Builder