如何为未注册的文件扩展名显示“打开方式”对话框?

时间:2012-02-10 08:15:38

标签: windows delphi winapi

我想让用户为当前未注册的文件扩展名选择一个关联(打开)。

目前我告诉API使用ShellExecute打开文件,它会返回ERROR_NO_ASSOCIATION错误代码。

有没有办法告诉API它应该让用户选择一个新关联?

3 个答案:

答案 0 :(得分:11)

我用

procedure ShellOpenAs(const AFileName: string; AHandle: HWND);
begin
  ShellExecute(AHandle, 'open', PChar('rundll32.exe'), PChar('shell32.dll,OpenAs_RunDLL ' + AFileName), nil, SW_SHOWNORMAL);
end;

修改(受David的评论和https://stackoverflow.com/a/13229516/1431618启发): 可以通过直接调用ShellExecute来省略RunDll32OpenAs_RunDLL

procedure OpenAs_RunDLL(hwnd: HWND; hinst: HINST; lpszCmdLine: LPSTR; nCmdShow: Integer); stdcall; external shell32;

procedure ShellOpenAs(AHandle: HWND; const AFileName: string);
begin
  OpenAs_RunDLL(AHandle, HInstance, PChar(AFileName), SW_SHOWNORMAL);
end;

Windows Vista及更高版本上也有SHOpenWithDialog。 (我觉得有趣的是,微软写了一个与RunDLL兼容的入口点,但直到Vista都没有提供常规的API函数。)

答案 1 :(得分:3)

使用以下代码,您将获得解决方案 -

public const uint SEE_MASK_INVOKEIDLIST = 12;//add this line in your code


CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE);
SHELLEXECUTEINFO sei = { sizeof(sei) };
sei.nShow = SW_SHOWNORMAL;
sei.lpVerb = "openas";
sei.lpFile = "C:\\yourfile.ext";
sei.lfmask= SEE_MASK_INVOKEIDLIST;//add this line in your code
ShellExecuteEx(&sei);

SEE_MASK_INVOKEIDLIST this variable set "Verb" from presented system registry.

答案 2 :(得分:3)

只是不要使用显式动词。使用像'open'这样的特定动词是一个很大的错误:

  • 'open'可能不是默认动词(例如,可能是'play','edit'或'run')
  • 'open'可能不存在

简单地将nil作为动词传递是一种更正确的方法。系统将自动选择最合适的动词:

  • 如果设置了
  • ,将使用默认动词 如果没有设置默认动词,将使用
  • 'open'动词
  • 如果没有默认和“打开”动词,
  • 将使用第一个动词
  • 如果未分配动词 - 系统将显示“打开方式”对话框

换句话说,简单

ShellExecute(0, nil, 'C:\MyFile.StrangeExt', ...);

将显示“打开方式”对话框。

如果您需要特定操作,请仅使用特定动词。例如。 'print','explore','runas'。否则 - 只传递nil。