UWP App 剪贴板访问:如何防止多次处理相同的项目

UWP App Clipboard Access: how to prevent processing the same items multiple times

从 UWP 应用程序访问 Win10 剪贴板时,该应用程序只能在获得焦点时检查剪贴板。 所以应用程序不知道它在睡觉时发生了什么。 聚焦后,它可以再次检查内容。

现在的问题是:它如何确定来自 Clipboard.GetContents()DataPackageView 是新包裹而不是它已经看过的包裹? DataPackageView.Properties 中似乎没有 ID 或任何其他可用于区分的内容。

我曾希望 DataPackageView.GetHashCode() 可能是答案,但不得不发现每次 GetContents() 调用时 DataPackageView 似乎都会重新实例化,所以没有运气.

有什么想法吗?

UWP App Clipboard Access: how to prevent processing the same items multiple times

Clipboard 包含用于获取 ClipboardHistoryItemsResultGetHistoryItemsAsync 方法。您可以调用 ClipboardHistoryItemsResult.Items 以获得 ClipboardHistoryItem。 ClipboardHistoryItem 有 id 属性 来通知差异。

var results = await Clipboard.GetHistoryItemsAsync();
var id = results.Items.Last().Id;

如果最后的项目id没有改变,这意味着没有新的项目插入剪贴板。请注意,它不能用于验证DataPackageView 的内容是否相同。

如果要验证DataPackageView,请取最后两项,分别比较。

对,没有得到足够快的东西。不幸的是,关于 ClipboardHistory 的建议是静音的,因为它可以被禁用(恕我直言应该是)...

我正在使用 位图内容,因此将剪贴板内容存储到一个文件中,然后对文件进行哈希处理失败,因为生成的文件可能会 meta-tagged,因此会产生一个不同的散列,即使位图是相同的。

唯一能在一定程度上确保位图本身不被看到的方法是对像素数组进行散列处理……仍然可以为您提供相同的散列结果,但这是我愿意承担的风险。关于内存有一些抱怨,但如果我想显示位图,我最好有内存来加载它。 NASA,这对你开箱即用...

所以我决定做艰苦的工作并对位图本身进行哈希处理。

public async Task<String> GetBitmapHashAsync(StorageFile sourceFile)
{
    string result = null;

    // load the bitmap file into a bitmap-decoder and run a Hash algo on the actual pixels
    try
    {
        using (IRandomAccessStream fileStream = await sourceFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
        {
            BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
            PixelDataProvider pixelData = await decoder.GetPixelDataAsync();

            // Get the pixel data
            byte[] sourcePixels = pixelData.DetachPixelData();

            SHA512 sha512Hasher = SHA512.Create();

            // and feed it to the Hasher
            byte[] data = sha512Hasher.ComputeHash(sourcePixels);

            // And now enjoy the result as a HEX string
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            result = sBuilder.ToString();
        }
    }
    catch (Exception)
    {
        result = null;
    }
    return result;
}