给按钮添加UAC盾牌并保留其背景图像?

9
在使用C#和.Net 4.0开发Windows窗体应用程序时,可以通过什么方式在按钮上添加UAC盾形图标并保留按钮的背景图像呢?以下是我目前正在使用的方法,但它会删除按钮的图像...
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

public static void UACToButton(Button button, bool add)
{
    const Int32 BCM_SETSHIELD = 0x160C;
    if (add)
        {
        // The button must have the flat style
        button.FlatStyle = FlatStyle.System;
        if (button.Text == "")
        // and it must have text to display the shield
            button.Text = " ";
            SendMessage(button.Handle, BCM_SETSHIELD, 0, 1);        
        }
        else
            SendMessage(button.Handle, BCM_SETSHIELD, 0, 0);    
}

谢谢!


你是想在按钮上只显示盾牌而不显示文本吗? - Cameron Tinker
按钮没有文本。它只有一个图像,当调用该方法时会被移除。 - Daro
从imageres.dll加载图标,并在绘制按钮上的图像之前将其绘制在背景图像上。 - Elmue
2个回答

3
如Elmue所提到的,SystemIcons.Shield是访问UAC Shield图标最简单的方法。这是我用来将其添加到其他图像之上的方法:
public static Image AddUACShieldToImage(Image image)
    {
        var shield = SystemIcons.Shield.ToBitmap();
        shield.MakeTransparent();

        var g = Graphics.FromImage(image);
        g.CompositingMode = CompositingMode.SourceOver;
        g.DrawImage(shield, new Rectangle(image.Width / 2, image.Height / 2, image.Width / 2, image.Height / 2));

        return image;
    }

2
也许这可以帮助您:http://blog.csharphelper.com/2011/03/03/add-uac-shields-to-buttons-menu-items-and-picture-boxes-in-c.aspx。它提供了UAC盾牌并返回一个位图,可以放置在支持位图的任何地方。
编辑:这是一些粗略的示例代码,可能会起作用:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace UAC_Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

        // Make the button display the UAC shield.
        public static void AddShieldToButton(Button btn)
        {
            const Int32 BCM_SETSHIELD = 0x160C;

            // Give the button the flat style and make it display the UAC shield.
            btn.FlatStyle = System.Windows.Forms.FlatStyle.System;
            SendMessage(btn.Handle, BCM_SETSHIELD, 0, 1);
        }

        // Return a bitmap containing the UAC shield.
        private static Bitmap shield_bm = null;
        public static Bitmap GetUacShieldImage()
        {
            if (shield_bm != null) return shield_bm;

            const int WID = 50;
            const int HGT = 50;
            const int MARGIN = 4;

            // Make the button. For some reason, it must
            // have text or the UAC shield won't appear.
            Button btn = new Button();
            btn.Text = " ";
            btn.Size = new Size(WID, HGT);
            AddShieldToButton(btn);

            // Draw the button onto a bitmap.
            Bitmap bm = new Bitmap(WID, HGT);
            btn.Refresh();
            btn.DrawToBitmap(bm, new Rectangle(0, 0, WID, HGT));

            // Find the part containing the shield.
            int min_x = WID, max_x = 0, min_y = HGT, max_y = 0;

            // Fill on the left.
            for (int y = MARGIN; y < HGT - MARGIN; y++)
            {
                // Get the leftmost pixel's color.
                Color target_color = bm.GetPixel(MARGIN, y);

                // Fill in with this color as long as we see the target.
                for (int x = MARGIN; x < WID - MARGIN; x++)
                {
                    // See if this pixel is part of the shield.
                    if (bm.GetPixel(x, y).Equals(target_color))
                    {
                        // It's not part of the shield.
                        // Clear the pixel.
                        bm.SetPixel(x, y, Color.Transparent);
                    }
                    else
                    {
                        // It's part of the shield.
                        if (min_y > y) min_y = y;
                        if (min_x > x) min_x = x;
                        if (max_y < y) max_y = y;
                        if (max_x < x) max_x = x;
                    }
                }
            }

            // Clip out the shield part.
            int shield_wid = max_x - min_x + 1;
            int shield_hgt = max_y - min_y + 1;
            shield_bm = new Bitmap(shield_wid, shield_hgt);
            Graphics shield_gr = Graphics.FromImage(shield_bm);
            shield_gr.DrawImage(bm, 0, 0,
                new Rectangle(min_x, min_y, shield_wid, shield_hgt),
                GraphicsUnit.Pixel);

            // Return the shield.
            return shield_bm;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Graphics gfx = Graphics.FromImage(button1.BackgroundImage);
            Bitmap shield = GetUacShieldImage();
            gfx.DrawImage(shield, button1.Width / 2, button1.Height / 2);
        }
    }
}

这是在背景图像上绘制UAC盾牌。您可以调整按钮顶部的图像位置。它看起来不像系统UAC盾牌那么漂亮,但它确实显示了UAC盾牌图标在您的背景图像之上。


不,它获取UAC盾牌作为位图,并将其放置在支持位图的任何内容上。将该代码添加到按钮上并添加背景图像,您就会看到我的问题。但还是谢谢。 - Daro
我已经更新了我的答案,包括一些示例代码。我最初忘记提到的是,您需要在背景图像上绘制UAC盾牌。 - Cameron Tinker
3
如果你的框架支持,可以使用SystemIcons.Shield,否则可以从imageres.dll中加载它,或者从其他地方下载该图标并自己绘制它。这太过复杂了! - Elmue

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