这个话题显然已经在这里反复出现了,但现在我从我的角度来看已经没有选择了。
操作系统: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;
问题是在最近的一些更改之后(unforutinetly我没有使用任何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参数丢失拖动文件路径。你能说一下问题隐藏在哪里吗?
答案 0 :(得分:4)
摘自official Microsoft support forum:
不存在的可能原因 能够拖拽将文件拖放到 应用程序可以是UAC完整性 水平(IL)。在Vista中启用UAC 或Win7,不允许拖放 从低IL过程发生到高 IL进程默认情况下。请检查 您的申请是否提升 (当管理员运行时)问题 发生的情况。
如果您不想禁用UAC,可以尝试禁用UIPI(用户界面权限隔离)。
打开注册表并转到:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Policies \ System
添加一个名为EnableUIPI的新DWORD(32位)值并将其设置为0.
重新启动机器并查看它是否符合您的要求。
答案 1 :(得分:3)
我要在这里尝试一下心理调试;你说它“不再起作用”,暗示它在某些方面起作用。虽然你还没有提到你正在使用哪种操作系统,但我也认为你使用的是Windows Vista或Windows 7(或相关的服务器版本)。
我怀疑发生的事情是您的应用程序作为与shell不同的用户或权限级别运行。 Windows不允许拖动(尤其是文件拖动)数据从一个权限级别的应用程序转移到另一个权限级别。如果您从IDE运行此命令,并且IDE以管理员身份运行,则生成的进程也在该级别运行。
检查以确保您的应用程序实际上以登录用户身份运行。我被这个被咬了太多次,并且非常微妙,以至于对于发生的事情来说,它永远不会立即显而易见。
答案 2 :(得分:2)
我担心我不是拖拉文件实际工作原理的专家。所以我无法通过你的代码弄清楚出了什么问题。
我能做的就是给你我使用的代码。它现在适用于我在Delphi 2009上的XP,Vista和Windows 7.当我以前在Windows 98和Windows XP上使用Delphi 4时,它也有效。
也许您可以使用此功能找出代码中的错误,或者您可能想尝试使用或调整此代码。它最初出自以下书:“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;