|
Страници по тази тема: 1 | 2 | >> (покажи всички)
Тема
|
Създаване на контроли от DL
|
|
Автор | Mojo (Нерегистриран) |
Публикувано | 27.06.04 23:05 |
|
Как мога да създам панел, бутон или какъвто и да е друг визуален контрол от динамична библиотека и да го сложа в главната форма на програмата? Опитвам с нещо от сорта:
library DynCompDLL; // библиотеката
uses
ShareMem,
SysUtils,
Classes,
Controls,
ExtCtrls;
{$R *.RES}
var Panel: TPanel;
procedure CreatePanel (AParent: TWinControl; X, Y: integer);
begin
Panel:=TPanel.Create(AParent);
with Panel do
begin
Left:=X;
Top:=Y;
Caption:='DLL Panel';
Parent:=AParent;
end;
end;
exports CreatePanel;
begin
end.
В главната програма съм прехванал OnMouseDown:
procedure CreatePanel (AParent: TWinControl; X, Y: integer); external 'DynCompDLL';
// ...
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
CreatePanel(Form1,X,Y);
end;
Идеята е ясна - където се щракне с мишката трябва да се създаде панел с
кода от DLL. Обаче вместо това дава грешка EConvertError: Cannot assign a
TFont to a TFont. Това става при присвояването Parent:=AParent. В кода на
проекта също съм сложил ShareMem най-отпред. Имаше нещо, свързано с
компонентите в DLL, но не се сещам какво беше. Къде бъркам?
| |
Тема
|
Re: Създаване на контроли от DL
[re: Mojo]
|
|
Автор |
PhantomAS () |
Публикувано | 28.06.04 07:09 |
|
Ами предавай Application и Screen обектите - при инциализация на библиотеката - запазваш тези които са инициализирани в DLL - и ги заменяш с тези които идват от приложението, преди освобождаване - връщаш старите.
Същото правило както при създаване на форма от DLL - мисля, че върви без проблем.
---
| |
Тема
|
Re: Създаване на контроли от DL
[re: PhantomAS]
|
|
Автор | Mojo (Нерегистриран) |
Публикувано | 28.06.04 23:25 |
|
В случая е малко по различно - въобще не използвам модула Forms (респ. обекта Application). Когато DLL-a се използва за извеждане на форма, той я "конструира" със собствени средства, без външни обръщения. A в моя случай трябва да се създават компоненти от DLL-a, които да се слагат във външна за него форма - главната форма на извикващото Delphi-приложение. Въпреки, че се работи в общо адресно пространство, проблема явно е по-комплексен и идва от "предаването" на създадения компонент към викащото приложение. Би трябвало да има начин, но засега не мога да го открия ...
| |
|
Мисля, че трябва да си предадеш Application-а задължително. Иначе няма да стане. Също така смятам, че такива неща е по-добре да ги направиш в BPL, а не в DLL - ще ти спести много проблеми от тоя сорт.
| |
Тема
|
Re: Създаване на контроли от DL
[re: Mojo]
|
|
Автор |
Mandor (Sawall) |
Публикувано | 29.06.04 13:41 |
|
Не е точно така - адресното пространство е едно, но имаш две различни таблици за описание на класовете. Затова не може да присвои TFont на TFont - за Delphi-то това са два различни класа (единият от главното приложение и единият от DLL-а). Мисля, че този въпрос е дискутиран и преди, но общо взето решенията са две - или предаваш и Application при конструиране, или компилираш и приложението и DLL-а с Run-Time Libraries.
| |
Тема
|
Re: Създаване на контроли от DL
[re: Mandor]
|
|
Автор |
NDeu (динозавър) |
Публикувано | 29.06.04 15:51 |
|
Право в десятката
| |
Тема
|
Re: Тц, не става ...
[re: NDeu]
|
|
Автор | Mojo (Нерегистриран) |
Публикувано | 29.06.04 22:22 |
|
Ами последвах вашите съвети, но нищо не се промени - грешката остава същата. Това, което направих, беше да присвоя обекта Application от главната програма към този на DLL-a:
procedure SetApp (AppHandle: THandle); // процедурата в DLL
begin
Application.Handle:=AppHandle;
end;
Предаването става в OnCreate на главната форма:
procedure TForm1.FormCreate(Sender: TObject);
begin
SetApp(Application.Handle);
end;
P.S. Дайте някакъв пример или линк (може и към предната дискусия, че не мога да я окрия), където това е реализирано, ще ми бъде много полезно. 10x!
| |
|
А опита ли да го направиш на BPL? Малко се съмнявам...
Те са точно за такива неща - остави делфито да ти свърши мръсната работа и не се занимавай с глупости :)
С тях не се работи кой знае колко по-различно, отколкото с DLL:
var PackageHandle: HMODULE;
PackageHandle := LoadPackage(ExtractFilePath(Application.ExeName) + 'my_pack.bpl);
....
FinalizePackage(PackageHandle);
Опитай! Мисля, че това ще ти реши проблемите. Ти си решаваш
| |
Тема
|
Re: Тц, не става ...
[re: Mojo]
|
|
Автор |
Mandor (Sawall) |
Публикувано | 30.06.04 09:43 |
|
Всъщност заместването би трябвало да е временно. В момента нямам време да ровя, затова опитай това (писано малко наизуст):
procedure CreatePanel(AHandle: THandle; AParent: TWinControl; X, Y: integer);
var
hApp: THandle;
begin
hApp := Application.Handle;
Application.Handle := AHandle;
try
Panel:=TPanel.Create(AParent);
with Panel do
begin
Left:=X;
Top:=Y;
Caption:='DLL Panel';
Parent:=AParent;
end;
finally
Application.Handle := hApp;
end;
end;
...и ако не стане, пиши пак за да потърсим по-точна реализация.
Допълнение:
Доколкото си спомям, това не беше "чисто" разрешаване на проблема. В повечето случаи възникваха последващи проблеми с опресняване на Canvas-и, изобразяване на TScrollBar и т.н. Най-чистото решение е да се компилира с RT-Package-и, но за съжаление в доста случаи това е невъзможно по "политически" причини. Склонен съм да подкрепя предложението на andrew_nikoloff, макар да не съм много наясно с какво точно bpl-а се различава от DLL-а при такъв проблем...
Редактирано от Mandor на 30.06.04 10:00.
| |
Тема
|
Re: Как точно става с BPL?
[re: andrew_nikoloff]
|
|
Автор | Mojo (Нерегистриран) |
Публикувано | 30.06.04 19:17 |
|
Досега съм използвал пакети само по време на дизайн. Сложих кода, който създава панела в отделен модул и си направих пакет от него. Компилирах пакета и се опитах да декларирам процедурата като DLL:
procedure CreatePanel (AParent: TWinControl; X, Y: integer); external 'Package1.bpl';
Обаче така не става - дава грешка Unable to create process. Device attached to the system is not functioning. Кода, който си постнал по-горе зарежда динамично пакета и реших да пробвам с него. Но GetProcAddress(PackageHandle,PChar('CreatePanel')) връща nil - не може да открие процедура с това име в пакета. Явно има още нещо, което пропускам. Всички ресурси, които чета обясняват за DLL-и и runtime-пакети, че били еднкави, но има твърде много разлики, които ми убягват. Как да извикам процедурата при динамично зареждане на пакета - пробвам както би трябвало да стане с DLL, но не ще...
| |
|
Страници по тази тема: 1 | 2 | >> (покажи всички)
|
|
|