Win10下UWP链接拖放解析接口(Qt)

注:本文仅说明流程,具体的分析涉及太多东西

在Win7及以前,解析快捷方式目标程序和参数等信息,可以使用IShellLink。创建对应的COM实例,加载lnk文件,通过GetPath、GetArguments读取。但对于Win10 UWP程序创建的快捷方式,获取不到任何信息。

UWP快捷方式(或磁贴,将开始桌面的磁贴拖入到窗口)的解析,需要使用Vista系统之后提供的IShellItem2::GetProperty,属于Windows Property System的内容(里面东西很多,以后再慢慢了解)。

IShellItem2::GetProperty接口需要两个参数:

  1. REFPROPERTYKEY结构
    在propkey.h头文件中预定了大量的结构,包括与快捷方式相关的PKEY_Link开头的结构。

  2. PROPVARIANT指针
    存储GetProperty的结果,需要使用PropVariantClear来释放动态申请的空间,比如字符串。

大概流程如下:

  1. 得到快捷方式或磁铁的PCIDLIST_ABSOLUTE结构,也就是一个ITEMIDLIST结构

    对于拖放操作,文件(包括快捷方式)、开始桌面磁贴,这些数据存在于Shell IDList Array格式中,这个结构比较复杂,是多个文件ITEMIDLIST合并后的复合结构。ITEMIDLIST有绝对和相对之分,类似文件的绝对和相对路径。需要通过以下方式转换:

    //data是保存Shell IDList Arra结构的字节序列指针
    //第一个4字节宽度保存了文件数量count,紧接着4字节是拖放多个文件的父文件夹的ITEMIDLISTdata中的偏移量
    //后面count个4字节是各文件的ITEMIDLISTdata中的偏移量,与父文件夹的ITEMIDLIST合并得到PCIDLIST_ABSOLUTE
    int count = *(const int *)(data);
    int offset = sizeof(unsigned);
    int idlist_offset = *(int *)(data + offset);
    LPCITEMIDLIST parent_id = LPCITEMIDLIST(data + idlist_offset);
    for (int i = 0; i < count; ++i)
    {
        offset += sizeof(unsigned);
        idlist_offset = *(int *)(data + offset);
        LPCITEMIDLIST child = LPCITEMIDLIST(data + idlist_offset);
        LPITEMIDLIST abspidl = ILCombine(parent_id, child); 
    }

    对于已经有了快捷方式的绝对路径字符串,IShellLink::GetIDList 也可以获取,不过获取的ITEMIDLIST已经是目标程序。或者使用其他通用的转换方式。

  2. 调用SHCreateItemFromIDList创建一个IShellItem2实例,针对不同类型数据使用不同的Property Key。

    IShellItem2 *shell_item = NULL;
    SHCreateItemFromIDList(abspidl, IID_PPV_ARGS(&shell_item));
    if (shell_item)
    {
        PROPVARIANT var{ 0 };
        shell_item->GetProperty(PKEY_AppUserModel_ID, &var);
        if (var.vt == VT_LPWSTR)
        {
            OutputDebugString(var.pwszVal);
        }
        PropVariantClear(&var);
        shell_item->Release();
    }

    以下是对常见的拖放做了测试,可能需要通过结果区分不同类型(有些文件快捷方式,如VS,也存在AppUserModelID属性):

    类型 Property Key 结果
    文件 PKEY_ParsingPath 文件绝对路径
    PKEY_ParsingName、PKEY_FileName 文件名
    PKEY_FileExtension 文件后缀
    文件的快捷方式(非UWP) PKEY_Link_TargetParsingPath 目标文件路径
    PKEY_Link_Arguments 快捷方式参数
    网页的快捷方式 PKEY_Link_TargetParsingPath、PKEY_Link_TargetUrl 网址
    UWP快捷方式 PKEY_Link_TargetParsingPath UWP程序的AppUserModelID
    UWP磁贴 PKEY_AppUserModel_ID、PKEY_ParsingName、PKEY_ParsingPath UWP程序的AppUserModelID
    我的电脑、回收站等 PKEY_NamespaceCLSID CLSID(GUID)指针,可以使用StringFromCLSID转换到字符串

你可能感兴趣的:(Windows开发)