Отобразить на форме Tlabel из dll
От: pdn_mail  
Дата: 08.10.08 16:39
Оценка:
Здравствуйте!
Сдаюсь на вашу милость дамы и господа, поскольку сломал уже всю голову, а обсуждения имеющиеся на подобные проблемы в форуме не привели к результату.
Итак, имеется Form1 с Label1 и код в этой форме динамически вызывает custom.dll ищет функцию showlabel(TForm *)
код этой функции в dll следующий

showlabel(TForm *MainForm)
{
TForm1 *F=(TForm1*)MainForm;

TLabel *debuglabelmc=new TLabel(F);

debuglabelmc->Top=F->Label1->Top+60; 
debuglabelmc->Left=F->Label1->Left;  
debuglabelmc->Caption="test";
debuglabelmc->BringToFront();
debuglabelmc->Update();
debuglabelmc->Show();
}


на форме в результате ничего нет, так как видимо debuglabelmc->Parent=NULL
но если добавляю следующую строчку после создания TLabel

debuglabelmc->Parent=(TWinControl*)F->Handle;


то получаю Access violation at address 00E043C6 in module "custom.dll". Read of address 00150612

Что я делаю не так? как надо правильно?
Есть условие, приложение и dll должны быть собраны без rtp, библиотека должна подключаться динамически и в нее передаваться указатель или хэндл главной формы.
Re: Отобразить на форме Tlabel из dll
От: Leonidze  
Дата: 08.10.08 18:01
Оценка:
Здравствуйте, pdn_mail, Вы писали:

...

_>на форме в результате ничего нет, так как видимо debuglabelmc->Parent=NULL

_>но если добавляю следующую строчку после создания TLabel

_>
_>debuglabelmc->Parent=(TWinControl*)F->Handle;
_>


_>то получаю Access violation at address 00E043C6 in module "custom.dll". Read of address 00150612


_>Что я делаю не так? как надо правильно?

ну, всё-таки (TWinControl*)F->Handle это виндовый хэндл, а никак не наследник TControl, вам так не кажется? если я правильно понимаю, debuglabelmc->Parent должен быть объектом, наследником TControl.

_>Есть условие, приложение и dll должны быть собраны без rtp, библиотека должна подключаться динамически и в нее передаваться указатель или хэндл главной формы.


точно ли указатель на хэндл главной формы, а не указатель на объект главной формы?
Re: Отобразить на форме Tlabel из dll
От: rivitna  
Дата: 08.10.08 19:56
Оценка:
Здравствуйте, pdn_mail, Вы писали:

_>Здравствуйте!

_>Сдаюсь на вашу милость дамы и господа, поскольку сломал уже всю голову, а обсуждения имеющиеся на подобные проблемы в форуме не привели к результату.
_>Итак, имеется Form1 с Label1 и код в этой форме динамически вызывает custom.dll ищет функцию showlabel(TForm *)

При работе с DLL следует забыть про классы Builder: (TForm *) в DLL и (TForm *) в EXE абсолютно разные классы, потому как у них свои RTTI. Исключение составляет только особый вид DLL — BPL. Поэтому использовать только типы Windows, что-то наподобие:

TLabel *g_debuglabelmc = NULL;

void showlabel(HWND hwndParent, int nLeft, int nTop)
{
  hidelabel();
  g_debuglabelmc=new TLabel((TComponent *)NULL);
  g_debuglabelmc->ParentWindow = hwndParent;
  g_debuglabelmc->Top=nTop; 
  g_debuglabelmc->Left=nLeft;  
  g_debuglabelmc->Caption="test";
  g_debuglabelmc->BringToFront();
  g_debuglabelmc->Update();
  g_debuglabelmc->Show();
}

