Project source
Form source (Pascal)
Form source (DFM)
| Project source: FileTest.dpr |
program FileTest;
{Test application for UnitOOPS OLE Drag and Drop components}
uses
Forms,
fmFileTest in 'fmFileTest.pas' {Form1};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Back to top
|
| Form source: fmFileTest.pas |
unit fmFileTest;
{ UnitOOPS OLE Drag and Drop Components - Example
for accepting files dragged from Explorer or other
file sources, and displaying them with icons, etc.
Also, dragging shortcuts from a window elsewhere.
Last modified: 03/23/2001}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls, uoole;
type
TForm1 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Panel2: TPanel;
Panel3: TPanel;
Button1: TButton;
Panel4: TPanel;
ListView1: TListView;
RadioGroup1: TRadioGroup;
UOTextTarget1: TUOTextTarget;
UOTextSource1: TUOTextSource;
procedure FormCreate(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure UOTextTarget1Drop(Sender: TObject; Acceptor: TWinControl;
const dropText: String; X, Y: Integer);
procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn);
procedure ListView1DblClick(Sender: TObject);
procedure ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
ilLarge: TImageList;
ilSmall: TImageList;
function FileAge(const FileName: string): Integer;
function FormatFileSize(aSize: integer): string;
function FormatFileAttr(aAttr: integer): string;
function GetFileSize(const fileName: String): integer;
procedure WMGetMinMaxInfO(var msg: TWMGetMinMaxInfo);
message WM_GETMINMAXINFO;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
ShellAPI, ShlObj, uoUtil;
procedure TForm1.WMGetMinMaxInfO(var msg: TWMGetMinMaxInfo);
// Limit smallest size of form. In Delphi 4 and above, you can do this
// using constraints.
begin
with msg.MinMaxInfo^ do
begin
ptMinTrackSize := POINT(448, 163);
end; // with
end;
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
var
aSHFi: TSHFileInfo;
begin
// Synchronize the listview and the radio group
RadioGroup1Click(RadioGroup1);
// Set up the image lists - small and large separately.
// They are owned by the form, and will be destroyed along with it.
// Share the images so that we won't destroy the system
// image lists.
// Use a dummy wildcard filename for this call.
ilSmall := TImageList.Create(Self);
ilSmall.ShareImages := true;
ilSmall.Handle := SHGetFileInfo('*.*', 0, aSHFi, sizeOf(aSHFi),
SHGFI_ATTRIBUTES // Retrieves the file attribute flags.
or SHGFI_DISPLAYNAME // Retrieves the display name for the file.
or SHGFI_SYSICONINDEX // Retrieves the handle of the icon
or SHGFI_SMALLICON // Causes the small icon to be retrieved
);
ListView1.SmallImages := ilSmall;
ilLarge := TImageList.Create(Self);
ilLarge.ShareImages := true;
ilLarge.Handle := SHGetFileInfo('*.*', 0, aSHFi, sizeOf(aSHFi),
SHGFI_ATTRIBUTES // Retrieves the file attribute flags.
or SHGFI_DISPLAYNAME // Retrieves the display name for the file.
or SHGFI_SYSICONINDEX // Retrieves the handle of the icon
or SHGFI_LARGEICON // Causes the large icon to be retrieved
);
ListView1.LargeImages := ilLarge;
end;
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
// Change the view style based on the radio button selection
ListView1.ViewStyle := TViewStyle(RadioGroup1.ItemIndex);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ListView1.Items.Clear;
end;
function TForm1.GetFileSize(const fileName: String): integer;
// Returns the size of the file named in fileName, or -1
var
searchRec: TSearchRec;
begin
result := -1; // Fall-through value
if (FindFirst(ExpandFileName(fileName), faAnyFile, SearchRec) = 0) then
begin
result := SearchRec.Size;
FindClose(SearchRec);
end;
end;
function TForm1.FormatFileSize(aSize: integer): string;
// Format file size like Explorer, in KB with thousands
// separators.
begin
result := ''; // Fall-through value
if (aSize >= 0) then
begin
if (aSize = 0) then
result := '0KB' // Some files are actually zero-size.
else
if (aSize < 1024) then // Files smaller than 1KB reported as 1KB
result := '1KB'
else
result := Format('%3.0nKB', [aSize/1024]); // Display to nearest KB
end;
end;
function TForm1.FormatFileAttr(aAttr: integer): string;
// Format file attributes like Explorer
begin
result := ''; // Fall-through value
if ((aAttr and faReadOnly) <> 0) then
result := result + 'R';
if ((aAttr and faHidden) <> 0) then
result := result + 'H';
if ((aAttr and faSysFile) <> 0) then
result := result + 'S';
if ((aAttr and faArchive) <> 0) then
result := result + 'A';
end;
function TForm1.FileAge(const FileName: string): Integer;
// Get the last modification time for the file named FileName.
// SysUtils.FileAge deliberately ignores directories. This source was
// copied from SysUtils, and the directory if-statement was commented out.
var
Handle: THandle;
FindData: TWin32FindData;
LocalFileTime: TFileTime;
begin
Handle := FindFirstFile(PChar(FileName), FindData);
if Handle <> INVALID_HANDLE_VALUE then
begin
Windows.FindClose(Handle);
//if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
//begin
FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
if FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi,
LongRec(Result).Lo) then Exit;
//end;
end;
Result := -1;
end;
procedure TForm1.UOTextTarget1Drop(Sender: TObject; Acceptor: TWinControl;
const dropText: String; X, Y: Integer);
// A file drop has taken place on the listview, as specified by UOTextTarget1.
// Handle it by processing the files listed in UOTextTargett1.DroppedLines.
var
j: Integer;
aFileName: string;
S: string;
aLi: TListItem;
aSHFi: TSHFileInfo;
fileSize: integer;
fileDate: TDateTime;
fileAttr: integer;
begin
// Loop over all dropped file names
for j := 1 to UOTextTarget1.DroppedLines.Count do // Iterate
begin
// Get the filename
aFileName := UOTextTarget1.DroppedLines[j-1];
// Get the icon info, etc, from the shell
SHGetFileInfo(PChar(aFileName), 0, aSHFi, sizeOf(aSHFi),
SHGFI_ATTRIBUTES // Retrieves the file attribute flags.
or SHGFI_DISPLAYNAME // Retrieves the display name for the file.
or SHGFI_SYSICONINDEX // Retrieves the handle of the icon
or SHGFI_TYPENAME // Retrieves the type of item
or SHGFI_SMALLICON // Causes the small icon to be retrieved
);
// Add an empty item to the list
aLi := ListView1.Items.Add;
// Populate the list item with the file details
with aLi do
begin
// Caption of the item - display name
Caption := StrPas(aSHFi.szDisplayName);
// Image index in the system image list
ImageIndex := aSHFi.iIcon;
// The remainder of the information goes in the SubItems string list
// which shows all columns beyond the first in when ViewStyle is vsReport
// File name
SubItems.Add(aFileName);
// Size of file
fileSize := GetFileSize(aFileName);
// Write file size only if not a folder. See FormatFileSize above
if ((aSHFi.dwAttributes and SFGAO_FOLDER) = 0) then
SubItems.Add(FormatFileSize(fileSize))
else
SubItems.Add('');
// Type of file.
if (length(aSHFi.szTypeName) = 0) then
begin
// No file type. For something.Ext use "EXT File"
// just like Explorer.
s := UpperCase(ExtractFileExt(aFileName))+ ' File';
System.Delete(s, 1, 1);
SubItems.Add(s);
end
else
begin
SubItems.Add(aSHFi.szTypeName);
end;
// Time of last modification
// Explorer uses the short date and time formats that the user has
// set in the Control Panel Regional Settings, so we do too!
fileDate := FileDateToDateTime(FileAge(aFileName)); // Date as a TDateTime
SubItems.Add(FormatDateTime(ShortDateFormat+' '+ShortTimeFormat, fileDate));
// File attributes
fileAttr := FileGetAttr(aFileName);
SubItems.Add(FormatFileAttr(fileAttr));
end; // with
end; // for
end;
procedure TForm1.ListView1ColumnClick(Sender: TObject;
Column: TListColumn);
// Click on a column header. Here's where you'd call your code for sorting
// the data based on columns. This is not related to the example at hand, so
// we don't bother.
begin
if (ListView1.Items.Count > 0) then
MessageBox(Self.Handle, 'Sorting of columns is left as an exercise for the user!',
'UnitOOPS FileTest Demo', MB_OK + MB_ICONINFORMATION + MB_SETFOREGROUND);
end;
procedure TForm1.ListView1DblClick(Sender: TObject);
// If we double-click an item, launch it.
var
aLi: TListItem;
begin
aLi := ListView1.Selected;
// Is there a selection?
if assigned(aLi) then
begin
// Launch it. The file name is in SubItems[0] (see UOTextTarget1Drop() above.
ShellExecute(Handle, 'open', PChar(aLi.SubItems[0]), nil, nil, SW_SHOW);
end;
end;
procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
// Detect drags and initiate drag of shortcuts to the files
// Detect the drag by handling OnMouseDown, and using the Win32 call
// DragDetect()
var
aSL: TStringList;
aLi: TListItem;
begin
// Are we dragging?
if DragDetect(ListView1.Handle, POINT(X, Y)) then
begin
// Build a string list to hold the list of files we're dragging
aSL := TStringList.Create;
try
// Get the first selected item in the list view
aLi := ListView1.Selected;
// Now find the rest of the selected items
while assigned(aLI) do
begin
// Add the filename for the selection
aSL.Add(aLi.SubItems[0]);
// Go find the next selected item
aLi := ListView1.GetNextItem(aLi, sdAll, [isSelected]);
end; // while
// Now, we have the list of selections, which could be empty
if (aSL.Count > 0) then
begin
with UOTextSource1 do
begin
// Clear out the custom format data from any previous executions
CustomFormatData.Clear;
// 'Shell IDList Array' is the format to drag for shortcuts
// Use uoUtils.uoShellIDListFromFileList
CustomFormatData.AddFormat('Shell IDList Array',
uoShellIDListFromFileList('', aSL));
// 'Preferred DropEffect' tells the shell not to bother giving
// us the "copy here", "Move here", "Create shortcut here" menu
CustomFormatData.addFormat('Preferred DropEffect',
uoEncodeDWORDToString(DropEffectFromEnum(deLink)));
// The shortcuts you drag are usually arranged on the desktop e.g.
// cascading down and right. You could use the 'Shell Object Offsets'
// drag format to have them positioned in a different manner, if you
// like. Search for "Shell Object Offsets" (including the "") in the
// Win32 help that ships with Delphi 4 for more details, on in MSDN.
// Do the drag operation
Execute;
end;
end;
finally
aSL.Free;
end;
end;
end;
end.
Back to top
|
| Form source: fmFileTest.dfm |
object Form1: TForm1
Left = 226
Top = 154
Width = 579
Height = 325
Caption = 'File drop and shortcut drag demo'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Panel1: TPanel
Left = 0
Top = 0
Width = 571
Height = 33
Align = alTop
BevelOuter = bvNone
BorderWidth = 3
TabOrder = 0
object Label1: TLabel
Left = 3
Top = 3
Width = 565
Height = 27
Align = alClient
Caption =
'Drop lists of files from Explorer or other sources onto the list' +
' below. Execute any file by double-clicking it. Drag files fro' +
'm the list to make a shortcuts elsewhere.'
WordWrap = True
end
end
object Panel2: TPanel
Left = 0
Top = 254
Width = 571
Height = 44
Align = alBottom
BevelOuter = bvNone
TabOrder = 1
object Panel3: TPanel
Left = 474
Top = 0
Width = 97
Height = 44
Align = alRight
BevelOuter = bvNone
TabOrder = 0
object Button1: TButton
Left = 10
Top = 11
Width = 75
Height = 25
Caption = 'Clear list'
TabOrder = 0
OnClick = Button1Click
end
end
object RadioGroup1: TRadioGroup
Left = 5
Top = 2
Width = 337
Height = 38
Caption = 'List view style'
Columns = 4
ItemIndex = 3
Items.Strings = (
'Icons'
'Small Icons'
'List'
'Report')
TabOrder = 1
OnClick = RadioGroup1Click
end
end
object Panel4: TPanel
Left = 0
Top = 33
Width = 571
Height = 221
Align = alClient
BevelOuter = bvNone
BorderWidth = 3
Caption = 'Panel4'
TabOrder = 2
object ListView1: TListView
Left = 3
Top = 3
Width = 565
Height = 215
Align = alClient
OnDblClick = ListView1DblClick
Columns = <
item
Caption = 'Display Name'
Width = 100
end
item
Caption = 'File Name'
Width = 100
end
item
Alignment = taRightJustify
Caption = 'Size'
Width = 60
end
item
Caption = 'Type'
Width = 120
end
item
Caption = 'Modified'
Width = 120
end
item
Alignment = taRightJustify
Caption = 'Attributes'
Width = 60
end>
ReadOnly = True
MultiSelect = True
OnColumnClick = ListView1ColumnClick
OnMouseDown = ListView1MouseDown
TabOrder = 0
ViewStyle = vsReport
end
end
object UOTextTarget1: TUOTextTarget
AcceptorControl = ListView1
AcceptTextFormats = [dtfFiles]
OnDrop = UOTextTarget1Drop
Left = 104
Top = 177
end
object UOTextSource1: TUOTextSource
DropEffects = [deLink]
Left = 312
Top = 121
end
end
Back to top
|