Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Class already exists

29 views
Skip to first unread message

Del

unread,
Jun 17, 2008, 7:59:50 AM6/17/08
to
Доброе всем время суток.

Камрады, подскажите, если кто сталкивался:
Имеем 2 dll-ки, в них юзается Chart. Обе две вызываются из одного и того же
приложения. Если поработать сначала с одной, а потом тыркнуть другую, то
получает вот такое:

---------------------------
Application Error
---------------------------
Exception EFilerError in module rtl60.bpl at 000282E7.
A class named TChartAxisTitle already exists.

В каком порядке - неважно. Можно сначала вызвать a.dll, а потом - b.dll,
можно наоборот - ошибка выскакивает одна и та же.

Регистрация (по крайней мере - у меня в коде) TChartAxisTitle нигде не
происходит. Пробовал на всякие в initialization прописать
Classes.UnRegisterClass(TChartAxisTitle) - не помогло. Одна dll-ка моя,
вторая - сотрудника, пока добраться до исходников возможности нет :(

Подскажите, куда копать, plz

--
Шмырев А. А.

Del

unread,
Jun 17, 2008, 8:38:12 AM6/17/08
to
Del пишет:

> Камрады, подскажите, если кто сталкивался:
> Имеем 2 dll-ки, в них юзается Chart. Обе две вызываются из одного и того
> же приложения. Если поработать сначала с одной, а потом тыркнуть другую,
> то получает вот такое:

Вопрос в целом решен, в главном приложении не выгружалась ни одна, ни вторая
dll после окончания их использования. Hо все же, если кто встречался с таким,
подскажите - как такой косяк можно обойти по-другому?

--
Шмырев А. А.

Sergei Andreev

unread,
Jun 17, 2008, 10:09:20 AM6/17/08
to
D> Вопрос в целом решен, в главном приложении не выгружалась ни одна, ни
вторая
D> dll после окончания их использования. Hо все же, если кто встречался с
таким,
D> подскажите - как такой косяк можно обойти по-другому?
Дык это ваш с сотрудником косяк - именовать классы надо
по-разному, даже если они и не используются одновременно

P.S.
А вообще-то освобождать по мере ненадобности ресурсы,
занимаемые тобой, в т. ч. и выгружать библиотеки - это признак
хорошего тона. У меня вот, как наиболее яркий например, есть
программуля, у которой, по показаниям TaskManager, пиковое
потребление 100МБ, а рабочее - 25МБ (страртап у нее очень
громоздкий). Прикинь, если б мне стало впадлу освобождать
эту память...


Del

unread,
Jun 18, 2008, 1:00:54 AM6/18/08
to
Sergei Andreev пишет:

> D> Вопрос в целом решен, в главном приложении не выгружалась ни одна, ни
> вторая
> D> dll после окончания их использования. Hо все же, если кто встречался с
> таким,
> D> подскажите - как такой косяк можно обойти по-другому?
> Дык это ваш с сотрудником косяк - именовать классы надо
> по-разному, даже если они и не используются одновременно

TAxisChartTitle - это кусок стандартного Delph'ового чарта, чарт используется
и у меня, и у сотрудника. Куды бечь? :)

--
Шмырев А. А.

sl

unread,
Jun 18, 2008, 2:37:57 AM6/18/08
to
Wed Jun 18 2008 10:00, Del wrote to Sergei Andreev:

D> TAxisChartTitle - это кусок стандартного Delph'ового чарта, чарт
D> используется и у меня, и у сотрудника. Куды бечь? :)

Бечь от ДЛЛ в сторону run time packages. Это те же ДЛЛ, только специальным
образом оформленные. Как должно быть известно, в Дельфи все классы имеют
общего предка - TObject. Класс физически представляет собой некую структуру, в
которой хранятся таблицы виртуальных и динамических методов, published свойств
и куча прочей RTTI. Когда ты создаёшь обычную ДЛЛ, в которой описываются
(используются) классы, в этой ДЛЛ создаются структуры RTTI для каждого такого
класса (и всех их предков). Если приложение написано тоже на дельфи, то, при
явном использовании классов из этой ДЛЛ можно огрести кучу приколов, т.к.
TObject приложения и TObject ДЛЛ получаются два разных класса - адреса
структур RTTI разные.
Есть и другой выход: не передавать классы через границу ДЛЛ (программа и ДЛЛ
пользуются каждая своим набором), а использовать простые функции или
интерфейсы. Интерфейсы удобнее - те же классы, практически.