void hidelabel()
{
  if (g_debuglabelmc != NULL)
  {
    delete g_debuglabelmc;
    g_debuglabelmc = NULL;
  }
}
Re: Отобразить на форме Tlabel из dll
От: pdn_mail  
Дата: 09.10.08 03:39
Оценка:
Ну эти ответы к сожалению из области теории, потому-что:
showlabel(TForm *MainForm) //здесь я передаю указатель на объект главной формы, причем указывается тип класса формы VCL, а не мой определенный TForm1, просто так надо и к последствиям не приводит.

{
TForm1 *F=(TForm1*)MainForm; // здесь я присваиваю новому указателю тип своей главной формы, инспектор в дебагере четко показывает что F это точно указатель на объект моей формы и соответственно F->Handle это ее хэндл.
...
}


такой код
g_debuglabelmc->ParentWindow = hwndParent;


вызывает ошибку компиляции [C++ Error] Unit1.cpp(222): E2316 'ParentWindow' is not a member of 'TLabel'
проходит только такой вариант
debuglabelmc->Parent->ParentWindow=F->Handle;


но опять получаю Access violation at address 00DD6653 in module "custom.dll". Read of address 00000030
Почему? да потому-что debuglabelmc->Parent = NULL следовательно присваивание значения ParentWindow приводит к этой ошибке.


debuglabelmc->Parent=F->Handle;

вызывает ошибку компиляции [C++ Error] Unit1.cpp(223): E2034 Cannot convert 'void *' to 'TWinControl *' потому и преобразовываю к (TWinControl *)

У кого еще есть какие мысли как побороть эту ситуацию?
Re[2]: Отобразить на форме Tlabel из dll
От: rivitna  
Дата: 09.10.08 04:42
Оценка:
Здравствуйте, pdn_mail, Вы писали:

_>Ну эти ответы к сожалению из области теории, потому-что:

_>showlabel(TForm *MainForm) //здесь я передаю указатель на объект главной формы, причем указывается тип класса формы VCL, а не мой определенный TForm1, просто так надо и к последствиям не приводит.

К сожалению, это еще и практика...
А то, что не работает разве не есть последствия?

_>
_>{
_>TForm1 *F=(TForm1*)MainForm; // здесь я присваиваю новому указателю тип своей главной формы, инспектор в дебагере четко показывает что F это точно указатель на объект моей формы и соответственно F->Handle это ее хэндл.
_>...
_>}
_>


Привидение типа в C-стиле — очень грубый маневр, таким образом, можно привести к любому типу любой указатель на память

_>такой код

_>
_>g_debuglabelmc->ParentWindow = hwndParent;
_>


_>вызывает ошибку компиляции [C++ Error] Unit1.cpp(222): E2316 'ParentWindow' is not a member of 'TLabel'

_>проходит только такой вариант
_>
_>debuglabelmc->Parent->ParentWindow=F->Handle;
_>


Увы, я забыл, что TGraphicControl -> TCustomLabel ->TLabel, и соответственно не имеет ParentWindow

_>У кого еще есть какие мысли как побороть эту ситуацию?


Изменить и пересмотреть постановку задачи
Re: Отобразить на форме Tlabel из dll
От: pdn_mail  
Дата: 09.10.08 05:52
Оценка:
Ну ладно, хорошо, зайдем с другого боку.
Если разместить нижеприведенный код в коде приложения главной формы, то он работает
TForm1 *F=Form1;
TLabel *debuglabelmc=new TLabel(F);
debuglabelmc->Parent=F;
debuglabelmc->Top=F->Label1->Top+60; 
debuglabelmc->Left=F->Label1->Left;  
debuglabelmc->Caption="test";
debuglabelmc->BringToFront();
debuglabelmc->Update();
debuglabelmc->Show();


Если его помеcтить в dll
showlabel(TForm *MainForm)
{
TForm1 *F=(TForm1*)MainForm;
TLabel *debuglabelmc=new TLabel(F);
debuglabelmc->Parent=F;
debuglabelmc->Top=F->Label1->Top+60; 
debuglabelmc->Left=F->Label1->Left;  
debuglabelmc->Caption="test";
debuglabelmc->BringToFront();
debuglabelmc->Update();
debuglabelmc->Show();
}

