Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как создать OnClick в DLL для добавленной кнопки? 
V
    Опции темы
Shtorm
  Дата 26.2.2009, 01:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 23.2.2009
Где: Таганрог

Репутация: нет
Всего: 1



Разрабатываю приложение, и делаю так что бы большая часть функций приложения загружалась из библиотек. В общем делаю приложение, которое может загружать плагины. Создал COM Object, который обеспечивает доступ ко всем объектам находящимся на основной форме, для этого делаю ссылки на Handle и Pointer объектов.(Для каждого объекта свой Handle и свой Pointer). В библиотеках, которые делаю, экспартирую функцию LoadPlug_in, которая вызывается при загрузке библиотеки основным приложением.
В библиотеки подключаю таблицу интерфейса основного приложения. После чего вызываю конструктор для интерфейса и зная Pointer MainMenu присваиваиваю его переменной.(см. код ниже) Создаю несколько новых пунктов меню и назначаю OnClick для этих итемов. Всё работает замечательно, но обработчик OnClick после загрузки библиотеки не работает.
Как это исправить? 
Вот например если создать в этой же библиотеки панель (TPanel) на форме и назначить обработчик OnClick, то для панели (а также и кнопку на созданную панель добавлял, которая так же реагировала на OnClick) всё замечательно. Я так понима для панели обработчик событий сохраняется то ли в потоке, то ли другой механизм, а если создать самостоятельную кнопу, то обработчик не сохраняется, как это сделать, может знает кто-то, подскажите. 
Вот мой пример, код не отимизировал, так как хочу сначала разобраться с этим вопросом
Код

type   
  ClickEvent = class(TPanel) // Это явно нужно реализовать иначе  
    procedure Btn_Click(Sender: TObject);   
  end;   
  
procedure ClickEvent.Btn_Click(Sender: TObject);   
begin   
  MessageBox(0,'Item Click','Menu_Click',0);   
end;   
  
function LoadPlug_in:WordBool;   
Var   
  ISh: IShtilMain; // Интерфейс основного приложения   
  MenuIt: TMenu;   
  mI,mI1,mI2: TMenuItem;   
  RClick: ClickEvent;   
begin   
  try   
    ISh := CoShtilMain.Create;   
    MenuIt := ISh.Menu_MainPointer;   
  
    mI:=TMenuItem.Create(MenuIt);   
    mI.Caption:='Данные';   
  
    mI1:=TMenuItem.Create(MenuIt);   
    mI1.Caption:='Открыть';   
  
    mI2:=TMenuItem.Create(MenuIt);   
    mI2.Caption:='Сохранить';   
  
    RClick := ClickEvent.Create(nil);   
    mI1.OnClick := RClick.Btn_Click;   
    mI2.OnClick := RClick.Btn_Click;   
  
    mI.Insert(0,mI1);   
    mI.Insert(1,mI2);   
    MenuIt.Items.Add(mI);   
    Result := True;   
  except   
    Result := False;   
  end;   
end;   
 
Библиотеку можно реализовать и в виде COM, но я пока не далёк в этой технологии, месяц как изучаю её, поэтому не знаю как это сделать. И хотел бы посмотреть пример такой реализации.  smile 
PM MAIL ICQ   Вверх
Alexeis
Дата 26.2.2009, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Shtorm, объекты Application в Dll и приложении объединял уже? Очередь сообщений крутится в приложении, а Dll ничего об этом не знает. Нужно перво наперво передать объект Application из программы в Dll и там присвоить его, тогда очередь сообщений будет для них общая.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
MetalFan
Дата 26.2.2009, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



я думаю не стоит "мешать" в кучу компоненты VCL, созданные в dll и в приложении... либо использовать пакеты (bpl) и общий менеджер памяти, либо полностью абстрагированные интерфейсы.
з.ы. а присвоением объекта TApplication из приложения в dll дело не поправишь имхо

Это сообщение отредактировал(а) MetalFan - 26.2.2009, 10:41


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Alexeis
Дата 26.2.2009, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



