You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Delphi应用中调用Windows 11原生分享功能的技术问询

在Delphi中调用Windows 10/11原生文件分享对话框

以下是两种可行的解决方案,针对你之前尝试失败的问题进行修正和补充:

方案一:修复IContextMenu调用(原生Shell上下文菜单方式)

之前的错误源于未正确初始化调用参数,需使用宽字符版本的命令结构并设置对应标志:

uses
  Winapi.Windows, Winapi.ShlObj, Winapi.ActiveX, System.SysUtils;

procedure ShowShareDialogViaContextMenu(const FilePath: string; ParentHWND: HWND);
var
  ShellItem: IShellItem;
  ContextMenu: IContextMenu;
  CmdInfo: CMINVOKECOMMANDINFOEX;
  hr: HRESULT;
begin
  // 创建目标文件的IShellItem实例
  hr := SHCreateItemFromParsingName(PWideChar(FilePath), nil, IID_IShellItem, ShellItem);
  if Failed(hr) then Exit;

  // 获取文件的上下文菜单接口
  hr := ShellItem.BindToHandler(nil, BHID_SFUIObject, IID_IContextMenu, ContextMenu);
  if Failed(hr) then Exit;

  // 初始化调用参数,必须使用宽字符版本
  ZeroMemory(@CmdInfo, SizeOf(CmdInfo));
  CmdInfo.cbSize := SizeOf(CMINVOKECOMMANDINFOEX);
  CmdInfo.fMask := CMIC_MASK_UNICODE or CMIC_MASK_HWND;
  CmdInfo.hwnd := ParentHWND;
  CmdInfo.lpVerbW := PWideChar('Share'); // 指定Share动词
  CmdInfo.nShow := SW_SHOWNORMAL;

  // 执行分享命令
  hr := ContextMenu.InvokeCommand(TCMInvokeCommandInfoEx(CmdInfo));
  if Failed(hr) then
    ShowMessage('调用失败,错误码: ' + IntToHex(hr, 8));
end;

方案二:使用WinRT DataTransferManager API(推荐,Win10/11原生支持)

通过调用WinRT的DataTransferManager接口,直接唤起系统分享对话框,兼容性更好:

uses
  Winapi.Windows, Winapi.ActiveX, System.SysUtils;

// 定义所需的WinRT COM接口和CLSID
const
  CLASS_DataTransferManager: TGUID = '{0A72DE86-0A5B-4D6B-877B-461CC66F8C3C}';
  IID_IDataTransferManager: TGUID = '{5BBDD811-1F42-4FF3-851C-8F30D9B565D8}';
  CLASS_DataPackage: TGUID = '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}';
  IID_IDataPackage: TGUID = '{3A3DCD6C-3EAB-43DC-BCDE-45671CE800C8}';
  IID_IStorageItemArray: TGUID = '{4E469486-6D7A-4C0F-A768-192B437B3F11}';

type
  IDataTransferManager = interface(IUnknown)
    ['{5BBDD811-1F42-4FF3-851C-8F30D9B565D8}']
    function SetDataPackage(value: IDataPackage): HRESULT; stdcall;
    function ShowShareUIForWindow(hWnd: HWND): HRESULT; stdcall;
  end;

  IDataPackage = interface(IUnknown)
    ['{3A3DCD6C-3EAB-43DC-BCDE-45671CE800C8}']
    function SetStorageItems(value: IStorageItemArray; readOnly: Boolean): HRESULT; stdcall;
  end;

function StorageItemFactory_GetItemsFromPaths(itemCount: UINT; const items: PWideChar; out result: IStorageItemArray): HRESULT; stdcall; external 'windows.storage.dll' name 'StorageItemFactory_GetItemsFromPaths';

procedure ShowSystemShareDialog(const FilePath: string; ParentHWND: HWND);
var
  hr: HRESULT;
  DataTransferManager: IDataTransferManager;
  DataPackage: IDataPackage;
  StorageItems: IStorageItemArray;
  FilePathArray: TArray<string>;
begin
  // 初始化WinRT环境
  hr := RoInitialize(RO_INIT_MULTITHREADED);
  if Failed(hr) then Exit;
  try
    // 获取DataTransferManager实例
    hr := CoCreateInstance(CLASS_DataTransferManager, nil, CLSCTX_INPROC_SERVER, IID_IDataTransferManager, DataTransferManager);
    if Failed(hr) then Exit;

    // 创建DataPackage用于封装分享内容
    hr := CoCreateInstance(CLASS_DataPackage, nil, CLSCTX_INPROC_SERVER, IID_IDataPackage, DataPackage);
    if Failed(hr) then Exit;

    // 准备要分享的文件路径数组
    SetLength(FilePathArray, 1);
    FilePathArray[0] := FilePath;

    // 将文件路径转换为WinRT存储项数组
    hr := StorageItemFactory_GetItemsFromPaths(Length(FilePathArray), @FilePathArray[0], StorageItems);
    if Failed(hr) then Exit;

    // 将文件添加到DataPackage
    hr := DataPackage.SetStorageItems(StorageItems, False);
    if Failed(hr) then Exit;

    // 设置分享内容并唤起对话框
    hr := DataTransferManager.SetDataPackage(DataPackage);
    if Succeeded(hr) then
      DataTransferManager.ShowShareUIForWindow(ParentHWND);
  finally
    RoUninitialize;
  end;
end;

补充:失败原因说明

  1. IContextMenu方案失败:未设置CMIC_MASK_UNICODE标志,且使用了ANSI版本的调用结构,导致参数解析错误。
  2. ShellExecute方案失败:"Share"并非文件关联的标准动词,而是Shell上下文菜单扩展提供的自定义动词,无法通过ShellExecute直接触发。

内容的提问来源于stack exchange,提问作者MohsenB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 18:17:43