Making RTPkgs trivial plug-ins in delphi.
- From: "Dennis Landi" <nada@xxxxxxxx>
- Date: Sun, 26 Aug 2007 08:49:32 +0530
In general, I am sick and tired of how klunky the design is for Run-time
Package system is in Delphi. Things that should be real simple are real
hard and real frusturating.
In the thread entitled "RTTI for RT Packages", I was trying to figure out
how to surface an OnRegisterClass event handler that I could consume in my
application that would fire any time register class was call from a packaged
unit loaded via LoadPackage(). This functionality is essential to achieve a
basic plug-in design, which is of course what a run-time package is: A
Plug-in...
The solution is trivial.
For future versions of delphi the solution is:
1) Add a new event-handler to TApplication:
TClassRegisteredEvent = procedure(AClass: TPersistentClass) of object;
TApplication = class(...)
private
FOnClassRegistered:TClassRegisteredEvent;
public
property OnClassRegistered:TClassRegisteredEvent read FOnClassRegistered
write
FOnClassRegistered;
end;
2) create a wrapper for RegisterClass that calls an
TApplication.OnRegisterClass.
procedure RegisterClassEx(AClass: TPersistentClass);
begin
classes.registerClass(AClass);
if assigned(Application.OnClassRegistered) then
Application.OnClassRegistered(AClass);
end;
That's it CodeGear, you're done.
However, that doesn't help us out here in the trenches using current and
past version of Delphi on a daily basis.
So below is a solution should work for just about any version of Delphi.
I'll post the code here and a zip to attachments; and eventually I'll get it
up on my website of utilities...
//*********The Package
Code*******************************************************
unit uPkgTest;
//---------A Unit In a Run-time Pkg---------------------
interface
uses Windows, Messages, SysUtils, Variants, Classes, Forms,
Dialogs, StdCtrls, ExtCtrls, Controls;
type
TTest01 = class(TPersistent)
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
procedure SendData(copyDataStruct: TCopyDataStruct) ;
var
receiverHandle : THandle;
recieverClassName, recieverName:string;
cbInt : integer;//callback value
begin
recieverName := application.mainform.Name;
recieverClassName:= application.mainform.ClassName;
showmessage('LoadPackage - '+#13#10+'Get the Application''s MainForm
Name: '+#13#10+
application.mainform.ClassName);
//application.MainForm.Handle;
receiverHandle :=
FindWindow(PChar(recieverClassName),PChar(recieverName)) ;
if receiverHandle = 0 then
begin
ShowMessage('CopyData Receiver NOT found!') ;
Exit;
end
else showmessage('MainForm''s Handle is: '+intToStr(receiverHandle));
cbInt := SendMessage(receiverHandle, WM_COPYDATA, 0,
Integer(@copyDataStruct));
if cbInt > 0 then ShowMessage(Format('Receiver has sent back this value:
%d !',[cbInt]));
end;
procedure SendString(s:string) ;
var
copyDataStruct : TCopyDataStruct;
begin
copyDataStruct.dwData := 0; //use it to identify the message contents
copyDataStruct.cbData := 1 + Length(s) ;
copyDataStruct.lpData := PChar(s) ;
SendData(copyDataStruct) ;
end;
procedure registerClassEx(AClass:TPersistentClass);
begin
registerClass(AClass);
sendString(AClass.ClassName);
//application should never be NIL...
if application = nil then showmessage('Application is nil');
end;
initialization
registerClassEx(TTest01);
finalization
unregisterClass(TTest01);
end.
//**********And below is code to drop into any MainForm ********************
//**** NOTE: Since we can't get an event handler in TApplication, **********
//***** TApplication.MainForm is our next best generic option...
**********
unit unit01;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm6 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure WMCopyData(var Msg : TWMCopyData) ; message WM_COPYDATA;
procedure HandleCopyDataString(copyDataStruct: PCopyDataStruct);
public
{ Public declarations }
end;
var
Form6: TForm6;
implementation
{$R *.dfm}
procedure TForm6.Button1Click(Sender: TObject);
begin
if FileExists('Pkg01.bpl') then
begin
loadPackage('Pkg01.bpl') ;
end
else beep;
end;
procedure TForm6.HandleCopyDataString(copyDataStruct: PCopyDataStruct);
var
s : string;
begin
s := PChar(copyDataStruct.lpData);
showmessage('ClassName: '+s+' Recieved!');
end;
procedure TForm6.WMCopyData(var Msg: TWMCopyData);
begin
HandleCopyDataString(Msg.CopyDataStruct);
//Send something back
msg.Result := 1111111;
end;
end.
.
- Prev by Date: Re: What are your favorite tools for Delphi programmers?
- Next by Date: Re: I have seen some fat client Dot Net apps
- Previous by thread: New movies and book reviews
- Next by thread: WGA servers are down
- Index(es):