MetalFan, конечно остаются проблемы дублирования реализаций классов и присваивание объектов TApplication является своеобразным хаком, но это иногда работает. Я пробовал более изящное решение, загрузку Dll в новом потоке, со своей собственной очередью сообщений. Т.е. изолировать 2 набора VCL. При этом Dll функционирует как отдельное приложение но с общим адресным пространством, однако при винда создает как бы 2 главных окна приложения, и каждое из них помещает свою кнопку на таскбар. Мне кажется что это также не совсем удобно.
  Вариант с bpl тоже весьма неудобен, потому что все классы, которые используются в обоих исполняемых модулях должны подключаться при помощи общих bpl, объем которых весьма велик.
  Путь интерфейсов тоже мало согласуется с VCL, потому что в библиотеке нет компонентов, которые имели бы интерфейсы содержащие большую часть public/published свойств и методов. Фактически такое программирование сводит на нет все преимущества Delphi.  

  Фактически приемлемым результатом могут быть только 2 пути.
1) Отказаться от применения VCL в Dll и от передачи объектов. 
2) Отказаться от взаимодействия VCL в Dll и VCL в приложении или свести это взаимодействие к минимуму (объединив очереди сообщений для работы механизма сообщений + объедение куч).


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Shtorm
Дата 26.2.2009, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 23.2.2009
Где: Таганрог

Репутация: нет
Всего: 1



Цитата(Alexeis @  26.2.2009,  10:25 Найти цитируемый пост)
Shtorm, объекты Application в Dll и приложении объединял уже? 

Нет этого я не делал, как это можно реализовать? Использовать ShareMem? Или что-то другое?
Да и инетересно почему например при создания OnClick вот примерчик (чуть и зменил тот что выше)
Код

type
  TBtn = class(TButton)
    procedure Btn_Click(Sender :TObject);
  end;


procedure TBtn.Btn_Click(Sender :TObject);
begin
  MessageBox(0,'Кнопка нажата',nil,0);
end;
function LoadPlug_in:WordBool;
Var
  ISh: IShtilMain;
  Pan_Add: TPanel;
  Btn_Pan: TButton;
  BtnDo: TBtn;
begin
  try
    ISh := CoShtilMain.Create;
    Pan_Add := TPanel.Create(nil);
    Pan_Add.ParentWindow := ISh.Pan_MainBottomHandle;//Handle панели расоложенной внизу основной формы
    Btn_Pan := TButton.Create(Pan_Add);
    Btn_Pan.Parent := Pan_Add;
    Btn_Pan.Caption := 'Test';
    BtnDo := TBtn.Create(nil);
    Btn_Pan.OnClick := BtnDo.Btn_Click;
    Result := True;
  except
    Result := False;
  end;
end;

Работает как нужно. Думаю понятно, что делаю, создаю панель, на панели основного приложения, на созданной панели добавляю кнопку и назначаю обработчик Btn_Pan.OnClick := BtnDo.Btn_Click; 
Какой тогда механизм использует ТPanel для этих дел и почему работает? 
Цитата(Alexeis @  26.2.2009,  11:17 Найти цитируемый пост)
2) Отказаться от взаимодействия VCL в Dll и VCL в приложении или свести это взаимодействие к минимуму (объединив очереди сообщений для работы механизма сообщений + объедение куч).
 А как объединить очереди сообщений? Или это и есть момент с использованием общего менджера памяти?

PM MAIL ICQ   Вверх
Alexeis
Дата 26.2.2009, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(Shtorm @  26.2.2009,  11:07 Найти цитируемый пост)
 А как объединить очереди сообщений? Или это и есть момент с использованием общего менджера памяти?

  Сейчас проверил на простом примере, и надо сказать что сообщения и так передаются в Dll, мне кажется что это делает стандартная оконная функция главного окна приложения. В общем выходит что стандартный механизм работает правильно в сочетании с Формами в Dll.

