Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display a UAC Shield Icon next to a WPF Button?

Tags:

c#

wpf

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

like image 697
BlueWizard Avatar asked Oct 22 '15 16:10

BlueWizard


People also ask

How to add a shield to a button using the API?

First, before we add a shield, we need to know if the process is elevated or not which is easily done. To add a shield to a button, make sure that the button uses FlatStyle.System and then sends the appropriate message using the API. The important API function parameters are the handle of the button and the BCM_SETSHIELD message.

Why is there a shield icon on the file icon?

That shield icon is a reminder that the file requires Administrator privileges to open. It can save time for a user who does not have admin privileges.

How to get rid of the shield symbol in a shortcut?

Open property dialog for the shortcut you want to get rid of shield symbol. Click 'Change icon..' and confirm with 'OK' right away without any changes (just do this step!) Add 'nircmd elevate ' at begin of the target application path.

How do I change the UAC settings?

To make changes to the User Account Control Settings complete the following steps: 1 Press the Windows key + C. 2 Select Search. 3 Type UAC. 4 Select Settings. 5 Select the UAC tile. 6 Use the slider to adjust the UAC settings Dena Report abuse 37 people found this reply helpful ·. Was this reply helpful?


2 Answers

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.

like image 53
Bradley Uffner Avatar answered Oct 01 '22 07:10

Bradley Uffner


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;
    }
like image 25
AH. Avatar answered Oct 01 '22 06:10

AH.