Windows 8启动屏幕平铺,基于桌面快捷方式

本文关键字:于桌面 桌面 快捷方式 启动 屏幕 Windows | 更新日期: 2023-09-27 18:06:35

我有一个当前工作的代码(c#,但不重要),通过在特殊目录(如%APPDATA%'Microsoft'Windows'Start Menu'Programs%LOCALAPPDATA%'Microsoft'Windows'Application Shortcuts)中创建快捷文件[.lnk],为Windows 8开始屏幕添加一个平纹。我已经搜索并发现了几个有用的工具,如lnk-parser和OblyTile,它们有助于清除有关所涉及的怪癖的几个方面。我也找到了许多与这个主题相关的文章和问题,但没有一篇能完全满足我的具体需求。

我使用IShellLink (COM互操作)来创建快捷方式和IPropertyStore (相同的对象实例)来添加一些明显需要的属性到链接文件。我的具体问题是:

创建的tile几乎在每个方面都像预期的那样工作。它运行预期的命令,具有预期的背景色和前景色,并显示自定义关联图标( .png image 144x144)。问题是,即使它在链接文件[System.ItemTypeText]中嵌入了一个自定义标签字符串,它也只是显示物理文件的名称减去扩展名。这并不是那么可怕,但是我更希望Windows能够尊重嵌入的属性而不是文件名。

链接文件中可能缺少什么导致这种行为而不是期望的行为?


<标题> 奖金

通过使用IPropertyStore,我遇到了几个所谓的"属性集",它们只是根据它们的GUID分组的属性。我对集合 {b725f130-47ef-101a-a5f1-02608c9eebac} {86d40b4d-9069-443c-819a-2a54090dccec}{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}特别感兴趣(后者包含无处不在的 System.AppUserModel.ID )。

附加问题:您能指出任何记录这两个属性集中的任何一个(或两个)的资源吗?我的意思是,每个属性是什么意思,它们是如何被Windows解释的。这可能比主要问题更有帮助。不管是官方的还是非官方的。

<标题>注意

根据需求,通过命令行调用OblyTile不是一个选项。根据我所观察到的,我可能需要在链接的目标文件父目录中添加一个自定义resources.pri文件。如果可能的话,最好避免这种情况,因为该格式没有文档。

<标题> 示例代码

ShellLink类是一个普通的&围绕IShellLinkIPropertyStore COM接口的无聊包装。它工作得很好,我完全确定问题不在那里。

using System;
using System.IO;
namespace Shell32NET
{
    public static class Win8Tiles
    {
        #region Fields
        /// <summary>
        /// b725f130-47ef-101a-a5f102608c9eebac
        /// </summary>
        static readonly Guid ItemTypeGroup = new Guid(
            0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac
            );
        /// <summary>
        /// b725f130-47ef-101a-a5f102608c9eebac, 4
        /// </summary>
        static readonly PropertyKey SystemItemTypeText = new PropertyKey(ItemTypeGroup, 4);
        /// <summary>
        /// 86d40b4d-9069-443c-819a2a54090dccec
        /// </summary>
        static readonly Guid TilePropertiesGroup = new Guid(
            0x86d40b4d, 0x9069, 0x443c, 0x81, 0x9a, 0x2a, 0x54, 0x09, 0x0d, 0xcc, 0xec
            );
        /// <summary>
        /// 86d40b4d-9069-443c-819a2a54090dccec, 2
        /// </summary>
        static readonly PropertyKey TileSmallImageLocation = new PropertyKey(TilePropertiesGroup, 2);
        /// <summary>
        /// 86d40b4d-9069-443c-819a2a54090dccec, 4
        /// </summary>
        static readonly PropertyKey TileBackgroundColor = new PropertyKey(TilePropertiesGroup, 4);
        /// <summary>
        /// 86d40b4d-9069-443c-819a2a54090dccec, 5
        /// </summary>
        static readonly PropertyKey TileForegroundColor = new PropertyKey(TilePropertiesGroup, 5);
        /// <summary>
        /// 86d40b4d-9069-443c-819a2a54090dccec, 11
        /// </summary>
        static readonly PropertyKey TileDisplayName = new PropertyKey(TilePropertiesGroup, 11);
        /// <summary>
        /// 86d40b4d-9069-443c-819a2a54090dccec, 12
        /// </summary>
        static readonly PropertyKey TileImageLocation = new PropertyKey(TilePropertiesGroup, 12);
        /// <summary>
        /// 86d40b4d-9069-443c-819a2a54090dccec, 14
        /// </summary>
        static readonly PropertyKey TileUnknownFlags = new PropertyKey(TilePropertiesGroup, 14);
        /// <summary>
        /// 9f4c2855-9f79-4b39-a8d0e1d42de1d5f3
        /// </summary>
        public static readonly Guid MetadataGroup = new Guid(
            0x9f4c2855, 0x9f79, 0x4b39, 0xa8, 0xd0, 0xe1, 0xd4, 0x2d, 0xe1, 0xd5, 0xf3
            );
        /// <summary>
        /// 9f4c2855-9f79-4b39-a8d0e1d42de1d5f3, 5
        /// </summary>
        public static readonly PropertyKey AppUserModelID = new PropertyKey(MetadataGroup, 5);
        /// <summary>
        /// b6578b39-11f9-449b-8438cb5cf03b7d9c
        /// </summary>
        static readonly Guid UnknownGroup1 = new Guid(
            0xb6578b39, 0x11f9, 0x449b, 0x84, 0x38, 0xcb, 0x5c, 0xf0, 0x3b, 0x7d, 0x9c
            );
        #endregion
        /// <summary>
        /// Creates a tile in the Windows 8 start screen.
        /// </summary>
        /// <param name="target">The file to be executed when the tile is clicked.</param>
        /// <param name="appId">The registering application's ID.</param>
        /// <param name="title">The caption text for the tile.</param>
        /// <param name="imageFilename">The image to be shown in the tile.</param>
        /// <param name="background">Background color for the tile.<para>
        /// Must be in the hex ARGB form: 0xAARRGGBB.
        /// Where AA is the alpha channel value, RR is for red, GG for green and BB for blue.
        /// </para></param>
        /// <param name="foreground">Foregreound color for the tile, in the
        /// same format as <paramref name="background"/>.</param>
        public static void CreateTile(
            string target,
            string appId,
            string title,
            string imageFilename,
            uint background,
            uint foreground
            )
        {
            string appdata = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            if (appdata == null)
                throw new NotSupportedException("The user's roaming application data directory does not exist.");
            using (var link = new ShellLink())
            {
                link.TargetPath = target;
                // The .lnk icon location and index (not quite important). Just using some defaults.
                link.SetIconLocation(@"%SystemRoot%'System32'SHELL32.DLL", 135);
                link.SetProperty(AppUserModelID, appId);
                // Apparently required properties (AS-IS).
                link.SetProperty(new PropertyKey(MetadataGroup, 11), true);
                link.SetProperty(new PropertyKey(MetadataGroup, 19), "Microsoft.InternetExplorer.Default");
                link.SetProperty(
                    new PropertyKey(MetadataGroup, 20),
                    "-contentTile -formatVersion 0x00000002 -securityFlags 0x00000000 -url 0x00000057"
                    );
                /**
                 * These are not really working at the moment; the tile just shows the name of the .lnk file.
                 */
                link.SetProperty(SystemItemTypeText, title);
                link.SetProperty(TileDisplayName, title);
                // Background and foreground.
                link.SetProperty(TileBackgroundColor, background);
                link.SetProperty(TileForegroundColor, foreground);
                // Small and normal tile icon. Set your own.
                string fileUri = new Uri(imageFilename).AbsoluteUri;
                link.SetProperty(TileImageLocation, fileUri);
                link.SetProperty(TileSmallImageLocation, fileUri);
                // Apparently required, not the tiniest clue of why.
                link.SetProperty(TileUnknownFlags, 0x41u);
                link.SetProperty(new PropertyKey(UnknownGroup1, 4), 0x41u);
                // The file should be saved to %LOCALAPPDATA%'Microsoft'Windows'Application Shortcuts
                string filename = Path.Combine(appdata, @"Microsoft'Windows'Application Shortcuts");
                filename = Path.Combine(filename, "Win8Tiles-Test");
                Directory.CreateDirectory(filename);
                filename = Path.Combine(filename, title + ".lnk");
                link.Save(filename);
            }
        }
    }
}

Windows 8启动屏幕平铺,基于桌面快捷方式

function GetPropertyKeyCanonicalName(const AKey: TPropertyKey): UnicodeString;
var
  PropertySystem: IPropertySystem;
  PropertyDescription: IPropertyDescription;
  N: PWideChar;
begin
  Result := '';
  if Succeeded(CoCreateInstance(CLSID_IPropertySystem, nil, CLSCTX_INPROC_SERVER, IPropertySystem, PropertySystem)) then
    try
      if Succeeded(PropertySystem.GetPropertyDescription(AKey, IPropertyDescription, PropertyDescription)) then
        try
          if Succeeded(PropertyDescription.GetCanonicalName(N)) then
            try
              Result := N
            finally
              CoTaskMemFree(N);
            end;
        finally
          PropertyDescription := nil;
        end;
    finally
      PropertySystem := nil;
    end;
end;