Если выберешь run time packages, совет: создай новый run time package и включи
в него все исходники стандартных компонент, которые используются программой и
твоими пакаджами (бывшими ДЛЛами), а программу и пакаджи к ней компилируй with
run time packages только этот пакадж. Это, во-первых, уменьшит количество
модулей, необходимых программе, а, во вторых, гарантирует от случайного
"цепляния" пакаджей дельфи, если она установлена (эти пакаджи могут быть от
другого сервис-пака или ещё какой глюк).

Alexander B. Bokovikov

unread,
Jun 18, 2008, 5:23:02 PM6/18/08
to
Hi, All,

Возникла непонятка на ровном месте. Имеем на форме две вложенные друг
в друга панели. Делаем простую функцию перевода координат (см.
процедуру TForm1.Panel2MouseMove() ниже). Вопреки ожиданиям получаем
неверные значения координат: должно быть (60, 70), а выдается (70,
80). При этом Label3 и Label2 показывают правильные значения.
Где что не так?

Это исходник:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure Panel2MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Panel2MouseMove(Sender: TObject; Shift: TShiftState;
X,
Y: Integer);
var
p : TPoint;
begin
p := Panel1.BoundsRect.TopLeft;
Label3.Caption := IntToStr(p.X) + ' ' + IntToStr(p.Y);
//
p := Panel2.BoundsRect.TopLeft;
Label2.Caption := IntToStr(p.X) + ' ' + IntToStr(p.Y);
//
p := GetParentForm(Panel2).ScreenToClient(Panel2.ClientToScreen(p));
Label1.Caption := IntToStr(p.X) + ' ' + IntToStr(p.Y);
end;

end.

Это DFM:

object Form1: TForm1
Left = 269
Top = 194
Width = 508
Height = 503
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 120
TextHeight = 16
object Label1: TLabel
Left = 225
Top = 20
Width = 3
Height = 16
end
object Label2: TLabel
Left = 5
Top = 20
Width = 3
Height = 16
end
object Label3: TLabel
Left = 110
Top = 20
Width = 3
Height = 16
end
object Panel1: TPanel
Left = 50
Top = 60
Width = 228
Height = 208
Caption = 'Panel1'
TabOrder = 0
OnMouseMove = Panel2MouseMove
object Panel2: TPanel
Left = 10
Top = 10
Width = 199
Height = 159
Caption = 'Top is in 60 70'
TabOrder = 0
OnMouseMove = Panel2MouseMove
end
end
end

Александр Боковиков
E-mail: bokovikov<gav-gav>mail<point>ru
http://old.apress.ru/pages/bokovikov/delphi
ICQ 272074426

sl

unread,
Jun 18, 2008, 11:11:25 PM6/18/08
to
Thu Jun 19 2008 02:23, Alexander B. Bokovikov wrote to sl:

Ты берёшь BoundsRect у Panel2 = (10,10), а координаты преобразуешь от её же
клиента, т.е. точку (10,10) в координатах Panel2. Скорее всего, ты для отладки
добавил строки

> p := Panel2.BoundsRect.TopLeft;
> Label2.Caption := IntToStr(p.X) + ' ' + IntToStr(p.Y);

не заметив, что p теперь другой.

А вообще, есть такая функция - TControl.ClientToParent:

procedure TForm1.Panel2MouseMove(Sender: TObject; Shift: TShiftState; X,Y:
Integer);

var Pnt: TPoint;
begin
...
// получить в Pnt координаты мыши относительно клиента Form1
Pnt:= Panel2.ClientToParent(Point(X,Y), Self);
// GetParentForm(Panel2) отличается от Self только если Form1
// сама лежит на другом TWinControl
...
end;

0 new messages