Wiemy, że do biblioteki dll można dołączać obiekty VCL np. zwykłą formę czy jak kto woli formularz. Problem pojawił się, gdy chciałem użyć takiej biblioteki wykorzystując bibliotekę importową *.lib (nie dynamicznie, za pomocą funkcji LoadLibrary). W zalezności od stopnia skomplikowania głównej aplikacji, można zaobserwować różne dziwne rzeczy np:
1) okno z biblioteki dll manifestuje się jako osobna aplikacja na pasku zadań
Sprawy komplikują się gdy zaczynam manipulować opcjami 'Linkier \ Use dynamic RTL' oraz 'Packages \ Build with runtime packages' lub dodaję komponent TXPManifest. Generalnie zaobserwowałem jeszcze takie czary:
2) okno aplikacji nie chce się minimalizować lub nie 'przebija' się przez inne okna
3) inne okna aplikacji też pojawiają się na pasku zadań jako osobne etykiety
4) przy zamykaniu aplikacji powstaje błąd "access violations"
W załączniku są dwa projekty (aplikacji - 'robo.bdsproj' i biblioteki - 'okno.bdsproj') napisane w BDS2006. Poniżej najwazniejsze fragmenty kodów źródłowych:
plik okno.h
- Kod: Zaznacz cały
//---------------------------------------------------------------------------
#ifndef OknoH
#define OknoH
#ifdef BUILD_DLL
#define DLL_MODE __declspec(dllexport)
#else
#define DLL_MODE __declspec(dllimport)
#endif
extern "C" DLL_MODE void __stdcall Okno_Create();
extern "C" DLL_MODE void __stdcall Okno_Destroy();
extern "C" DLL_MODE void __stdcall Okno_Show();
#endif
//---------------------------------------------------------------------------
plik oknoUnit1.cpp
- Kod: Zaznacz cały
//---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#include "oknoUnit2.h"
#define BUILD_DLL
#include "okno.h"
//---------------------------------------------------------------------------
// Important note about DLL memory management ...
//---------------------------------------------------------------------------
#pragma argsused
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
return 1;
}
//---------------------------------------------------------------------------
void __stdcall Okno_Create()
{
if(Form11==NULL){Form11 = new TForm11(NULL);}
}
//---------------------------------------------------------------------------
void __stdcall Okno_Destroy()
{
if(Form11!=NULL){delete Form11; Form11=NULL;}
}
//---------------------------------------------------------------------------
void __stdcall Okno_Show()
{
if(Form11!=NULL)Form11->Show();
}
//---------------------------------------------------------------------------
plik roboUnit1.cpp
- Kod: Zaznacz cały
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "roboUnit1.h"
#include "roboUnit2.h"
#include "roboUnit3.h"
#include "okno.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Okno_Create();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
Okno_Destroy();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button11Click(TObject *Sender)
{
Okno_Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Form2->Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
Form3->Show();
}
//---------------------------------------------------------------------------
Jestem ciekaw czy to ja popełniam jakiś błąd, czy opcje kompilacji muszą być jakoś specjalnie dobrane, czy to może wina środowiska BDS2006. Może ktoś spróbuje to przekompilować w innym środowisku. Byłbym bardzo wdzięczny.
I jeszcze jedno. Chciałbym aby biblioteka była załadowana przy starcie programu i zwolniona dopiero po jego zamknięciu, tak aby obiekt Form11 był powołany na początku i był aktywny przez cały czas trwania programu (przecież nie ma nic w tym złego).