home *** CD-ROM | disk | FTP | other *** search
- {*********************************************************}
- { }
- { Calmira Visual Component Library 1.0 }
- { by Li-Hsin Huang, }
- { released into the public domain January 1997 }
- { }
- {*********************************************************}
-
- unit DropServ;
-
- { TDropServer component
-
- If you ever need to drop files into other programs, this component
- can lend a hand, although it still requires some programming on your
- part. In a control's OnMouseMove handler, call CanDrop to determine
- if if the cursor is over a suitable window. In the OnEndDrag handler,
- call the DragFinished method. If a drop is allowed, the OnFileDrop
- event is triggered which lets you assign the files to drop.
-
- AutoClear : Boolean (inherited)
- If this is True, then the Files property is cleared after each
- drop is completed.
-
- Files : TStrings (run-time only)
- Contains a list of files to drop into another program
-
- InternalDrop : Boolean
- If this is set to True, OnFileDrag events will occur when the
- cursor is over a valid window belonging to your program. If it is
- False, OnFileDrag only occurs when the cursor is over another program.
- Generally, you should use Delphi's own drag and drop handling and set
- this to False.
-
- DesktopDrop : Boolean
- If this is set to True, you will receive an OnDesktopDrop event when
- the mouse is released over the desktop background or wallpaper.
-
- CanDrop: Boolean;
- Returns True if the cursor is over something that can accept drops.
- Call this inside an OnMouseMove handler. If the cursor is currently
- over a window, the call will trigger the OnFileDrag event to ask you
- for confirmation of the drop.
-
- procedure DragFinished;
- Call this inside an OnEndDrag handler. If the cursor is over a
- suitable window and you have responded to the OnFileDrag event,
- then an OnFileDrop is triggered to let you assign the filenames.
-
- procedure DropFiles(Wnd: HWnd; AMousePos: TPoint);
- Encapsulates the WM_DROPFILES message and immediately causes a
- drop into the given window. The strings in the Files property are
- contatenated into the required structure and a WM_DROPFILES message
- is sent to the given window. The TPoint parameter lets you control
- the location of this forced drop.
-
- OnFileDrag
- Occurs when you call CanDrop and the cursor is over a window that
- accepts dropped files. To permit the drop (if the user releases the
- mouse button), set the Accept property to True. The Target parameter
- contains the handle of the window in question, and lets you perform
- your own tests before accepting.
-
- OnFileDrop
- Occurs when the user releases the mouse button over a window that
- accepts files and you call DragFinished method. During this event,
- you must fill the Files property with the files you wish to drop
- (one file per line). The drop takes place as soon as your handler
- finishes executing.
-
- OnDesktopDrop
- Occurs when the user releases the mouse button over the desktop.
- This is only a notification - TDropServer doesn't do anything
- afterwards. The Target parameter contains the window handle of
- the desktop, in case you want to send any messages to it.
- }
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs, DragDrop;
-
- type
- TFileDragEvent = procedure (Sender : TObject; X, Y: Integer;
- Target : HWND; var Accept : Boolean) of object;
-
- TFileDropEvent = procedure (Sender : TObject; X, Y: Integer;
- Target : HWND) of object;
-
- TDropServerError = class(Exception);
-
- TDropServer = class(TDragDrop)
- private
- { Private declarations }
- DropPoint : TPoint;
- AllowDrop : Boolean;
- DropWindow : HWND;
- FInternalDrop : Boolean;
- FDesktopDrop : Boolean;
- FOnFileDrag : TFileDragEvent;
- FOnFileDrop : TFileDropEvent;
- FOnDeskDrop : TFileDropEvent;
- protected
- { Protected declarations }
- public
- { Public declarations }
- procedure DropFiles(Wnd: HWnd; AMousePos: TPoint);
- function CanDrop: Boolean;
- procedure DragFinished;
- published
- { Published declarations }
- property InternalDrop : Boolean read FInternalDrop write FInternalDrop default False;
- property DesktopDrop : Boolean read FDesktopDrop write FDesktopDrop default False;
- property OnFileDrag : TFileDragEvent read FOnFileDrag write FOnFileDrag;
- property OnFileDrop : TFileDropEvent read FOnFileDrop write FOnFileDrop;
- property OnDeskDrop : TFileDropEvent read FOnDeskDrop write FOnDeskDrop;
- end;
-
- procedure Register;
-
-
- implementation
-
- type
- { Windows expects a WM_DROPFILES message to contain a memory
- handle with this structure as a header }
-
- PDropFileRec = ^TDropFileRec;
- TDropFileRec = record
- Size: Word;
- MousePos: TPoint;
- InNonClientArea: Boolean;
- end;
-
- procedure TDropServer.DropFiles(Wnd: HWnd; AMousePos: TPoint);
- var
- H: THandle;
- p: PDropFileRec;
- data : PChar;
- size : Word;
- i, count: Integer;
- begin
- { Thanks to Brian Andersen for this procedure's algorithm (it doesn't
- seem to be documented by Microsoft) }
-
- if GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_ACCEPTFILES = 0 then
- raise TDropServerError.Create('This windows does not accept dropped files');
-
- WinProcs.ScreenToClient(Wnd, AMousePos);
-
- { Find the size of the buffer needed to hold the filenames }
- size := SizeOf(TDropFileRec) + 1;
- count := 0;
- while (size < 65276) and (count < Files.Count) do begin
- Inc(size, Length(Files[count]) + 1);
- Inc(count);
- end;
-
- { Allocate the buffer }
- H := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, size);
-
- if H = 0 then raise TDropServerError.Create('Unable to allocate file drop buffer.');
-
- p := GlobalLock(H);
-
- { Initialize the header info }
- with p^ do begin
- Size := SizeOf(TDropFileRec);
- MousePos := AMousePos;
- InNonClientArea := SendMessage(Wnd, WM_NCHITTEST, 0, Longint(AMousePos)) <> HTCLIENT;
- end;
-
- { Append the filenames to the buffer after advancing the pointer
- beyond the header }
- data := PChar(p) + Sizeof(TDropFileRec);
- for i := 0 to count-1 do begin
- StrPCopy(data, Files[i]);
- Inc(data, Length(Files[i]) + 1);
- end;
- GlobalUnlock(H);
-
- { Drop the files }
- PostMessage(Wnd, WM_DROPFILES, H, 0);
-
- if AutoClear then Files.Clear;
- end;
-
-
- function TDropServer.CanDrop: Boolean;
- var
- p: TPoint;
- begin
- GetCursorPos(p);
- AllowDrop := False;
- DropWindow := WindowFromPoint(p);
-
- if ((DropWindow = GetDesktopWindow) and DesktopDrop) then begin
- AllowDrop := True;
- DropPoint := p;
- end
- else begin
- if ((DropWindow <> 0) and
- (InternalDrop or (GetWindowTask(DropWindow) <> GetCurrentTask)) and
- (GetWindowLong(DropWindow, GWL_EXSTYLE) and WS_EX_ACCEPTFILES > 0)) then begin
- AllowDrop := True;
- DropPoint := p;
- if Assigned(FOnFileDrag) then FOnFileDrag(self, p.x, p.y, DropWindow, AllowDrop);
- end;
- end;
- Result := AllowDrop;
- end;
-
-
- procedure TDropServer.DragFinished;
- begin
- if AllowDrop then begin
- if DropWindow = GetDesktopWindow then begin
- if Assigned(FOnDeskDrop) then
- FOnDeskDrop(self, DropPoint.x, DropPoint.y, DropWindow);
- end
- else if Assigned(FOnFileDrop) then begin
- FOnFileDrop(self, DropPoint.x, DropPoint.y, DropWindow);
- DropFiles(DropWindow, DropPoint);
- end;
- end;
- AllowDrop := False;
- end;
-
-
-
- procedure Register;
- begin
- RegisterComponents('Samples', [TDropServer]);
- end;
-
-
- end.
-
-
-