Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.01.2008, 20:38   #1
darkstarx
Пользователь
 
Регистрация: 20.01.2008
Сообщений: 24
Вопрос Создание плагинов на DLL: SharedMemory

Такой вот вопросик.
Что нужно написать в коде программы, чтобы она нашла все имеющиеся у нее в каталоге DLL`ки и "забрала" у них их внутрении меню, включив эти меню в свое главное меню?

Точнее что написать - второй вопрос, а первый - как организовать между программой и динамически подгружаемой DLL при инициализации последней обмен ссылками на компоненты, например, чтобы DLL-ка, приняв указатель на главное меню программы, смогла бы в этом меню накрутить что душе библиотечной угодно, например MainMenu.Items.Insert(0, Menu_from_DLL.Items)

Использую тип вызова процедуры инициализации DLL-ки register и включаю модуль ShareMem в библиотеку и программу - вроди бы без ошибок на первый взгляд, НО! невероятным образом обработчики событий OnClick изменяются следующим образом:
1. Первым MenuItem вставляется меню из DLL
2. Существующие в меню программы двигаются вправо
3. Обработчики первого (точнее нулевого) MenuItem работают корректно
4. Обработчики следующего за ни - копируются из предыдущего (то есть библиотечного)
5. ...и это при том, что Sender остается из меню библиотеки, а не из того MenuItem (программы), который вызвал процедуру-обработчик

Помогите справиться с этим чудом, плз. Или может быть есть менее извращенный способ написания плагинов? Спасибо.
darkstarx вне форума Ответить с цитированием
Старый 20.01.2008, 21:22   #2
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Странно тут Вы все сделали Я лично в этом не профи НО кто Вам мешает описать структуры record с нужными переменными например типа такого

Код:
PItemMenu = ^TItemMenu;
TItemMenu = packed record
  Text: String;
  ImageIndex: Integer;
  Index: Integer;
  // ну еще что необходимое для Вашей программы
  OnClick: Pointer;
  // можно сделать без списка - на основе узлов т.е.
  PrevItem: PItemMenu;
  NextItem: PItemMenu;
end;
А потом типа функции которая возвращала бы по индексу PItemMenu, а т.к. библиотека запущена то и все работат будет

ну пример поиска по индексу функции в длл на экспорт
Код:
// ваш список пунктов меню
var
  FirstItem: PItemMenu;

...


function GetItemMenu(Index: Integer): PItemMenu; {export; stdcall;}
var
  p: PItemMenu;
begin
  p := FirstItem;
  while (p <> NIL) do
  begin
    if (p^.Index = Index) then
      Break;
    p := p^.NextItem;
  end;
  Result := p;
end;
Если не ошибаюсь система такова При инициализации библиотеки Вы заполняете узлы FirstItem....

да и еще таким образом в директиве uses у вас будет Windows ну может еще что соответственно размер длл довольно таки маленьким.
BOBAH13 вне форума Ответить с цитированием
Старый 20.01.2008, 21:32   #3
darkstarx
Пользователь
 
Регистрация: 20.01.2008
Сообщений: 24
Восклицание

Ммм, наверно я не совсем точно проблему описал.
Дело не в том, чтобы организовать при помощи DLL механизм изменения главного меню программы, а в принципе его (меню) один раз изменить при инициадизации библиотеки и всё.

Кстати TMenuItem - это не структура, а класс, причем уже существующий в VCL, это те самые пункты, которые мы видим в меню, открывая его (Open File, Edit, Cut, Paste...)

Вот пример того, что мне нужно:

Код:
library TestDLL;

uses
  ShareMem, Forms, SysUtils, Classes, Menus,
  DataModuleUnit in 'DataModuleUnit.pas' {frmDataModule: TDataModule};

{$R *.res}

var
  frmMain: TForm;
  frmMenu: TMenu;

function InitDLL(MainForm: Pointer; MainMenu: Pointer): Boolean; register;
begin
  Result:=false;
  frmMain:=TForm(MainForm);
  frmMenu:=TMenu(MainMenu);
  if Assigned(frmMain) then
    if Assigned(MainMenu) then
      Result:=true;
  if not Result then exit;
  frmDataModule:=TfrmDataModule.Create(Application);

  frmDataModule.MainMenu.Items.Caption:='AnalysisModule';
  frmMenu.Items.Insert(0, frmDataModule.MainMenu.Items);
end;

function DeallocateDLL: Boolean; register; 
begin
  Result:=false;
  if Assigned(frmMain) then
    if Assigned(frmMain.Menu) then begin
      frmMenu.Items.Remove(frmDataModule.MainMenu.Items);
      Result:=true;
    end;
  frmDataModule.Free;
end;

exports
  InitDLL,
  DeallocateDLL;

begin
end.
darkstarx вне форума Ответить с цитированием
Старый 20.01.2008, 21:41   #4
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Я Вам не помогу извените... я предпочитаю подход который я описал Выше, для меня в нем все более понятно. А все добавления меню делать в программе...
BOBAH13 вне форума Ответить с цитированием
Старый 20.01.2008, 21:56   #5
darkstarx
Пользователь
 
Регистрация: 20.01.2008
Сообщений: 24
По умолчанию

а что у Вас за подход - я тоже Вас не понял) Вы предложили, чтобы DLL формировала некоторую структуру, по которой программа будет редактировать меню. Это хорошо и понятно. Но как быть с обработчиками событий нажатия OnClick каждого из созданных программой пунктов меню по структуре из DLL? только если в структуру еще включить адрес на обработчика, прописанного в DLL - это трудоемкая работка. Желательно, чтобы в DLL мне нужно было бы всего лишь создать компонент TMainMenu например на DataModul`e и создать в нем всю нужную структуру пунктов и назначить для них обработку и написать для них код автоматизированными средствами Delphi, а не вручную все это делать (потом много придется писать подобных DLL-ок и часто изменять меню в них - нужно чтобы бало как можно проще, без большого кода)
darkstarx вне форума Ответить с цитированием
Старый 20.01.2008, 22:31   #6
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Пишите процедуру обработки пункту типа

