如何在 WPF 按钮旁显示 UAC 盾牌图标?

9

微软要求在将打开UAC验证提示的按钮和列表条目旁边放置UAC盾形图标。我如何在我的WPF按钮旁边获取此图标?

UAC按钮图像

我已经在网上搜索了一个多小时,但是我无法找到一种方法将这个盾形图标添加到WPF按钮中。

我有一个使用普通WPF按钮的WPF表单,但是大多数我能找到的脚本都对我没有用 - 主要是因为我的按钮没有FlatStyleHandle属性(我认为WinForms-按钮具有这些属性)

我使用的是Visual Studio 2015 Community,使用WPF的.NET Framework 3.5应用程序

希望你们能帮助我。祝你们拥有愉快的一天


使用自定义的WPF样式。在按钮上添加图像和文本。 - Fᴀʀʜᴀɴ Aɴᴀᴍ
请看此处此处有关编程的内容。 - Lucas Trzesniewski
我无法让它工作。我尝试了这个方法(http://blogs.msdn.com/b/yvesdolc/archive/2006/10/16/stockicons-for-windows-presentation-framework.aspx),但我的IDE无法找到clr-namespace:VistaBridge.UI,因此图像嵌入不起作用。 - BlueWizard
1
@farhan-anam 在不同的Windows版本上,图标看起来会有所不同。这就是为什么Windows应该提供图像的原因 - 至少这是我理解的方式。 - BlueWizard
我原以为你只是想告诉用户该按钮与UAC有关,但事实并非如此,恐怕我无法提供帮助。抱歉。 - Fᴀʀʜᴀɴ Aɴᴀᴍ
3个回答

15
实际运行版本的Windows图标是通过Win32 API提供的。我不知道.NET中是否有直接检索它的函数,但是可以通过对user32.dll进行p/invoke访问。详情请参见这里。需要针对WPF进行调整,因为链接的代码适用于Winforms。
[DllImport("user32")]
public static extern UInt32 SendMessage
    (IntPtr hWnd, UInt32 msg, UInt32 wParam, UInt32 lParam);

internal const int BCM_FIRST = 0x1600; //Normal button
internal const int BCM_SETSHIELD = (BCM_FIRST + 0x000C); //Elevated button

static internal void AddShieldToButton(Button b)
{
    b.FlatStyle = FlatStyle.System;
    SendMessage(b.Handle, BCM_SETSHIELD, 0, 0xFFFFFFFF);
}

更新

这个链接将直接为您提供正确的图标,并且可以在WPF中直接使用。

BitmapSource shieldSource = null;

if (Environment.OSVersion.Version.Major >= 6)
{
    SHSTOCKICONINFO sii = new SHSTOCKICONINFO();
    sii.cbSize = (UInt32) Marshal.SizeOf(typeof(SHSTOCKICONINFO));

    Marshal.ThrowExceptionForHR(SHGetStockIconInfo(SHSTOCKICONID.SIID_SHIELD,
        SHGSI.SHGSI_ICON | SHGSI.SHGSI_SMALLICON,
        ref sii));

    shieldSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
        sii.hIcon,
        Int32Rect.Empty, 
        BitmapSizeOptions.FromEmptyOptions());

    DestroyIcon(sii.hIcon);
}
else
{
    shieldSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
        System.Drawing.SystemIcons.Shield.Handle,
        Int32Rect.Empty, 
        BitmapSizeOptions.FromEmptyOptions());
}

p/Invoke签名可以在这里找到。


谢谢你的回答! [我做错了什么吗?] (https://i.imgur.com/2fgMfBt.png) - BlueWizard
看起来你缺少p/invoke签名的类定义。如果你按照底部的链接查看签名,你会发现更多标记为“用户定义类型”的链接,这些链接的名称与你缺少的类匹配。你只需要将这些类和枚举添加到你的项目中即可。 - Bradley Uffner
非常好用。谢谢。 - AndresRohrAtlasInformatik

3

最简单的解决方案:WPF控件支持嵌套。

        <Button Height="30" Width="200">
            <DockPanel>
                <Image Source="ImagePath"/>
                <Label Content="Label"/>
            </DockPanel>
        </Button>

它可以工作,但我不是100%满意。感谢你介绍给我一个我之前不知道的WPF项。我喜欢这个答案,因为它是100%的XAML,但是我不接受它作为答案,因为它不能适应Windows资源和Windows设计指南(我的图标可能比原始Windows按钮大或小一点)。谢谢 :) - BlueWizard

1
非常简单的例子,从代码中添加一个小盾牌图标和按钮文本。按钮应该在XAML中以名称“OkButton”添加。
    [DllImport("user32.dll")]
    static extern IntPtr LoadImage(
        IntPtr hinst,
        string lpszName,
        uint uType,
        int cxDesired,
        int cyDesired,
        uint fuLoad);

    public MainWindow()
    {
        InitializeComponent();

        var image = LoadImage(IntPtr.Zero, "#106", 1, SystemInformation.SmallIconSize.Width, SystemInformation.SmallIconSize.Height, 0);
        var imageSource = Imaging.CreateBitmapSourceFromHIcon(image, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

        // Set button content from code
        var sp = new StackPanel
        {
            Orientation = Orientation.Horizontal,
        };
        sp.Children.Add(new Image { Source = imageSource, Stretch = Stretch.None });
       sp.Children.Add(new TextBlock { Text = "OK", Margin = new Thickness(5, 0, 0, 0) });
        OkButton.Content = sp;
    }

非常好用,只需要进行一些小修改 - SystemInformation.SmallIconSize.Width => (int)SystemParameters.SmallIconWidthSystemInformation.SmallIconSize.Height => (int)SystemParameters.SmallIconHeight 以避免引用 Winforms,并且我已经将 ImageSource 存储为属性以便加载并绑定。谢谢! - itsho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接