Камрады, подскажите, если кто сталкивался:
Имеем 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
--
Шмырев А. А.
> Камрады, подскажите, если кто сталкивался:
> Имеем 2 dll-ки, в них юзается Chart. Обе две вызываются из одного и того
> же приложения. Если поработать сначала с одной, а потом тыркнуть другую,
> то получает вот такое:
Вопрос в целом решен, в главном приложении не выгружалась ни одна, ни вторая
dll после окончания их использования. Hо все же, если кто встречался с таким,
подскажите - как такой косяк можно обойти по-другому?
--
Шмырев А. А.
P.S.
А вообще-то освобождать по мере ненадобности ресурсы,
занимаемые тобой, в т. ч. и выгружать библиотеки - это признак
хорошего тона. У меня вот, как наиболее яркий например, есть
программуля, у которой, по показаниям TaskManager, пиковое
потребление 100МБ, а рабочее - 25МБ (страртап у нее очень
громоздкий). Прикинь, если б мне стало впадлу освобождать
эту память...
TAxisChartTitle - это кусок стандартного Delph'ового чарта, чарт используется
и у меня, и у сотрудника. Куды бечь? :)
--
Шмырев А. А.
D> TAxisChartTitle - это кусок стандартного Delph'ового чарта, чарт
D> используется и у меня, и у сотрудника. Куды бечь? :)
Бечь от ДЛЛ в сторону run time packages. Это те же ДЛЛ, только специальным
образом оформленные. Как должно быть известно, в Дельфи все классы имеют
общего предка - TObject. Класс физически представляет собой некую структуру, в
которой хранятся таблицы виртуальных и динамических методов, published свойств
и куча прочей RTTI. Когда ты создаёшь обычную ДЛЛ, в которой описываются
(используются) классы, в этой ДЛЛ создаются структуры RTTI для каждого такого
класса (и всех их предков). Если приложение написано тоже на дельфи, то, при
явном использовании классов из этой ДЛЛ можно огрести кучу приколов, т.к.
TObject приложения и TObject ДЛЛ получаются два разных класса - адреса
структур RTTI разные.
Есть и другой выход: не передавать классы через границу ДЛЛ (программа и ДЛЛ
пользуются каждая своим набором), а использовать простые функции или
интерфейсы. Интерфейсы удобнее - те же классы, практически.
Если выберешь run time packages, совет: создай новый run time package и включи
в него все исходники стандартных компонент, которые используются программой и
твоими пакаджами (бывшими ДЛЛами), а программу и пакаджи к ней компилируй with
run time packages только этот пакадж. Это, во-первых, уменьшит количество
модулей, необходимых программе, а, во вторых, гарантирует от случайного
"цепляния" пакаджей дельфи, если она установлена (эти пакаджи могут быть от
другого сервис-пака или ещё какой глюк).
Возникла непонятка на ровном месте. Имеем на форме две вложенные друг
в друга панели. Делаем простую функцию перевода координат (см.
процедуру 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
Ты берёшь 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;