Ich hab D2005 Enterprise SP3 in Deutsch im Einsatz.
Habe die nachstehende Komponente "Filedropper.pas" als Packet installiert.
Wenn ich die Eigenschaft "Linkage Target" mit (gültigem) Inhalt versehe, läuft meine Applikation hinterher zwar (ich kann jetzt nicht checken, ob dort ein Leak vorliegt oder so), aber das D2005 bringt beim Schliessen der Applikation die Fehlermeldungen:
Element hat kein Übergeordnetes Fenster.
Detail: [0053C0CB]{vcl90.bpl } Controls.TWinControl.CreateWnd (Line 6242, "Controls.pas" + 9) + $3B
Dann: Zugriffsverletzung bei Adresse 0000001C. Lesen von Adresse 0000001C.
Detail: [0000001C]{
bds.exe }
[40005F5B]{rtl90.bpl } System.@HandleAnyException (Line 9625, "system.pas" + 13) + $0
[7C913786]{ntdll.dll } RtlConvertUlongToLargeInteger + $41
[7C91EAF5]{ntdll.dll } KiUserExceptionDispatcher + $9
[400059D4]{rtl90.bpl } System.TObject.Free (Line 8498, "system.pas" + 1) + $4
[0035DB3D]{designide90.bpl} ComponentDesigner.TComponentRoot.Close (Line 5205, "ComponentDesigner.pas" + 4) + $5
[02554F58]{delphicoreide90.bpl} DelphiModule.TPascalCodeMgrModHandler.Destroyed (Line 527, "DelphiModule.pas" + 4) + $5
[003440E2]{designide90.bpl} ToolUtils.ForEach (Line 90, "ToolUtils.pas" + 5) + $F
[00775802]{coreide90.bpl} DocModul.TCodeIDocModule.NotifyDestruction (Line 2237, "DocModul.pas" + 2) + $B
[40005E1D]{rtl90.bpl } System.@BeforeDestruction (Line 9214, "system.pas" + 7) + $0
[00773D51]{coreide90.bpl} DocModul.TDocModule.WalkDependencies (Line 1514, "DocModul.pas" + 1) + $1
[00772F4C]{coreide90.bpl} DocModul.TDocModule.Close (Line 1011, "DocModul.pas" + 12) + $F
[006D4515]{coreide90.bpl} ProjectModule.TBaseProject.BeforeDestruction (Line 782, "ProjectModule.pas" + 30) + $2
[0252F2B9]{delphicoreide90.bpl} BaseDelphiProject.TBaseDelphiProject.BeforeDestruc tion (Line 990, "BaseDelphiProject.pas" + 4) + $2
[400059D4]{rtl90.bpl } System.TObject.Free (Line 8498, "system.pas" + 1) + $4
[00773D51]{coreide90.bpl} DocModul.TDocModule.WalkDependencies (Line 1514, "DocModul.pas" + 1) + $1
[00772F4C]{coreide90.bpl} DocModul.TDocModule.Close (Line 1011, "DocModul.pas" + 12) + $F
[006C91DA]{coreide90.bpl} ProjectGroup.TProjectGroupWrapper.CloseMiscProject s (Line 1984, "ProjectGroup.pas" + 8) + $A
[00412BE7]{
bds.exe }
[4003E1FF]{rtl90.bpl } Classes.TBasicAction.Execute (Line 10954, "classes.pas" + 3) + $7
[009DB524]{vclactnband90.bpl} ActnMenus.TCustomActionMainMenuBar.TrackMenu (Line 3068, "ActnMenus.pas" + 3) + $3
[009D6C4D]{vclactnband90.bpl} ActnMenus.TCustomActionMenuBar.CMItemClicked (Line 880, "ActnMenus.pas" + 3) + $4
[0053CF02]{vcl90.bpl } Controls.TWinControl.WndProc (Line 6673, "Controls.pas" + 51) + $4
[4003EEC0]{rtl90.bpl } Classes.StdWndProc (Line 11456, "classes.pas" + 8) + $0
[77D18731]{user32.dll } GetDC + $6A
[77D18811]{user32.dll } GetDC + $14A
[77D189C8]{user32.dll } GetWindowLongW + $122
[77D196C2]{user32.dll } DispatchMessageA + $A
Hier jetzt der Quellcode des Filedroppers.pas:
Delphi-Quellcode:
unit FileDropper;
{ This is an invisible component to enable file drag & drop to anything on
a form.
Usage: 1. drop on form
2. Connect any TWinControl (or the form itself) as the target
3. Write a handler for the OnAddFile event eg.
function TForm1.FileDropper1AddFile(filename: String): Boolean;
begin
Memo1.Lines.LoadFromFile(FileName);
result := true;
end;
and assign it to the OnAddFile event
4. Optionally attach a handler to the OnFileQuery event. This event
could be used to allow/disallow file drop based on file name,
file size or file content.
DISCLAMER - Use at own risk!
}
interface
uses Controls, Classes, Messages;
type
TFileDropHandler =
function(filename:
string):boolean
of object;
TFileDropper =
class(TComponent)
private
FTarget : TWinControl;
// the target control
FOnAddFile :TFileDropHandler;
FOnFileQuery :TFileDropHandler;
FOldWndProc: TWndMethod;
procedure WMDROPFILES(
var Msg: TMessage);
procedure WndProcExtra(
var Message: TMessage);
procedure SetTarget(
const Value: TWinControl);
function GetAcceptDrop: boolean;
public
constructor Create(AOwner: TComponent);
override;
destructor Destroy;
override;
property AcceptDrop: boolean
read GetAcceptDrop;
published
property Target: TWinControl
read FTarget
write SetTarget;
property OnAddFile: TFileDropHandler
read FOnAddFile
write FOnAddFile;
property OnFileQuery: TFileDropHandler
read FOnFileQuery
write FOnFileQuery;
end;
procedure Register;
implementation
uses ShellAPI, SysUtils;
procedure Register;
begin
RegisterComponents('
Samples', [TFileDropper]);
end;
constructor TFileDropper.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TFileDropper.Destroy;
begin
SetTarget(
nil);
inherited;
end;
function TFileDropper.GetAcceptDrop: boolean;
begin
result := FTarget <>
nil;
end;
procedure TFileDropper.SetTarget(
const Value: TWinControl);
begin
if ( Value =
nil)
then
begin
// This is an unhook action
if Assigned(FTarget)
then
begin
DragAcceptFiles(FTarget.Handle, False);
// unregister control for drop
FTarget.WindowProc := FOldWndProc;
end;
FTarget :=
nil;
end
else
begin
// This is a hook action, just try to also handle the case that
// some other control was hooked before
if Assigned(FTarget)
and (FTarget <> Value)
then
FTarget.WindowProc := FOldWndProc;
// unhook old
FTarget := Value;
FOldWndProc := FTarget.WindowProc;
FTarget.WindowProc := WndProcExtra;
DragAcceptFiles(FTarget.Handle, True);
// register control for drop
end;
end;
procedure TFileDropper.WMDROPFILES(
var Msg: TMessage);
var
pcFileName: PChar;
sFileName:
string;
i, iSize, iFileCount: integer;
begin
pcFileName := '
';
// to avoid compiler warning message
iFileCount := DragQueryFile(Msg.wParam, $FFFFFFFF, pcFileName, 255);
for i := 0
to iFileCount - 1
do
begin
iSize := DragQueryFile(Msg.wParam, i,
nil, 0) + 1;
pcFileName := StrAlloc(iSize);
DragQueryFile(Msg.wParam, i, pcFileName, iSize);
sFileName := pcFileName;
StrDispose(pcFileName);
if (
not Assigned(FOnFileQuery))
or FOnFileQuery(sFileName)
then
if Assigned(FOnAddFile)
then
FOnAddFile(sFileName);
// method to add each file
end;
DragFinish(Msg.wParam);
end;
procedure TFileDropper.WndProcExtra(
var Message: TMessage);
begin
if (
Message.Msg = WM_DROPFILES)
and AcceptDrop
then
WMDROPFILES(
Message);
// handle WM_DROPFILES message
// call default WindowProc method to handle all other messages
FOldWndProc(
Message);
end;
end.
Ich hoffe, das der eine oder andere eine Idee hat.
Gruss
EL