то debuglabelmc->Parent=F; вызывает ошибку
Project application.exe raised exception class EConvertError with message 'Cannot assing a TFont to a TFont'. Process stoped. Use Step or Run to continue.
Причем любым другим свойствам объекта дает присваивать значения и вызываются методы нормально.

Да блин, опять косяк какой-то. а теперь то что надо? почему он не дает присвоить значение свойства Parent созданного в dll объекта? только из-за того что Owner у него при создании была главная форма приложения?

Что интересно в таком варианте все работает из dll, хоть и вылетает на присваивании Parent, но debuglabelmc на форме появляется
showlabel(TForm *MainForm)
{
TForm1 *F=(TForm1*)MainForm;
TLabel *debuglabelmc=new TLabel(F);
debuglabelmc->Top=F->Label1->Top+60; 
debuglabelmc->Left=F->Label1->Left;  
debuglabelmc->Caption="test";
debuglabelmc->Update();
debuglabelmc->Parent=F;
debuglabelmc->BringToFront();
debuglabelmc->Show();
}


Получается что для Label присваивать значение Parent не надо и последующие строки тоже не обязательны. Достаточно для отображения на форме следующего кода в dll ?
showlabel(TForm *MainForm)
{
TForm1 *F=(TForm1*)MainForm;
TLabel *debuglabelmc=new TLabel(F);
debuglabelmc->Top=F->Label1->Top+60; 
debuglabelmc->Left=F->Label1->Left;  
debuglabelmc->Caption="test";
debuglabelmc->Update();
}
Re[2]: Отобразить на форме Tlabel из dll
От: pdn_mail  
Дата: 09.10.08 06:11
Оценка:
_>Получается что для Label присваивать значение Parent не надо и последующие строки тоже не обязательны. Достаточно для отображения на форме следующего кода в dll ?
_>
_>showlabel(TForm *MainForm)
_>{
_>TForm1 *F=(TForm1*)MainForm;
_>TLabel *debuglabelmc=new TLabel(F);
_>debuglabelmc->Top=F->Label1->Top+60; 
_>debuglabelmc->Left=F->Label1->Left;  
_>debuglabelmc->Caption="test";
_>debuglabelmc->Update();
_>}
_>


Малость ошибся, всетаки Parent для прорисовки нужен. Он присваивается, хоть и вылетает по ошибке.
Поэтому просто ее игнорирую.

showlabel(TForm *MainForm)
{
TForm1 *F=(TForm1*)MainForm;
TLabel *debuglabelmc=new TLabel(F);
debuglabelmc->Top=F->Label1->Top+60; 
debuglabelmc->Left=F->Label1->Left;  
debuglabelmc->Caption="test";
try {debuglabelmc->Parent=F;}
catch (...) {;}
debuglabelmc->Update();
}


вот такие пироги
Re[3]: Отобразить на форме Tlabel из dll
От: wallaby  
Дата: 09.10.08 07:36
Оценка:
Здравствуйте, pdn_mail, Вы писали:

_>вот такие пироги


Учите матчасть

Во-первых, динамическая память в dll и exe управляется разными менеджерами памяти, если только не используется общий менеджер памяти как того рекомендует dll-wizard в комментарии. Без общего менеджера при передаче динамических структур (классов, строк и т.п.) между dll и exe ошибки AV неизбежны.

Во-вторых, одноименные классы в dll и в exe — это не одно и тоже, если только как уже было сказано вместо dll не используется bpl.
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
Re[3]: Отобразить на форме Tlabel из dll
От: Danchik Украина  
Дата: 09.10.08 09:58
Оценка:
Здравствуйте, pdn_mail, Вы писали:

[Skip eto]

_>вот такие пироги


Вот такой вот бред. Читайте что вам говорят знающие люди.
И как всегда в таких случаях рекомендую почитать это от Softwarer Run-time packages
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.