Добавить комментарий

Delphi

Drag And Drop из проводника Windows в приложение Delphi

Поскольку в перетаскивании участвует сторонне приложение, реализация механики будет существенно отличаться от Drag&Drop внутри одного приложения.

Отправитель - проводник Windows. Старт перетаскивания, подготовка информации о перетаскиваемых объектах - всё это теперь не наша забота.

Процесс перетаскивания тоже осуществляется Windows. Ей нужно знать в какие приложения можно сбросить перетаскиваемый объект, а в какие нет(и рисовать соответственный курсор мышки во время перетаскивания).

Windows решает эту проблему просто. Сброс возможен только в окно (в терминах Windows), только целиком(окно или принимает объекты или нет, ни каких "приму в левой половине"), и готовое к приёму окно должно само об этом заявить. Соответственно, если окно больше не желает принимать файлы из проводника, и об этом оно должно само уведомить Windows.

Чтобы зарегистрировать готовность окна принимать Drag&Drop из проводника и отменить его нужно вызвать DragAcceptFiles(WND: HWND; Accept: LongBool);

Аргументами служат Хэндл окна и булевское значение, готово окно принимать Drag&Drop или нет. Чтобы принимать перетаскивания из проводника в форму Form1, где-то на старте приложения нужно вызвать  DragAcceptFiles(Form1.Handle, True);, а перед завершением: DragAcceptFiles(Form1.Handle, False);

Когда происходит дроп, Windows отправляет окну сообщение WM_DROPFILES, и передаёт в нём необходимую информацию о перетаскиваемых объектах. Чтобы поймать его, класс, зарегистрировавшийся на приём Drag&Drop-а должен обладать обработчиком:

procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;

Типичная ситуация, когда дроп должен происходить не в любое место формы, а в отдельные контролы, TMemo или TTreeView. Любой наследник от TWinControl является окном Windows, обладает своим Handle и может быть заявлен за получатель Drag&Drop-а.

Обработчик WM_DROPFILES должен быть у того класса, который регистрируется как получатель. Если это TTreeView, то и обработчик должен быть у этого класса, а не у формы... smiley

Пример обработчика для собственного класса TMyMemo:

  TMyMemo = class(TMemo)
              procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
            end;
...

{ TMyMemo }

procedure TMyMemo.WMDropFiles(var Msg: TWMDropFiles);
var
    i          : Integer;
    FileName   : string;
    DropPoint  : TPoint;
begin
  // Msg.Drop содержит хэндл структуры с информацией о
  //  перетаскиваемых файлах.
  try
    // Получаем точку сброса внутри окна, если нам важно.
    DragQueryPoint(Msg.Drop, DropPoint);
    // Например, если мы дерево, и хочется понять, на какой узел сброшены файлы.

    // Этот DragQueryFile вернёт количество перетаскивыаемых файлов.
    for i := 0 to DragQueryFile(Msg.Drop, $FFFFFFFF, nil, 0) - 1  do
    begin
      // Подготавливаем буфер для получения имени.
      // Этот DragQueryFile вернёт размер имени i-го файла.
      // Займём дополнительный символ под терминирующий 0.
      SetLength(FileName, DragQueryFile(Msg.Drop, i, nil, 0) + 1);
      // Получаем имя.
      DragQueryFile(Msg.Drop, I, PChar(FileName), Length(FileName));
      // Делаем что-то полезное. Этот TMemo просто показывает имена файлов,
      //  которые в него сбросили.
      Lines.Add(FileName);
    end;
  finally
    // Разрешаем Windows забыть про это перетаскивание.
    DragFinish(Msg.Drop);
  end;
  // Сообщаем, что событие нами обработано.
  Msg.Result := 0;
end;

 

Метки:

Filtered HTML

  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Допустимые HTML-теги: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Строки и абзацы переносятся автоматически.
  • Вы можете цитировать другие сообщения, используя тэг [quote]

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и абзацы переносятся автоматически.