Obsługa MainMenu programu z wtyczki DLL

0

Witam.
Mam pewien problem, który próbowałem rozwiązać przez cały dzień i mi się to nie udało, więc spróbuję zadać tutaj pytanie:
Mam sobie program, który ma obsługiwać wtyczki. Wywołuje on procedurę z DLL'ka o następującej składni:

InitializePlugin(CocpitForm: TForm; MainMenu: TMainMenu)

, przy czym CocpitForm jest dodatkową formatką programu głównego, a MainMenu - menu główne na podstawowej formatce. Teraz próbowałem zrobić coś takiego:

procedure InitializePlugin(CocpitForm: TForm; MainMenu: TMainMenu); stdcall;
var
  MenuItem: TMenuItem;
begin
  MessageBox(0, 'Witaj! Jestem procedurą z wtyczki test.dll!', 'Witam!', MB_OK);
  MenuItem:=TMenuItem.Create(MainMenu.Owner);
  MenuItem.Caption:='Opcja z Pluginu';
  MainMenu.Items.Add(MenuItem);
  end;

I teraz przy uruchomieniu programu głównego powinno wyświetlić się okienko z informacją (działa) i dodać opcja w Menu (to już nie działa). Dlaczego opcja się nie dodaje? Czy coś przegapiłem? I mam jeszcze jedno pytanko. Jak w takiej sytuacji w tym DLL'ku stworzyć procedurę obsługi takiego MenuItem'a? Próbowałem:

procedure MenuItemClick(Sender: TObject);
begin
  ShowMessage('Kliknięty');
  end;
{...}
  MenuItem.OnClick:=MenuItemClick;

Lecz w linijce "MenuItem.OnClick:=MenuItemClick;" wywala mi następujący błąd:"[Error] test.dpr(32): Incompatible types: 'method pointer and regular procedure'" w/g helpa Delphi powinna ta procedurka wyglądać następująco:

procedure TForm1.MenuItemClick(Sender: TObject);
begin
  ShowMessage('Kliknięty');
  end;

Ale jak ja mam to zrobić, skoro nie mam dostępu do Formy?

0

Ta procedura musi być częścią dowolnego obiektu.

0

No dobrze, tylko że to mi niewiele da w tej chwili. Już mi się udało z tym podwiązaniem, ale nie zmienia to faktu, że nie mogę z jakiegoś powodu odwołać się do przekazywanych w ramach parametrów procedury obiektów. Zawsze mi się w tym momencie wywala :/. Dlaczego?

0

Generalnie Delphi ma przewidziane wsparcie dla programow modulowych w postaci opcji kompilacji z pakietami (Buid with runtime packages). Chodzi o to, zeby kazda instancja korzystala z tego samego RTTI. Po wlaczeniu tej opcji w ustwieniach kompilatora exec zostanie wygenerowany bardzo maly (dllka tez) a czesc wspolna, czyli wszystkie unity delphinowe (windows,sysutils,forms,system, i milion innych) beda w plikach *.bpl, ktore nalezy dolaczac do instalki wersji dystrybucyjnej softu.
To zaleca papa Borland. W praktyce dziala wspolpraca z dllka standardowymi, tylko istotne jest kilka drobiazgow:

  • prawidlowe przekazywanie parametrow (w dllu i execu takie samo)
  • przekazanie wartosci zmiennej Application do dllki
  • stosowanie pcharow w miejsce stringow.
0

Nie no, nie mogę... Drugi dzień nad tym siedzę i nie mogę dojść :/
Mam coś takiego:
W programie głównym:

var InitializePlugin: Procedure(CocpitForm: TCocpitForm; MainForm: TMainForm; ParentApplication: TApplication);
{...}
      MainForm.Plugins[J] := LoadLibrary(PChar(ExtractFilePath(Application.ExeName)+'Plugins'+TMPPluginsString+'.dll')); // laduj biblioteke
      try
        @InitializePlugin:= GetProcAddress(MainForm.Plugins[J], 'InitializePlugin');
        if not (@InitializePlugin = nil) then InitializePlugin(CocpitForm, MainForm, Application);
      except
//        ShowMessage('Błąd podczas próby inicjalizacji wtyczki '+TMPPluginsString+'.dll!');
        end;

A w biblioteczce:

type TMethodContainer = Class(TComponent)
  procedure MenuItemClick(Sender: TObject);
  end;

var
  MethodContainer: TMethodContainer;
  Application: TApplication;

procedure TMethodContainer.MenuItemClick(Sender: TObject);
begin
  MessageBox(0, 'Witaj! Jestem procedurą z wtyczki test.dll! Kliknąłes w opcję menu.', 'Witam!', MB_OK);
  end;

procedure InitializePlugin(CocpitForm: TCocpitForm; MainForm: TMainForm; ParentApplication: TApplication); stdcall;
var
  MenuItem, PluginsMenu: TMenuItem;
begin
  Application:=ParentApplication;
  MessageBox(0, 'Witaj! Jestem procedurą z wtyczki test.dll!', 'Witam!', MB_OK);
  MessageBox(0, '1', 'Raport', MB_OK); //Wszystkie te Message Boxy to tylko po to, bym wiedział, kiedy się wywala...
  PluginsMenu:=MainForm.Menu.Items.Find('&Wtyczki'); // <-- I w tym miejscu nie działa
  MessageBox(0, '2', 'Raport', MB_OK);
  MenuItem:=TMenuItem.Create(MethodContainer);
  MessageBox(0, '3', 'Raport', MB_OK);
  MenuItem.Caption:='Opcja z Pluginu';
  MessageBox(0, '3.1', 'Raport', MB_OK);
  MenuItem.OnClick:=MethodContainer.MenuItemClick;
  MessageBox(0, '4', 'Raport', MB_OK);
  MessageBox(0, PChar(PluginsMenu.Parent.Find('&Plik').Name), 'Index', MB_OK);
  MessageBox(0, '4.1', 'Raport', MB_OK);
  PluginsMenu.Add(MenuItem);
  MessageBox(0, '5', 'Raport', MB_OK);
  MessageBox(0, PChar(IntToStr(PluginsMenu.IndexOf(MenuItem))), 'Index', MB_OK);
  end;

exports // eksportuj procedurę
InitializePlugin name 'InitializePlugin';

Próbowałem na najróżniejsze sposoby już i nic... :(

0

Konkretnie to powinno byc chyba:

Application.Handle := ParentApplication.Handle;

i co teraz?

0

A wiesz, że ja miałem opdobny problem z pluginami? Podobnie jak Ty kombinowałem, ale już miałem dosyć, więc sięgnąłem po pomoc, która jest na wyciągnięcie ręki -> http://www.torry.net/samples/samples/plugins/plugin.zip ;) Mi ten kodzik pomógł, a Tobie z pewnością też się przyda [cya] Pozdrawiam

0

Hmmm... Doszedłem do wniosku, że coś jest nietak z przekazywaniem parametrów. Dodałem do argumentów funkcji x:Integer, w wywołaniu podałem wartość 5, a we wtyczce dodałem ShowMessage, która ma na celu wyświetlenie tej wartości... Wyświetla '4713520'... Dlaczego? Może ktoś zna odpowiedź na to pytanie? :( Niestety w tym przykładzie jest to zorganizowane trochę inaczej, wtyczka tam ma mniejsze możliwości... Prawdopodobnie to nieprawidłowe przekazywanie argumentów ma również wpływ na to, że przekazywane są nieprawidłowe wskaźniki i, w związku z tym, wyskakują mi AccesViolationy... Co poradzić? Może ktoś spotkał się z takim problemem...

0

A deklarację w bibliotece masz z stdcall?

// Dopisane

Oopss... faktycznie ta funkcja, którą podałeś (ta z stdcall) była z biblioteki. Nie wiem, czemu mi się ubzdurało, że to deklaracja w programie :). Inaczej zapytałbym właśnie o bibliotekę :P. Ale dobrze, że cię to naprowadziło :).

0

[glowa] Jak ja mogłem być tak sprytny? W bibliotece... Oczywiście, że miałem, tak było w artykule Adama Boducha... Ale dlaczego nie wpadłem na pomysł, by w deklaracji procedury w programie to dodać? Nie było w przykładzie, nie pomyślałem o tym :/ [glowa] [glowa]. Wielkie dzięki!

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