⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dropfile.pas

📁 一套很好用的系统控件: Drag and Drop Component Suite v4.0
💻 PAS
📖 第 1 页 / 共 2 页
字号:
  case DWORD(Effect) of
    DROPEFFECT_COPY: Windows.SetCursor(Screen.Cursors[crCopy]);
    DROPEFFECT_MOVE: Windows.SetCursor(Screen.Cursors[crMove]);
    DROPEFFECT_LINK: Windows.SetCursor(Screen.Cursors[crLink]);
    DROPEFFECT_SCROLL OR DROPEFFECT_COPY:
      Windows.SetCursor(Screen.Cursors[crCopyScroll]);
    DROPEFFECT_SCROLL OR DROPEFFECT_MOVE:
      Windows.SetCursor(Screen.Cursors[crMoveScroll]);
    DROPEFFECT_SCROLL OR DROPEFFECT_LINK:
      Windows.SetCursor(Screen.Cursors[crLinkScroll]);
  else UseDefaultCursors := true; //Use default NoDrop
  end;

end;

//--------------------------
// TARGET events...
//--------------------------

//******************* TFormFile.DropFileTarget1Enter *************************
procedure TFormFile.DropFileTarget1Enter(Sender: TObject;
  ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
begin
  //Note: GetDataOnEnter = true ...
  //saves the location (path) of the files being dragged.
  //Also flags if an EXE file.
  //This info will be used to set the default (ie. no Shift or Ctrl Keys pressed)
  //drag behaviour, whether COPY, MOVE or LINK
  if (DropFileTarget1.Files.count > 0) then
  begin
    SourcePath := extractfilepath(DropFileTarget1.Files[0]);
    if (DropFileTarget1.Files.count = 1) and
         (lowercase(extractfileext(DropFileTarget1.Files[0])) ='.exe') then
      IsEXEfile := true else 
      IsEXEfile := false;
  end;
end;

//******************* TFormFile.DropFileTarget1Drop *************************
procedure TFormFile.DropFileTarget1Drop(Sender: TObject;
  ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
var
  i, SuccessCnt: integer;
  NewFilename: string;
  newPath: string;
begin
  SuccessCnt := 0;
  NewPath := AddSlash(DirectoryOutline.Directory);
  with DropFileTarget1 do
  begin
    for i := 0 to Files.count-1 do
    begin
      NewFilename := NewPath+ExtractFilename(Files[i]);

      if (Effect = DROPEFFECT_LINK) then
      begin
        CreateLink(Files[i], NewFilename);
        inc(SuccessCnt);
        continue;
      end;

      if NewFilename = Files[i] then
      begin
        windows.messagebox(handle,
          'The destination folder is the same as the source!',
          'DropSource Demo', mb_iconStop or mb_OK);
        Break;
      end;
      if not fileexists(NewFilename) then
        try
          if (Effect = DROPEFFECT_MOVE) and
              renamefile(Files[i],NewFilename) then
            inc(SuccessCnt)
          else if (Effect = DROPEFFECT_COPY) and
                    copyfile(PChar(Files[i]),PChar(NewFilename),true) then
            inc(SuccessCnt);
        except
        end;
    end; {for loop}

    if (Effect = DROPEFFECT_MOVE) then
      StatusBar1.simpletext :=
        format('%d file(s) were moved.   Files dropped at point (%d,%d).',
          [SuccessCnt, Point.x,Point.y])
    else if (Effect = DROPEFFECT_COPY) then
      StatusBar1.simpletext :=
        format('%d file(s) were copied.   Files dropped at point (%d,%d).',
          [SuccessCnt, Point.x,Point.y])
    else
      StatusBar1.simpletext :=
        format('%d file(s) were linked.   Files dropped at point (%d,%d).',
          [SuccessCnt, Point.x,Point.y]);
  end;
end;

//******************* TFormFile.DropFileTarget1GetDropEffect *************************
procedure TFormFile.DropFileTarget1GetDropEffect(Sender: TObject;
  ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
begin
  //Note: The 'Effect' parameter (on event entry) is the
  //set of effects allowed by both the source and target.
  //Use this event when you wish to override the Default behaviour...

  //We're only interested in ssShift & ssCtrl here so
  //mouse buttons states are screened out ...
  ShiftState := ([ssShift, ssCtrl] * ShiftState);

  //if source and target paths are the same then DROPEFFECT_NONE
  if (AddSlash(DirectoryOutline.Directory) = SourcePath) then
    Effect := DROPEFFECT_NONE
  //else if Ctrl+Shift...
  else if (ShiftState = [ssShift, ssCtrl]) and
    (Effect and DROPEFFECT_LINK<>0) then Effect := DROPEFFECT_LINK
  //else if Shift...
  else if (ShiftState = [ssShift]) and
    (Effect and DROPEFFECT_MOVE<>0) then Effect := DROPEFFECT_MOVE
  //else if Ctrl...
  else if (ShiftState = [ssCtrl]) and
    (Effect and DROPEFFECT_COPY<>0) then Effect := DROPEFFECT_COPY
  //else if dragging a single EXE file then default to LINK ...
  else if IsEXEfile and (Effect and DROPEFFECT_LINK<>0) then
    Effect := DROPEFFECT_LINK
  //else if source and target drives are the same then default to MOVE
  else if (SourcePath <> '') and (DirectoryOutline.Directory[1] = SourcePath[1]) and
    (Effect and DROPEFFECT_MOVE<>0) then Effect := DROPEFFECT_MOVE
  else if (Effect and DROPEFFECT_COPY<>0) then Effect := DROPEFFECT_COPY
  else if (Effect and DROPEFFECT_MOVE<>0) then Effect := DROPEFFECT_MOVE
  else if (Effect and DROPEFFECT_LINK<>0) then Effect := DROPEFFECT_LINK
  else Effect := DROPEFFECT_NONE;

  //Adding DROPEFFECT_SCROLL to Effect will now
  //automatically scroll the target window.
  if (Point.Y < 15) or (Point.Y > Listview1.clientheight-15) then
    Effect := Effect or integer(DROPEFFECT_SCROLL);
end;

//----------------------------------------------------------------------------
// TDirectoryThread methods
//----------------------------------------------------------------------------

//OK, we're showing off ... it's a little fiddly for a demo ...
//but still you can see what can be done.

//******************* TDirectoryThread.Create *************************
constructor TDirectoryThread.Create(ListView: TListView; Dir: string);
begin
  inherited Create(True);

  fListView := ListView;
  FreeOnTerminate := true;
  Priority := tpLowest;
  fDirectory := Dir;
  FWakeupEvent := windows.CreateEvent(nil, False, False, nil);
  FFiles := TStringList.Create;

  Resume;
end;

//******************* TDirectoryThread.Destroy *************************
destructor TDirectoryThread.Destroy;
begin
  CloseHandle(FWakeupEvent);
  FFiles.Free;
  inherited Destroy;
end;

//******************* TDirectoryThread.WakeUp *************************
procedure TDirectoryThread.WakeUp;
begin
  SetEvent(FWakeupEvent);
end;

//******************* TDirectoryThread.SetDirectory *************************
procedure TDirectoryThread.SetDirectory(Value: string);
begin
  if (Value = FDirectory) then
    exit;
  FDirectory := Value;
  WakeUp;
end;

//******************* TWaitThread.ScanDirectory *************************
procedure TDirectoryThread.ScanDirectory;
var
  sr: TSearchRec;
  res: integer;
begin
  FFiles.Clear;
  res := FindFirst(AddSlash(fDirectory)+'*.*', 0, sr);
  try
    while (res = 0) and (not Terminated) do
    begin
      if (sr.name <> '.') and (sr.name <> '..') then
        FFiles.Add(lowercase(sr.name));
      res := FindNext(sr);
    end;
  finally
    FindClose(sr);
  end;
end;

//******************* TDirectoryThread.UpdateListView *************************
procedure TDirectoryThread.UpdateListView;
var
  NewItem : TListItem;
  i: integer;
begin
  with fListView.items do
  begin
    beginupdate;
    clear;
    for i := 0 to FFiles.Count-1 do
    begin
      NewItem := Add;
      NewItem.Caption := FFiles[i];
    end;
    if count > 0 then fListView.itemfocused := item[0];
    endupdate;
  end;
  FFiles.Clear;
end;

//******************* TWaitThread.Execute *************************
procedure TDirectoryThread.Execute;
var
  fFileChangeHandle : THandle;
begin

  //OUTER LOOP - which will exit only when terminated ...
  //  directory changes will be processed within this OUTER loop
  //  (file changes will be processed within the INNER loop)
  while (not Terminated) do
  begin
    ScanDirectory;
    Synchronize(UpdateListView);

    //Monitor directory for file changes
    fFileChangeHandle :=
      FindFirstChangeNotification(PChar(fDirectory), false, FILE_NOTIFY_CHANGE_FILE_NAME);
    if (fFileChangeHandle = INVALID_HANDLE_VALUE) then
      //Can't monitor filename changes! Just wait for change of directory or terminate
      WaitForSingleObject(FWakeupEvent, INFINITE)
    else
      try
        //This function performs an INNER loop...
        ProcessFilenameChanges(fFileChangeHandle);
      finally
        FindCloseChangeNotification(fFileChangeHandle);
      end;
  end;
end;

//******************* TWaitThread.ProcessFilenameChanges *************************
procedure TDirectoryThread.ProcessFilenameChanges(fcHandle: THandle);
var
  WaitResult : DWORD;
  HandleArray : array[0..1] of THandle;
begin
  HandleArray[0] := FWakeupEvent;
  HandleArray[1] := fcHandle;
  //INNER LOOP -
  //  which will exit only if terminated or the directory is changed
  //  filename changes will be processed within this loop
  while (not Terminated) do
  begin
    //wait for either filename or directory change, or terminate...
    WaitResult := WaitForMultipleObjects(2, @HandleArray, False, INFINITE);

    if (WaitResult = WAIT_OBJECT_0 + 1) then //filename has changed
    begin
      repeat //collect all immediate filename changes...
        FindNextChangeNotification(fcHandle);
      until Terminated or (WaitForSingleObject(fcHandle, 0) <> WAIT_OBJECT_0);
      if Terminated then break;
      //OK, now update (before restarting inner loop)...
      ScanDirectory;
      Synchronize(UpdateListView);
    end else
    begin // Either directory changed or terminated ...
      //collect all (almost) immediate directory changes before exiting...
      while (not Terminated) and
        (WaitForSingleObject(FWakeupEvent, 100) = WAIT_OBJECT_0) do;
      break;
    end;
  end;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -