Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.12.12;
Скачать: [xml.tar.bz2];

Вниз

Invalid Class Typecast   Найти похожие ветки 

 
qwe   (2003-11-21 16:53) [0]

Что это за ошибка? И как с не бороться?


 
Reindeer Moss Eater   (2003-11-21 16:54) [1]

Недопустимое преобразование типов.


 
qwe   (2003-11-21 16:57) [2]

PluginForm := TComponentClass(AClass).Create(Application) as TForm;

вот здесь, то есть вот это дело TComponentClass(AClass).Create(Application)преобразовать к Tform нельзя


 
Anatoly Podgoretsky   (2003-11-21 16:57) [3]

Не делать этого.


 
jack128   (2003-11-21 17:05) [4]

AClass - это не форма..


 
Юрий Зотов   (2003-11-21 17:09) [5]

> qwe

if AClass.InheritsFrom(TForm) then
PluginForm := TFormClass(AClass).Create(Application)
else
raise Exception.Create(AClass.ClassName + " - это не форма");


 
qwe   (2003-11-21 17:10) [6]

var
AClass: TPersistentClass;


 
qwe   (2003-11-21 17:11) [7]

AClass := GetClass("TfTestClass");


 
alex_***   (2003-11-21 17:12) [8]

ты проверь, InheritsFrom( TForm ) или нет. и все вопросы отпадут


 
alex_***   (2003-11-21 17:14) [9]

кстати, если ты находишься в DLL, собранной без галочки пакетов, то там оператор as не работает.


 
Юрий Зотов   (2003-11-21 17:20) [10]

> alex_*** (21.11.03 17:14) [9]

Работает. Но не стыкуется с классами из Exe.


 
qwe   (2003-11-21 17:21) [11]

InheritsFrom(TForm) - не форма
но PluginForm := TFormClass(AClass).Create(Application) работает


 
Юрий Зотов   (2003-11-21 17:23) [12]

> qwe

Так не бывает. См.[5].


 
qwe   (2003-11-21 17:26) [13]

if AClass.InheritsFrom(TForm) then
PluginForm := TFormClass(AClass).Create(Application)
else
raise Exception.Create(AClass.ClassName + " - это не форма");

выдает ошибку не форма а если сделать просто

PluginForm := TFormClass(AClass).Create(Application)
PluginForm.Show

показывается та форма которая нужна


 
alex_***   (2003-11-21 17:29) [14]

AClass - это что вообще?


 
qwe   (2003-11-21 17:32) [15]

var
AClass: TPersistentClass;

AClass := GetClass("TfTestClass");


 
alex_***   (2003-11-21 17:36) [16]

ну блин... объяснил. "TfTestClass" - некая форма, вызываемая из пакета?


 
Юрий Зотов   (2003-11-21 17:40) [17]

1. Где и как объявлен TfTestClass?
2. Используются ли DLL?


 
qwe   (2003-11-21 17:43) [18]

unit в пакете

unit TestClass;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TfTestClass = class(TForm)
Button1: TButton;
private
{ Private declarations }
public
{ Public declarations }
end;
var
fTestClass: TfTestClass;
implementation
{$R *.dfm}
initialization
RegisterClass(TfTestClass);
finalization
UnRegisterClass(TfTestClass);
end.


 
han_malign   (2003-11-21 17:45) [19]

Приехали, приведение метаклассов делать - вы бы еще i: integer(byte); объявили...

TFormClass(AClass) - это по вашему он должен понять, что вы извращенец и подменить на AClass:=TFormClass???

Для чего, по вашему, вообще метаклассы нужны?

> Юрий Зотов © (21.11.03 17:09) [5]
- может все-таки
if AClass.InheritsFrom(TForm) then
PluginForm := AClass.Create(Application) //TFormClass(AClass).Create(Application)
else
raise Exception.Create(AClass.ClassName + " - это не форма");

- или на худой конец
if AClass.InheritsFrom(TForm) then
PluginForm := TForm(AClass.Create(Application))
else
raise Exception.Create(AClass.ClassName + " - это не форма");

уж вы то...


 
Юрий Зотов   (2003-11-21 18:02) [20]

> han_malign © (21.11.03 17:45) [19]

Будем проверять? Готов поспорить на пиво.
:о)

Оба Ваших вариант даже не откомпилируются.
:о)


 
Юрий Зотов   (2003-11-21 18:05) [21]

> qwe (21.11.03 17:43) [18]

1. Проект компилируется с run-time пакетами?
2. GetClass вызывается тоже в пакете, или в Exe?


 
qwe   (2003-11-25 10:16) [22]


> Юрий Зотов © (21.11.03 18:05) [21]

1. да
2. в EXE


 
Юрий Зотов   (2003-11-25 12:56) [23]

