BlueWizard
BlueWizard

Reputation: 372

Display a UAC Shield Icon next to a WPF Button?

Microsoft requires a UAC Shield Icon next to buttons and list entries that will open a UAC verification prompt. How do I get this Icon next to my WPF Button?

Image of UAC Button

I've been searching the web for more than an hour now but I was unable to find a way of adding this shield icon to an WPF Button.

I have a WPF Form using a normal WPF Button but most of the scripts I was able to find didn't worked for me - mostly because my Buttons don't have a FlatStyle or Handle property (I think the WinForms-Buttons have these properties)

I'm using Visual Studio 2015 Community with a .NET Framework 3.5 Application using WPF

I hope you guys are able to help me. Have a nice day

Upvotes: 9

Views: 4452

Answers (3)

AH.
AH.

Reputation: 3091

Very simple example adding a small shield icon and button text from code. The button should be added to XAML with the name "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;
    }

Upvotes: 1

Mathew Sachin
Mathew Sachin

Reputation: 1449

Simplest solution: WPF Controls support nesting

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

Upvotes: 3

Bradley Uffner
Bradley Uffner

Reputation: 16991

The actual Windows icon for running version of windows is supplied via the Win32 API. I'm not aware of any functions in .NET to directly retrieve it, however it can be accessed via p/invoke on user32.dll. Details can be found here. Adjustments will need to be made for WPF, as the linked code is for Winforms.

Short summary:

[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);
}

Update

This will give you direct access to the correct icon and it works in WPF directly.

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 Signatures can be found here.

Upvotes: 15

Related Questions