Drag and Drop больше не работает в моем проекте в Delphi - PullRequest
2 голосов
/ 03 декабря 2010

Эта тема, очевидно, обсуждалась здесь снова и снова, но теперь у меня просто не осталось вариантов с моей точки зрения.

ОС: Windows XP SP3

Итак, вот Пример перетаскивания для RichEdit Я использую в своем приложении:

procedure TForm1.AcceptFiles( var msg : TMessage ); // or TWMDROPFILES
const
  cnMaxFileNameLen = 255;
var
  i,
  nCount     : integer;
  acFileName : array [0..cnMaxFileNameLen] of char;
begin
  // find out how many files we're accepting
  nCount := DragQueryFile( msg.WParam, // or msg.Drop
                           $FFFFFFFF,
                           acFileName,
                           cnMaxFileNameLen );

  // query Windows one at a time for the file name
  for i := 0 to nCount-1 do
  begin
    DragQueryFile( msg.WParam, { or msg.Drop} i,
                   acFileName, cnMaxFileNameLen );

    // do your thing with the acFileName
    MessageBox( Handle, acFileName, '', MB_OK );
  end;

  // let Windows know that you're done
  DragFinish( msg.WParam ); // or msg.Drop
end;

Проблема в том, что после некоторых недавних изменений (к сожалению, я не использую SVN, поэтому не могу отследить, какой коммит создавал эту проблему) Перетаскивание больше не работает.

Я использовал точки останова безуспешно в каждом событии, которое может быть как-то связано (вызвано):

RichEditMouseOver;

RichEditChange;

FormClick;

Мое приложение обрабатывает следующие WM:

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

procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;

procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;

procedure WMGetMinMaxInfo(var AMsg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;

procedure CMDialogKey(var Msg: TCMDialogKey ); message CM_DIALOGKEY;

В пустом проекте с TRichEdit на форме - все работает нормально.

Также попытался изменить DragAcceptFiles() Form1.Handle на RichEdit.Handle - все равно не повезло.

При отображении параметров nCount и acFileName acFileName не имеет пути к файлу перетаскиваемого файла ... Почему ????

В настоящее время я просто понятия не имею, что делает параметр acFileName теряющим путь к перетаскиваемым файлам. Не могли бы вы подсказать, где скрывается проблема?

Ответы [ 3 ]

4 голосов
/ 01 февраля 2011

Извлечено с официального форума поддержки Microsoft :

Возможной причиной невозможности перетаскивания файлов в приложение может быть уровень целостности UAC (IL),При включенном UAC в Vista или Win7 по умолчанию перетаскивание не может происходить от процесса с низким IL до процесса с высоким IL.Пожалуйста, проверьте, повышено ли ваше приложение (запущено от имени администратора) при возникновении проблемы.

Если вы не хотите отключать UAC, вы можете попробовать просто отключить UIPI (изоляция привилегий пользовательского интерфейса).

Откройте regedit и перейдите по адресу: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Policies \ System

Добавьте новое DWORD (32-разрядное) значение с именем EnableUIPI и установите его в 0.

Перезагрузите машину и посмотрите, будет ли она вести себя так, как вы хотите.

3 голосов
/ 03 декабря 2010

Я собираюсь попробовать психическую отладку здесь;Вы говорите, что «больше не работает», подразумевая, что в какой-то момент это сработало.Хотя вы не упомянули, какую ОС вы используете, я также собираюсь предположить, что вы используете Windows Vista или Windows 7 (или соответствующую версию сервера).

Я подозреваю, что происходитчто ваше приложение работает как пользователь или уровень привилегий, отличный от оболочки.Windows не позволяет перетаскивать (особенно перетаскивать файлы) данные из приложения на одном уровне привилегий в другое.Если вы запускаете это из IDE, а IDE работает от имени администратора, то порожденные процессы также работают на этом уровне.

Убедитесь, что ваше приложение действительно работает как вошедший в систему пользователь.Меня укусило это слишком много раз, чтобы сосчитать, и оно настолько тонко, что никогда не сразу становится ясно, что происходит.

2 голосов
/ 01 февраля 2011

Боюсь, я не эксперт в том, как на самом деле работает перетаскивание файлов. Поэтому я не могу просмотреть твой код и выяснить, в чем дело.

Что я могу сделать, так это дать вам код, который я использую. Теперь он работает под Delphi 2009 на XP, Vista и Windows 7. Он также работал, когда я ранее использовал Delphi 4 на Windows 98 и Windows XP.

Возможно, вы сможете выяснить, что не так в вашем коде, используя это, или вы можете попробовать использовать или адаптировать этот код. Из книги: «Delphi 3 - Дизайн пользовательского интерфейса», страницы 169 - 171.

Если я пропустил важную процедуру, дайте мне знать в комментарии, и я отредактирую свой ответ, чтобы включить его.

type
  TMainForm = class(TForm)
    procedure WMDropFiles(var WinMsg: TMessage);
              message wm_DropFiles;
    procedure AppMessageHandler(var Msg: TMsg; var Handled: Boolean);

procedure TMainForm.FormShow(Sender: TObject);
begin
  DragAcceptFiles(Handle, true);
  Application.OnMessage := AppMessageHandler;
end;

procedure TLogoAppForm.WMDropFiles(var WinMsg: TMessage);
const
  BufSize = 255;
var
  TempStr : array[0..BufSize] of Char;
  NumDroppedFiles, I: integer;
  Filenames: TStringList;
begin
  NumDroppedFiles := DragQueryFile(TWMDropFiles(WinMsg).Drop, $ffffffff, nil, 0);
  if NumDroppedFiles >= 1 then begin
    Filenames := TStringList.Create;
    for I := 0 to NumDroppedFiles - 1 do begin
      DragQueryFile(TWMDropFiles(WinMsg).Drop, I, TempStr, BufSize);
      Filenames.Add(TempStr);
    end;
    OpenFiles(Filenames, '');
    Filenames.Free;
  end;
  DragFinish(TWMDropFiles(WinMsg).Drop);
  WinMsg.Result := 0;
end;

procedure TLogoAppForm.AppMessageHandler(var Msg: TMsg; var Handled: Boolean);
begin
  if (Msg.Message = WM_DropFiles) and IsIconic(Application.Handle) then begin
    Perform(Msg.Message, Msg.Wparam, Msg.lParam);
    Handled := true;
  end
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...