Вероятно, пакет просто не грузится, за неимением такой необходимости. Вот код, который работает соверщенно нормально.

unit PluginFrm; // В run-time пакете с именем Package

interface

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

type
TPluginForm = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
end;

implementation

{$R *.dfm}

procedure TPluginForm.Button1Click(Sender: TObject);
begin
Close
end;

procedure TPluginForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree
end;

initialization
RegisterClass(TPluginForm)
finalization
UnregisterClass(TPluginForm)
end.

===========================

unit AppFrm; // В EXE (собирается с run-time пакетом)

interface

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

type
TAppForm = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;

var
AppForm: TAppForm;

implementation

{$R *.dfm}

function CreatePluginForm(AClass: TPersistentClass): TForm;
begin
if AClass.InheritsFrom(TForm) then
Result := TFormClass(AClass).Create(Application)
else raise Exception.CreateFmt("%s - это не форма", [AClass.ClassName])
end;

procedure TAppForm.Button1Click(Sender: TObject);
begin
CreatePluginForm(FindClass("TPluginForm")).Show
end;

initialization
LoadPackage("Package.bpl")
end.

==============================================

> han_malign © (21.11.03 17:45) [19]

Так как насчет пива? Согласен на бутылочку "Миллера".
:о)


 
qwe   (2003-11-26 17:14) [24]

Заметил одну странную штуку, если приложение не большое то пакеты таким способом грузятся легко. Если у меня приложение в памяти занимает более 9 000 кб То FindClass("TPluginForm") ничего не возвращает


 
qwe   (2003-11-27 08:59) [25]

Кто нибудь выскажите свое мнение по поводу последнего сообщения, прав ли я в своих наблюдениях? И как можно решить эту проблему?


 
Юрий Зотов   (2003-11-27 15:26) [26]

> qwe (27.11.03 08:59) [25]
> Кто нибудь выскажите свое мнение по поводу последнего
> сообщения, прав ли я в своих наблюдениях

А как Вы сами думаете, Вы правы в своих наблюдениях? Ну с чего бы это вдруг приложение весом 8.9 M грузят пакеты без проблем, а весом 9.1 М - уже с проблемами?

Может, дело тут вовсе не в размере, а в Вашем коде? Вам не кажется, что именно это и есть наболее вероятная причина?


 
qwe   (2003-11-27 15:50) [27]

Хорошо, тогда почему приведенный вами код в простом приложениии работает а в моем нет. И еще есль ли какая нибудь функция возвращающая список зарегестрированных классов


 
Юрий Зотов   (2003-11-27 16:57) [28]

> qwe (27.11.03 15:50) [27]
> почему приведенный вами код в простом приложениии работает а
> в моем нет.

Вот как раз это и указывает на ту самую наиболее вероятную причину.

> функция возвращающая список зарегестрированных классов

Внутри IDE, конечно, есть (там просто доступен весь список). Но "снаружи" все это, насколько я знаю, недоступно. Есть только GetClass и FindClass.

Но ведь никто не мешает Вам организовать собственный список зарегистрированных Вами классов, верно?

Вообще же, очень похоже, что Вы, как говорится, ломитесь в открытую дверь. Никаких проблем возникать не должно и если Вы просто расскажете, что именно Вы хотите сделать, то, думаю, мы тут же найдем очень простое решение.


 
qwe   (2003-11-27 17:29) [29]

Я хочу подключить bpl к проекту, проблема в том делаю одни и те же действия в разных проектах, а результат разный, где то FindClass работает где то нет. Насчет создания собственного списка классов то я так и делал, но там возникает другвя проблема, при создании окна переданного класса все нормально если стиль окна fsnormal, если сделать его fsMDIChild то выдается ошибка Нет MDI Form currenty active. Опять же передавая плагину указатель на приложение
var
lpA: ^TApplication;

initialization
lpA := pointer(ApplicationID);
Application := lpA^;

добиваюсь нужного результата плагин загружается как MDIChild но возникают проблемы при выгрузки пакета. И так далее замкнутый круг различных ошибок.


 
Юрий Зотов   (2003-11-27 19:47) [30]

Ох-х-х... ну почему было не сказать простыми русскими словами - мол, хочу то-то и то-то? Без всяких pointer"ов.

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

Насколько я понял, Вы хотите использовать BPL, как плагины дочерних форм? Если так, то в "кладовке" есть готовое решение этой задачи.


 
qwe   (2003-11-28 11:44) [31]

Спасибо за пример, еще один вопрос который вы в примере не расматриваете это выгрузка BPL

вешаю реакцию на закрытие дочерней формы
with TBaseFormClass(lbFormList.Items.Objects[0]).Create(Application) do
begin
OnClose := ChildFormClose;
Show
end

