[DELPHI] Problem z dll'ką i show modal.

0

Zrobiłem programik i dll'ke.
Odpalam program. Odpalam dll'ke. Po stworzeniu DLL'ki.. robie showmodal pewnego unitu dll'ki... i wszystko byloby OK, gdyby nie to iż pokazana Dll'ka jest tak jakby osobną aplikacją (na pasku menu start jest zarówno moja główna aplikacja, jak i moja dll'ka). Co więcej.. jezeli w dll'ce chce pokazac obojętnie jakie okno za pomoca showmodal.. to ono tez widnieje na dole w pasku menu start...

Jak sobie z tym poradzić?
Z góry dzięki za podpowiedzi.

0

bodajże przekaż jak tworzysz forme jako sender application albo forme.Nie wiem czy to załatwi problem.Musiałbym sprawdzić w praktyce :D

0

Dzieje się tak dlatego ponieważ Application DLLki i Application EXEka to dwa różne Application. Należy odpowiednio wywołać DLLkę (a znajdziesz o tym w każdym opisie tworzenia pluginów w Delphi, które to znajdziesz przy pomocy google a którego to ja Ci nie podam, bo linki do google nie są tu mile widziane). W zarysie to wygląda tak:

W DLLce musisz dodać dwie dodatkowe funkcje (być może już masz coś podobnego) oraz dwie dodatkowe zmienne

var
  DS: TScreen;
  DA: TApplication;

procedure InitPlugin(App, Scr: Integer); stdcall;
begin
  DS := Screen;
  Screen := TScreen(Scr);
  DA := Application;
  Application := TApplication(App);
end;

procedure DonePlugin; stdcall;
begin
  Screen := DS;
  Application := DA;
end;

// oraz ich export
eports
  InitPlugin    name 'InitPlugin', 
  DonePlugin    name 'DonePlugin';

Procedura InitPlugin powinna zostać wywołana po dynamicznym załadowaniu DLLki przez EXE a najpóźniej przed stworzeniem jakiego kolwiek okna z DLLki.
Natomiast procedura DonePlugin MUSI zostać wykonana przed wyładowaniem DLLki z pamięci.

Teraz w EXEku wołamy DLLkę tak

...
// np. jako zmienne globalne
var
  InitPlugin: procedure(App, Scr: Integer; stdcall;
  DonePlugin: procedure; stdcall;

...

//wywołanie plugina
  Dll := LoadLibrary(PChar('nazwa_pliku'));
  try
    @InitPlugin := GetProcAddress(Dll, 'InitPlugin');
    @DonePlugin := GetProcAddress(Dll, 'DonePlugin');        
    // reszta procedur z DLLki
    if (@InitPlugin <> nil) and (@DonePlugin <> nil) and ({reszta_procedur_z_DLLki <> nil}) then
    begin
      InitPlugin(Integer(Application), Integer(Screen));
      //co tam dalej
     end;  
  except
    FreeLibrary(Dll);
  end

...

// wyładowanie plugina
  DonePlugin;
  FreeLibrary(Dll);

Mam nadzieję, że moja odpowiedz rozwiązuje Twój problem i jest zrozumiała i nie urąga Ci w żadnym sensie i po jej przeczytaniu czujesz się dobrze i choć odrobinę bardziej mądry (chociaż o tą wiedzę, czemu to nie działało).

0

Dzięki MiskiekD.. tak wlaśnie sądziłem że to coś takiego z tym application wziązanego będzie. Jak tylko znajde chwilke czasu to sprawdze Twoje rozwiązanie. Jeszcze raz dzięki. [browar]

0

Niestety nie działa :-/ Podczas tworzenia pierwszej formy wywala access violation. Gdy zaremuje

// DS := Screen;
// Screen := TScreen(Scr);

w procedurce InitPlugin(App, Scr: Integer); stdcall; program działa (błąd się nie pojawia), ale pomimo przypisywania aplikacji (miałem coś podobnego wcześniej) problem (z oknami otwierającymi się tak jakby to była inna aplikacja) nadal pozostaje. Jakieś wskazówki? :|

0

W C++ Builderze robie to tak:

/* 
  kod (od strony DLL'ki) w C++ ale myśle, że skumasz o co chodzi ;) 
  hwndOwner to uchwyt okna rodzica.
*/

Application->Handle=hwndOwner;

TFormXXX *dlg=new TFormXXX(Application);
dlg->ShowModal();

delete dlg;
0
Calavero napisał(a)

Niestety nie działa :-/ Podczas tworzenia pierwszej formy wywala access violation. Gdy zaremuje

// DS := Screen;
// Screen := TScreen(Scr);

w procedurce InitPlugin(App, Scr: Integer); stdcall; program działa (błąd się nie pojawia), ale pomimo przypisywania aplikacji (miałem coś podobnego wcześniej) problem (z oknami otwierającymi się tak jakby to była inna aplikacja) nadal pozostaje. Jakieś wskazówki? :|

  1. mi pozostaje SOA - u mnie tak działa trochę większa aplikacja i jest to OK w 100%
  2. a masz takie wywołanie w EXE InitPlugin(Integer(Application), Integer(Screen));?
0

DLL"ka wygląda w skrócie tak:

////////////////////////////////* DLL *///////////////////////////////
var
DS: TScreen;
DA: TApplication;

procedure InitPlugin(App:Integer; Scr: Integer); stdcall;
begin
DS := Screen;
Screen := TScreen(Scr);
DA := Application;
Application := TApplication(App);
end;

procedure DonePlugin; stdcall;
begin
Screen := DS;
Application := DA;
end;

procedure Intro_dll(abaza_danych:shortstring); StdCall;
begin
with TfrmIntro.Create(Application) do <----- TUTAj wywala blad :/
begin
Baza_danych := abaza_danych;
ShowModal;
Free;
end;
end;

exports
Intro_dll,
InitPlugin,
DonePlugin;

/////////////////////PROGRAM///////////////////////////

procedure Uruchomienie_DLL_INIT;
type
TProcedura = procedure(abaza:shortstring) : TModalResult; StdCall;
TInitPlugin = procedure(App, Scr: Integer); StdCall;
TDonePlugin = procedure; stdcall;
var
LibHandle : THandle;
Procedura : TProcedura;
InitPlugin : TInitPlugin;
DonePlugin : TDonePlugin;
baza_danych : string;
begin

LibHandle :=LoadLibrary(PChar(ExtractFilePath(Application.ExeName) + 'DLL\Intro.dll'));

if LibHandle <> 0 then
begin
@Procedura:=GetProcAddress(LibHandle,'Intro_dll');
@InitPlugin := GetProcAddress(LibHandle, 'InitPlugin');
@DonePlugin := GetProcAddress(LibHandle, 'DonePlugin');

if (not(@Procedura = nil)) AND (not(@InitPlugin = nil)) AND (not(@DonePlugin = nil)) then
begin
InitPlugin(Integer(Application), Integer(Screen));
Procedura(baza_danych)
DonePlugin;
end;

 FreeLibrary(LibHandle);

end
else
Application.MessageBox(PChar('Nie znaleziono biblioteki: '+ ExtractFilePath(Application.ExeName) + 'DLL\Intro.dll'),'Błąd',mb_IconError);

end;

0

ps. Dodam iz nie mam zadnego zdarzenia na onCreate.... i w ogóle nie wiem o co biega. O ile sie nie myle... zrobiłem wszystko dokładnie tak jak napisał Miskiekd - zresztą każdy może to zobaczyć, a mimo wszystko przy tworzeniu formy wywala błąd. Może powinienem jakoś inaczej ją stworzyć ? :| Ale jezeli zaremuje linie przypisującą screeny to aplikacja działa poprawnie, z tymże okna funckjonują tak jak napisałem wczesniej..... :(

0

TProcedura = procedure(abaza:shortstring) : TModalResult; StdCall;

Coś mi się wydaje, że ściemniasz - przecież to się nawet nie kąpiluje.

Ps. po poprawieniu kodu (kilka błędów) skąpilowało się i normalnie zadziałało.

Tu masz działający kod + exe i dll

0

Sorry.. rzeczywiscie tam byl błąd.. wczesniej to byla funkcja .. która zmieniłem w nocy na procedurke, rano nie kompilowałem tego.. tylko walnąłem na forum.. i tak zostało..... a tak ogólnie nie ściemniam :P ;) Dzięki za kod... sprawdze [browar]

0

ja mam D7 Ent
A spróbuj skąpilować u siebie tylko exe, a dllke weź tą skąpilowana u mnie i na odwrót, tzn mój exe i Twoją dllkę

0

No właśnie coś w tym stylu kombinuje i działa.. Cóż.. postaram się jakoś pokombinować.. i zobacze co wyjdzie....

EDIT: Działa. Porównałem dokładnie cały kod programu. Jedyna różnica - i jak się okazało cały problem polegał na pewnym unicie który był w "uses".. a nie był używany. Troche dziwne.. bo raczej nie powinno to powodować takich tragicznych błędów (tak mi sie wydaje)... sam w sumie jestem na siebie zły, za takie niedopatrzenie :-/

Ogólnie wielkie DZIĘKI MiskiekD. [browar] [browar] [browar]

0

Kolejny problem z tymi nieszczęsnymi dll'kami :[

Skonstruowałem dll'ke w podany wyżej sposób z jednym unitem Forma_Dll1.. dokonuje w niej pewnych działań.. wszystko pięknie chodzi. Następnie... dodaje pusty unit Forma_Dll2 i nowy przycisk na forma_Dll1 tworzący forme drugą.... odpalam.. klikam na przycisk.. pokazuje sie czysta forma - OK. No to teraz dalej....

Na formie drugiej proste przypisanie label1.caption := forma_dll1.label1.caption; Dodaje forma_dll1 do uses... odpalam.. klikam na przycisk.. I co? Wywala acces violation.... za każdym razem... gdy w jakikolwiek sposob na forma_Dll2... chce sie odwołać do Forma_Dll1. Chociaż nie przekazuje stringów, dodałem Sharemem do uses.... i nadal to samo. Jakakolwiek proba odczytania danych z innej niż obecnie aktywna forma... kończy się błędem dostępu.... :[ Any ideas o co biega? (czego może mi brakować w applikacji/dll'ce/unicie ?)

0

nie bardzo rozumiem, na czym się wywala. forma_dll1 i forma_dll2 są w dllce? Pokazał byś kod zarówno form1 jak i form2 (najlepiej cały)

0

Dokładnie. Forma1 (frmSQL) oraz Forma2(frmKolumny) są w DLL'ce. Wszystko ładnie chodzi... ale jak chce przepisać wartość labela z formy1 do labela na formie 2 wywala błąd.

Cały kod można ściągnąć z: http://xthost.info/calavero/dll.rar

Jako że kod jest raczej prosty.. to przypuszczam iż mam coś za dużo w "uses" co powoduje błąd, albo mi czegoś brakuje w kodzie...

Będe wdzięczny za podpowiedzi...
Pozdrawiam!
Cal

0

zauważ, że tu

procedure SQL_dll; StdCall;
begin
 with TfrmSQL.Create(Application) do
   begin
    ShowModal;
    Free;
   end;
end;

Tworzysz formę TfrmSQL, ale nie przepisujesz jej wskaźnika do żadnej zmiennej, natomiast tu

label1.Caption := frmsql.Label1.Caption;

odwołujesz się do zmiennej frmsql, która na dobra sprawę wskazuje w kosmos lub jest nilem.
Wystarczy, że zamienisz kod tak:

procedure SQL_dll; stdcall;
begin
  frmSQL := TfrmSQL.Create(Application);
  with frmSQL do
  begin
    ShowModal;
    Free;
  end;
end;

i już działa. Mam nadzieję, że wiesz dlaczego.

0

Dzięki. Tak.. wiem. Wychodzi mój brak doświadczenia w dynamicznym tworzeniu komponentów :-/

1 użytkowników online, w tym zalogowanych: 0, gości: 1