Добавьте экран UAC для управления в C#
В Windows Vista и более поздних версиях Windows вы должны добавить экран UAC (контроль доступа пользователя) к кнопкам, запускающим процессы, требующие повышения привилегий. К сожалению, Microsoft не сделала это легко.
Добавление экрана к кнопке неудобно, но возможно. Метод AddShieldToButton, показанный в следующем коде, делает это, отправив сообщение BCM_SETSHIELD на кнопку. Обратите внимание, что кнопка должна иметь FlatStyle prperty, установленную в System, и она должна содержать текстовую подпись, даже если заголовок является одиночным пробелом.
[DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); // Сделайте кнопку, отображающую экран UAC. public static void AddShieldToButton(Button btn) { const Int32 BCM_SETSHIELD = 0x160C; // Дайте кнопке плоский стиль и сделайте это // отображаем экран UAC. btn.FlatStyle = System.Windows.Forms.FlatStyle.System; SendMessage(btn.Handle, BCM_SETSHIELD, 0, 1); }
К сожалению, Microsoft не предоставила никакого способа добавить экран к чему-либо, кроме кнопки, поэтому добавление его к другим вещам - это больше работы. Вы можете сделать изображение щита и просто добавить, что нужно, но внешний вид экрана изменяется в зависимости от системных настроек (например, обычного или большого размера шрифта) и может измениться в будущих версиях операционной системы.
Метод GetUacShieldImage, показанный в следующем коде, получает изображение экрана системы и возвращает его в растровое изображение, чтобы вы могли добавить его к пунктам меню, полям изображений и другим элементам управления, если это необходимо. р>
// Возвращает растровое изображение, содержащее экран UAC. 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; // Создаем кнопку. По какой-то причине он должен // есть текст или экран UAC не появится. Button btn = new Button(); btn.Text = " "; btn.Size = new Size(WID, HGT); AddShieldToButton(btn); // Нарисуем кнопку на растровом изображении. Bitmap bm = new Bitmap(WID, HGT); btn.Refresh(); btn.DrawToBitmap(bm, new Rectangle(0, 0, WID, HGT)); // Найдите часть, содержащую экран. int min_x = WID, max_x = 0, min_y = HGT, max_y = 0; // Заполните слева. for (int y = MARGIN; y < HGT - MARGIN; y++) { // Получить цвет самого левого пикселя. Color target_color = bm.GetPixel(MARGIN, y); // Заполните этот цвет, пока мы видим цель. for (int x = MARGIN; x < WID - MARGIN; x++) { // Посмотрим, является ли этот пиксель частью экрана. if (bm.GetPixel(x, y).Equals(target_color)) { // Это не часть щита. // Очистите пиксель. bm.SetPixel(x, y, Color.Transparent); } else { // Это часть щита. 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; } } } // Закрепите часть экрана. 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 shield_bm; }
Этот метод делает кнопку с единственным пространством в качестве текста и использует метод AddShieldToButton, чтобы дать ему экран UAC. Затем он вызывает метод кнопки DrawToBitmap кнопки, чтобы заставить его рисовать на растровое изображение.
Далее код вырывается через растровое изображение, чтобы увидеть, где находится экранное изображение. Он пропускает те края, на которых расположены границы кнопки, и обнаруживает цвет фона для каждой горизонтальной строки пикселей в растровом изображении. По мере прохождения изображения он записывает самые большие и наименьшие координаты X и Y, которые не имеют этих цветов. Вот где щит. Код также преобразует фоновые пиксели в прозрачный цвет.
Наконец, код копирует экран в новый растровый рисунок, размер которого соответствует размеру и возвращает новое растровое изображение. Фоновые пиксели прозрачны, поэтому вы можете поместить экран над несогласованным фоном.
Следующий код показывает, как основная программа добавляет экраны UAC к кнопке , MenuItem и PictureBox.
private void Form1_Load(object sender, EventArgs e) { // Добавьте экран к кнопке. UacStuff.AddShieldToButton(btnClickMe); // Добавление экрана в пункт меню. mnuFileFormatHardDrive.ImageScaling = ToolStripItemImageScaling.None; mnuFileFormatHardDrive.Image = UacStuff.GetUacShieldImage(); // Добавление экрана в PictureBox и // перемещаем LinkLabel рядом с ним. picShield.Image = UacStuff.GetUacShieldImage(); int y = ClientSize.Height - 8 - picShield.Height; llblDangerous.Location = new Point( btnClickMe.Right - llblDangerous.Width, y); picShield.Location = new Point( llblDangerous.Left - picShield.Width, y); }