procedure TfMain.ChildFormClose(Sender: TObject; var Action: TCloseAction)
begin
if PluginModule<>0 then
UnLoadPackage(PluginModule);
PluginModule:=0;
end;

дает AV, как можно решить эту проблему.


 
Юрий Зотов   (2003-11-28 13:20) [32]

1. Давайте рассмотрим, как работает Ваш алгоритм.

Код дочерней формы сидит в BPL. Он возбуждает событие OnClose -то есть, вызывает его обработчик ChildFormClose, код которого находится в Exe. Тот выгружает пакет и завершается - после чего, естественно, должен произойти возврат в точку вызова. То есть, в код дочерней формы, находящийся в пакете. А пакета уже нет и вместе с ним уже нет того самого кода, откуда был сделан вызов ChildFormClose и куда нужно выполнить возврат. Некуда возвращаться, понимаете?

Какие могут быть последствия? Да любые - и AV еще самое лучшее, потому что хотя бы явно кричит об ошибке.

2. > Как можно решить эту проблему.

Например, так. Сделайте обработчик OnClose дочерней формы в самой этой форме (не в главной, а в самой дочерней). Из него через PostMessage (но не через SendMessage) отправьте главной форме любое сообщение (например, WM_USER+100), передав в параметре хэндл (HInstance) модуля дочерней формы. А в главной форме напишите обработчик этого сообщения, который и выгрузит тот пакет, HInstance которого он получил в параметре.

Идея в том, что PostMessage поместит сообщение в очередь и поэтому оно будет обработано не сразу, а тогда, когда будет из этой очереди выбрано - то есть, когда код выгружаемого модуля будет уже не нужен. Обращений к нему не произойдет и модуль будет нормально выгружен.


 
Anton.   (2003-12-01 11:11) [33]

Сделал но появилась еще одна проблема

PluginModule := LoadPackage(); - handle модуля плагина.

PostMessage( , , application.Handle, 0); в плагине совсем другой handle у application, разные цифры, так что передавать из подгружаемого модуля? Может я что то путаю?


 
Юрий Зотов   (2003-12-01 11:56) [34]

Передавать ведь надо хэндл модуля, который надо выгрузить, верно? А его вернула LoadPackage при загрузке модуля. И хранится он в PluginModule.

Если несколько модулей могут грузиться одновременно, заведите их список (вместо одной переменной PluginModule). При загрузке модуля добавляйте в этот список элемент с хэндлом, а при его выгрузке - удаляйте этот элемент.


 
Anton.   (2003-12-01 12:37) [35]

Как я понял в PostMessage можно и не передавать ничего, оно лишь является сообщением главной форме что окно с плугином закрылось(1 bpl).

Тогда непонятно следующее
в дочернем окне:
procedure TfPluginReport.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Action:=caFree;
fPluginReport:=nil;
PostMessage(FindWindow("TfMain", "xx"), WM_USER+100, 0, 0);
end;

в главном:
procedure TfMain.ChildFormClose();
var
i: Integer;
M: TMemoryBasicInformation;
begin
for i := Application.ComponentCount - 1 downto 0 do
begin
VirtualQuery(GetClass(Application.Components[i].ClassName), M, SizeOf(M));
if (HMODULE(M.AllocationBase) = PluginModule) then
Application.Components[i].Free;
end;
UnRegisterModuleClasses(PluginModule);
if PluginModule<>0 then
UnLoadPackage(PluginModule);
PluginModule:=0;
end;

procedure TfMain.WMUser(var Msg: TMessage);
begin
ChildFormClose;
end;

Если пользоваться этими процедурами - AV,а если закрыть окно и отдельной кнопкой выгрузить пакет то без проблем.


 
Юрий Зотов   (2003-12-01 13:45) [36]

procedure TfPluginReport.FormClose(Sender: TObject; var Action: TCloseAction);
begin
...
PostMessage(FindWindow("TfMain", "xx"), WM_USER + 100,
FindClassHInstance(ClassType), 0)
end;

procedure TfMain.WMUserPlus100(var Msg: TMessage);
begin
with Msg do
begin
...
UnloadPackage(WParam)
end
end;



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.12.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.007 c
1-36637
Soi
2003-12-01 10:36
2003.12.12
Регулярные выражения


1-36605
Альф
2003-12-01 15:28
2003.12.12
Как програмно закрыть OpenDialog ?


1-36719
Triny
2003-12-02 13:13
2003.12.12
Сохранение


4-36882
Talla2k
2003-10-22 01:28
2003.12.12
тормоз Thread


1-36694
Davron
2003-12-02 18:13
2003.12.12
Delphi: ошибка в MessageDlg





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский