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 endBack to top |