Цитата(Shtorm @  26.2.2009,  00:01 Найти цитируемый пост)
В библиотеки подключаю таблицу интерфейса основного приложения. После чего вызываю конструктор для интерфейса и зная Pointer MainMenu присваиваиваю его переменной.(см. код ниже) Создаю несколько новых пунктов меню и назначаю OnClick для этих итемов. Всё работает замечательно, но обработчик OnClick после загрузки библиотеки не работает.
Как это исправить? 

  Все, кажется понял в чем прикол.

Скорее всего пункты меню создаются в Dll примерно таким образом

Код

procedure CreateMenuItem();
var
  newItem : TMenuItem;
begin
  newItem := TMenuItem.Create(MainMenu1);
  newItem.Caption := 'newItem';
  MainMenu1.Items.Add(newItem);
end;


  Т.е. имеем стандартную схему конфликта 2х различных реализаций VCL или Dll и приложения.

    Для правильного решения такой задачи лучше перенести код CreateMenuItem из Dll в приложение, тогда будет создан правильный экземпляр TMenuItem класса расположенного в приложении. Тот что создается в Dll (TMenuItem) для MainMenu1 из главного приложения является как бы не родным. 

  Короче совет остается тем же не смешивать объекты из Dll и программы. При их смешивании результат будет непредсказуемым.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Shtorm
Дата 26.2.2009, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 23.2.2009
Где: Таганрог

Репутация: нет
Всего: 1



Таким образом, лучше например предусмотреть в приложение создание объектов, и вызывать эту функцию в dll например с координатами обьекта. Ну это для обычных Butoon а для меню тоже написать свою функцию. И например что бы эта функция возвращала Handle или Pointer созданного объекта, после чего назначить ему обработчик.
PM MAIL ICQ   Вверх
Shtorm
Дата 26.2.2009, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 23.2.2009
Где: Таганрог

Репутация: нет
Всего: 1



Да, действительно, если создавать объекты внутри приложения вызывая для этого функцию и возвращая Pointer созданного объекта, всё работает без проблем. Спасибо 
Alexeis, первоначально я хотел создавать так объекты, но думал пускай об этом заботятся те, кто пишет под мою прогу дополнения. Прийдётся упростить немного жизнь им  smile Ещё раз спасибо за помощь 
Alexeis, и MetalFan
Приведу примерчик свой, что б если у кого возникла такая проблема мог разобраться

Код основого приложения:

Код

unit uMain;
//...
type
  TF_Main = class(TForm)
  public
    { Public declarations }
    function Add_Btn(TopB, LeftB: LongInt; HandlePan: OLE_HANDLE): Pointer;stdcall;
  end;

function TF_Main.Add_Btn(TopB, LeftB: LongInt; HandlePan: OLE_HANDLE): Pointer;
var
  Btn_Add: TButton;
begin
  Btn_Add := TButton.Create(nil);
  Btn_Add.Caption := 'Test';
  Btn_Add.Top := TopB;
  Btn_Add.Left:= LeftB;
  Btn_Add.ParentWindow := HandlePan;
  Result := Btn_Add;
end;


Код интерфейса (так как я работаю через интерфейсы и СОМ является надстройкой над моей прогой) получаем следующее:
Код

uses
  Windows, ActiveX, Classes, ComObj, Shtil_TLB, StdVcl, uMain;
type
  TShtilMain = class(TTypedComObject, IShtilMain)
  protected
//...
  function Add_Btn(Top, Left: Integer; Handle: OLE_HANDLE): Pointer; stdcall;
  end;
//...
function TShtilMain.Add_Btn(Top, Left: Integer; Handle: OLE_HANDLE): Pointer;
begin
 Result := F_Main.Add_Btn(Top,Left,Handle)
end;


Ну и код библиотечки(думаю всем известно как загружать библиотеки и вызывать экспортируемую функцию)
Код

library TestAdd;

