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
类是一个普通的&围绕IShellLink
和IPropertyStore
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);
}
}
}
}
标题>标题>标题>
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;