Код:
procedure OnClickFirstItemMenu(Sender: TObject);
begin
end;
в одном из пунктов в структуре я описал переменную OnClick: Pointer;
следовательно OnClick := @OnClickFirstItemMenu;
отсюда и отталкивайтесь.

А потом в форме вы получаете PItemMenu и чтобы обратиться к обработчику делаете типа TMenuItem.OnClick := TNotifyEvent(PItemMenu^.OnClick); вроде так или даже без TNotifyEvent.

Последний раз редактировалось BOBAH13; 20.01.2008 в 23:55.
BOBAH13 вне форума Ответить с цитированием
Старый 20.01.2008, 22:49   #7
darkstarx
Пользователь
 
Регистрация: 20.01.2008
Сообщений: 24
По умолчанию

Ах ну да, прошу пращения, не заметил OnClick в структуре.
...
MenuItem.OnClick:=TNotifyEvent(PMen uItem^.OnClick)

Значит придется в DLL писать нечто в роде построителя этой самой структуры по существующему компоненту TMainMenu, которую нужно отдавать приложению при инициализации DLL... неужели нельзя какой-нибудь Assign использовать...

лень писать

Благодарю за помощь
darkstarx вне форума Ответить с цитированием
Старый 20.01.2008, 23:45   #8
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

В том то и дело что лень писать Вы же программист. Наша суть в писанине Я бы так все реализовал + это размер dll будет ну киллобайт 15 )) а с VCL ух... кто его знает
BOBAH13 вне форума Ответить с цитированием
Старый 21.01.2008, 01:28   #9
darkstarx
Пользователь
 
Регистрация: 20.01.2008
Сообщений: 24
По умолчанию

Да VCL все равно придется использовать, там ведь меню нужно только для того, чтобы вызывать остальные функции обработки данных, уже реально большие функции, формы, компоненты наборы данных и т.п... так что бог уж с ним размером
darkstarx вне форума Ответить с цитированием
Старый 21.01.2008, 08:52   #10
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Я имел ввиду передать данные в программу на уровне Api и Pascal А в проге уже эти данные читать и вносить в меню... Вот что я имел ввиду.
А в проге в цикле через длл узнаем кол-во пунктов в длл и
for i:= 0 to countitemfromdll do
begin
TMenuItem := TMenuItem.Create(NIL);
ну тут свой-ва присваиваем из PItemMenu
тут уже
Menu.AddItem .. или как там, лень лезть смотреть с утра.
end

Вот и все.... после в длл можно ту структуру пунктов разрушить, и соответственно больше к ней не обращаться или сделать типа инициализации структуры и разрущения ее. Но указатели на обработки всеравно уже остануться и на них ( в длл ) будет ссылаться программа.
Что Вас именно еще интерисует ? Если Вы конкретно еще не поняли могу попробывать сделать пример даже, если не буду занят.
BOBAH13 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание вкладки. фЁдОр Общие вопросы Delphi 10 11.02.2008 16:27
Создание dll John_chek Общие вопросы Delphi 3 24.09.2007 14:26
Помогите с разработкой приложения с поддержкой плагинов. krik Общие вопросы Delphi 3 17.06.2007 13:40
Написание программ или плагинов для тюнера Behold TV СТРАННИК Общие вопросы Delphi 0 29.01.2007 09:54