uses
  ComServ,
  TestAdd_TLB in 'TestAdd_TLB.pas',
  uITestAdd in 'uITestAdd.pas' {TestCo: CoClass},
  Shtil_TLB, Windows, StdCtrls;
type
  TBtnC = class(TButton)
    procedure ClickMe(Sender: TObject);
  end;
procedure TBtnC.ClickMe(Sender: TObject);
begin
  MessageBox(0,'qwerty',nil,0)
end;
function LoadPlug_in:WordBool;
Var
  ISh: IShtilMain;
  Btn: TButton;
  BtnAct: TBtnC;
begin
  BtnAct := TBtnC.Create(nil);
  ISh := CoShtilMain.Create;
  Btn := ISh.Add_Btn(0,0,ISh.Pan_MainBottomHandle);
  Btn.OnClick := BtnAct.ClickMe;
  Result := True;
end;
exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer,
  LoadPlug_in;

{$R *.TLB}

{$R *.RES}

begin
end.


Но один вопрос я так и не понял, почему же при создании панели TPanel и назначение ей обработчика OnClick (эта кухня вся в библиотеки происходит) всё работает нормально и не приводит к конфликтам?
PM MAIL ICQ   Вверх
Alexeis
Дата 26.2.2009, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(Shtorm @  26.2.2009,  14:20 Найти цитируемый пост)
И например что бы эта функция возвращала Handle или Pointer созданного объекта, после чего назначить ему обработчик.

  Обработчик лучше передать сразу в функцию создания. Единственное, что можно делать с полученный указателем, так это хранить его, для того чтобы потом уничтожить кнопку, если предусмотрена досрочная выгрузка плагина, если же нет, то объект прекрасно уничтожит объект (тот чей указатель передан в конструктор). Тогда и хранить ничего не нада. Можно хранить дескриптор. Он нужен в случае если захочется проделать некоторые операции при помощи WinApi функций, но это тоже весьма сомнительные операции. VCL компоненты не всегда адекватно реагируют на прямое изменение параметров api функциями. 
  Трудно назвать это удобной работой. 

  Для нормальной работы плагина придется либо передать здоровенную запись с внушительным количеством указателей на все необходимые внутренние функции или написать несколько объектов посредников и передавать плагину их интерфейсы. Это аналогично технологии COM. 

Цитата(Shtorm @  26.2.2009,  00:01 Найти цитируемый пост)
Создал COM Object, который обеспечивает доступ ко всем объектам находящимся на основной форме, для этого делаю ссылки на Handle и Pointer объектов.

  Можно возвращать только указатели COM объектов (а не простых VCL). В этом и состоит неудобство VCL при программировании плагинов Dll.

Кстати если вопрос размера остро не стоит, может действительно задуматься о bpl? Для большого проекта 10-15Мб пакетов не такая уж внушительная цифра

Добавлено через 7 минут и 36 секунд
Цитата(Shtorm @  26.2.2009,  14:45 Найти цитируемый пост)
Но один вопрос я так и не понял, почему же при создании панели TPanel и назначение ей обработчика OnClick (эта кухня вся в библиотеки происходит) всё работает нормально и не приводит к конфликтам? 

  При такой работе вероятность успеха 50/50. В случае с панелькой внутренние механизмы не были затронуты по этому и сработало.

  Приведенный пример также использует недокументированные возможности, потому нет гарантии что он будет работать. Где-то в разделе уже проскакивал еще один "хакерский" прием позволяющий стыковать Dll и Exe на VCL, там еще лучше были учтены внутренние механизмы работы. Но все это не переносимо, особенно если dll и exe будет писаться на разных версиях Delphi.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Shtorm
Дата 26.2.2009, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 23.2.2009
Где: Таганрог

Репутация: нет
Всего: 1



Я так понимаю, что бы подружить Dll и exe лучше использовать bpl. 
Цитата(Alexeis @  26.2.2009,  15:48 Найти цитируемый пост)
Кстати если вопрос размера остро не стоит, может действительно задуматься о bpl?
 вопрос размера не ставился. Только я с bpl никогда не работал и не знаю что это, Alexeis, можешь подсказать с чего начать или где почитать об этом?
Цитата(Alexeis @  26.2.2009,  15:48 Найти цитируемый пост)
написать несколько объектов посредников и передавать плагину их интерфейсы. Это аналогично технологии COM.

У меня стояла изначально задача подружить  VCL с СОМ, решит ли этот вопрос использование bpl?  smile 
PM MAIL ICQ   Вверх
Alexeis
Дата 26.2.2009, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(Shtorm @  26.2.2009,  19:20 Найти цитируемый пост)
У меня стояла изначально задача подружить  VCL с СОМ, решит ли этот вопрос использование bpl? 

  При использовании bpl необходимость в COM вообще отпадает. bpl представляет собой набор модулей. Эти модули можно использовать как в приложении так и в плагине, главное то что реализации классов VCL расположены в них. Т.е. и Dll и плагин будут создавать полностью совместимые объекты.
  Фактически bpl представляет собой Dll, с которой Delphi умеет правильно работать. Она экспортирует не только функции но и сами VCL классы.
  Кстати у нас на форуме есть хороший пример такой работы см. http://forum.vingrad.ru/forum/act-ST/f-84/t-157316.html


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Shtorm
Дата 26.2.2009, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 23.2.2009
Где: Таганрог

Репутация: нет
Всего: 1



Спасибо Alexeis, я поговорю ещё с парнишкой который хотел реализовать всё с использованием COM, но думаю прийдётся всё ж возится с СОМ. Просто дело в том, что он хочет создавать плагины на разных языках и bpl я так понимаю это вещь чисто под делфу.
PM MAIL ICQ   Вверх
Alexeis
Дата 26.2.2009, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(Shtorm @  26.2.2009,  21:22 Найти цитируемый пост)
Просто дело в том, что он хочет создавать плагины на разных языках и bpl я так понимаю это вещь чисто под делфу. 

  Но и VCL считай тоже только под Delphi. Если нужны другие языки тогда нужно все взаимодействия делать только по средствам COM и функций.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Shtorm
Дата 26.2.2009, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 23.2.2009
Где: Таганрог

Репутация: нет
Всего: 1



Так и прийдётся делать,
Цитата(Alexeis @  26.2.2009,  15:48 Найти цитируемый пост)
написать несколько объектов посредников и передавать плагину их интерфейсы. Это аналогично технологии COM. 

Вот ещё момент
Цитата(Alexeis @  26.2.2009,  15:48 Найти цитируемый пост)
Можно возвращать только указатели COM объектов (а не простых VCL). В этом и состоит неудобство VCL при программировании плагинов Dll.

Самый простой пример этого можно? smile  , или как передавать указатель, и какой тип данных необходимо выбрать?
Это например вот так 
Код

function F_MainSet: Pointer; // Какой тип данных тут нужен?
begin
  Result := @F_Main;
end;


PM MAIL ICQ   Вверх
Alexeis
Дата 27.2.2009, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Shtorm, все верно Pointer это указатель, хотя насколько я помню, при работе с COM, COM объект создается функцией, а передается даже не указатель на COM объект, а один из его интерфейсов. Но можно и указатель. Если указатель, то механизм примерно такой.
  При установке прога регистрирует свой СОМ объект, а плагин будет делать примерно так
Код

var
  obj : Variant;
Begin
  obj := CreateComObject(<NAME>);

или 

  obj := CreateComObject(<GUID>);

  obj.foo();

в зависимости от того как регистрировался по имени или по GUID


После этого можно вызывать методы. Но такой способ не очень быстрый, потому что указатель на foo будет получен через дополнительный сервис по ее имени. 
  Для создания интерфейса производительность не играет большой роли, потому можно и так. Но для быстрых вызовов лучше получить интерфейс. С ним работа будет значительно быстрее.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1231 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.