Как я могу добавить прозрачность в форму C #, оставляя элементы управления видимыми?

UPDATE: I took a break from messing with the transparency stuff for a few days. I started messing with it again tonight. I got a new result using Hans Passant's solution: new result http://img3.imageshack.us/img3/4265/icontransp.jpg http://img3.imageshack.us/img3/4265/icontransp.jpg

Passant's solution does solve the issue of the transparent background gradient. However, I'm still running into the problem with the transparent colors in my icon blending with the form's BackColor. You can see the fuchsia around various parts of the icon in the above image.

ORIGINAL CONTENT:

Я занимаюсь этим уже несколько часов, и мне не очень повезло. Я перепутал с Control.Region, Form.TransparencyKey, Form.Opacity и парой других случайных вещей с некоторыми забавными эффектами.

В последнее время я пытался настроить свой рабочий стол и решил связываться с док-станциями приложений. Посмотрев, что может предложить док-станция Mac и несколько сторонних реализаций Windows, я решил, что хочу создать свою собственную.

В конце концов я хочу перейти к использованию Win32 API. Сейчас я просто хочу, чтобы что-то работало, используя как можно больше возможностей C # и .Net Framework.

There are a few things I want to be able to do in this application:

Display a form/menu with a gradient background. Allow the form/menu to have transparency while keeping icons opaque. Display icons that contain transparent backgrounds. The Menu and Icons should be able to receive mouse-related events (hover, leave, click, dragover, dragdrop, and a few others).

Это эффект, который я снимаю для: Желаемый эффект http://img207.imageshack.us/img207/5716/desired.jpg http://img207.imageshack.us/img207/5716/desired.jpg

Это изображение показывает визуальные эффекты, которые я пытаюсь достичь. Это был скин, который я сделал для программы Rainmeter. Изображение показывает Notepad ++ за скином с несколькими открытыми в редакторе файлами скина. Меню прозрачное, но значки остаются непрозрачными.

My Approach:

Использование формы в качестве меню показалось мне логичным выбором. У меня есть базовое понимание событий. Я не совсем уверен, как создавать свои собственные события кликов, поэтому форма облегчит работу с событиями. Я рассмотрел несколько вариантов значков. Я решил использовать PictureBox для значков, так как они могут содержать изображения и получать события.

Как только я закончил код для всей структурной логики моего меню, я начал играть с ним, пытаясь получить нужный визуальный эффект. Form.Opacity влияет на прозрачность всего в форме. Поскольку я хочу, чтобы значки были полностью непрозрачными, я оставил это свойство в покое. Я попытался установить BackColor в Color.Transparent, но это дает ошибку. Я играл с несколькими комбинациями ... Комбинированные эффекты http://img204.imageshack.us/img204/757/effectsi.jpg http://img204.imageshack.us/img204/757/effectsi.jpg

Я нарисовал градиент с помощью Drawing2D.LinearGradientBrush в растровое изображение. Это растровое изображение было затем помещено как Form.BackgroundImage или как PictureBox.Image. Если используется, размер PictureBox должен охватывать всю форму и отправляться обратно.

Я заметил, что некоторые из Form.BackgroundColor будут смешаны с контурами моих значков. Значки имеют прозрачность по краям для более плавного внешнего вида. Поскольку значки выбирают BackgroundColor формы, это заставляет меня думать, что PictureBox создает новые изображения, когда значки загружаются в форму. Полупрозрачные части изображения затем объединяются с BackgroundColor формы, когда они должны сливаться с любыми цветами позади формы.

эффект с белым рабочим столом http://img838.imageshack.us/img838/8299/whitedesktop.jpg http://img838.imageshack.us/img838/8299/whitedesktop.jpg

На этом изображении вы можете видеть фуксию, существующую на значках, даже если цвет фуксии формы теперь полностью прозрачен. Я забыл указать, что в каждом случае использовался один и тот же градиент от зеленого к желтому со значением альфа 150. На изображениях, где градиент не выглядит зеленым, это происходит потому, что прозрачные цвета смешиваются с фоном фуксии.

Я не совсем уверен, что делать дальше. Я чувствую, что могу получить то, что хочу, если бы смог каким-то образом сделать одну форму полностью прозрачной. Я также подумал, что мне может повезти больше, просто рисуя значки вместо использования PictureBoxes. Тогда проблема заключается в настройке значков для получения событий мыши. (Я никогда не проводил свои собственные события, и я думаю, что это потребовало бы некоторых вызовов Win32 API.)

Что еще я могу сделать с PictureBox, чтобы получить желаемый эффект? В любом случае я открыт для любых идей или предложений относительно общего эффекта, которого я пытаюсь достичь.

Ответы на вопрос(2)

two формы. Нижний должен обеспечивать прозрачный градиентный фон, верхний должен рисовать значки и обрабатывать щелчки мышью. Пример кода:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        this.TopMost = true;
        this.FormBorderStyle = FormBorderStyle.None;
        this.TransparencyKey = this.BackColor = Color.Fuchsia;
        this.Opacity = 0.3;
        var overlay = new Form();
        overlay.FormBorderStyle = FormBorderStyle.None;
        overlay.TransparencyKey = overlay.BackColor = Color.Fuchsia;
        overlay.StartPosition = FormStartPosition.Manual;
        overlay.Location = this.Location;
        overlay.MouseDown += HandleIconClick;
        this.Resize += delegate { overlay.Size = this.Size; };
        this.LocationChanged += delegate { overlay.Location = this.Location; };
        overlay.Paint += PaintIcons;
        this.Paint += PaintBackground;
        this.Load += delegate { overlay.Show(this); };
    }
    private void PaintBackground(object sender, PaintEventArgs e) {
        var rc = new Rectangle(0, 0, this.ClientSize.Width, this.ClientSize.Height);
        using (var br = new LinearGradientBrush(rc, Color.Gainsboro, Color.Yellow, 0f)) {
            e.Graphics.FillRectangle(br, rc);
        }
    }
    private void PaintIcons(object sender, PaintEventArgs e) {
        e.Graphics.DrawIcon(Properties.Resources.ExampleIcon1, 50, 30);
        // etc...
    }
    void HandleIconClick(object sender, MouseEventArgs e) {
        // TODO
    }
}

Который выглядит так со случайными цветами и иконкой, которые я выбрал

enter image description here

 22 апр. 2012 г., 18:59
Не используйте PictureBoxes. Они просто не нужны и портят графические эффекты. Просто используйте событие Paint, чтобы нарисовать все, что вы хотите, как показано во фрагменте. Единственное, что вам нужно сделать, это обнаружить, что они нажали. В методе HandleIconClick вы знаете, где нарисовали значки, а также знаете, когда e.Location перекрывает значок. Ключевой момент - перестать думать, что все должно быть под контролем.
 22 апр. 2012 г., 13:36
Это результат без установки FormBoderStyle.SnapShot
 22 апр. 2012 г., 13:15
Я пишу событие Paint, очень похожее на ваше, но оно не работает. Поэтому я попробовал ваше мероприятие, и оно тоже не работает. Это очень странное поведение.
 22 апр. 2012 г., 13:57
Я уже реализовал событие Paint. Так что у меня была другая проблема. Но я решил это. Спасибо. :)
 22 апр. 2012 г., 13:42
Ну, нижняя форма бутерброда видна. Вы не реализовали Paint для рисования градиентного фона, и нет признаков верхней формы, возможно, потому, что он также не реализовал Paint. Пожалуйста, начните свой вопрос, если вам нужна помощь.

я немного растерялся во всем этом, но из описания в исходном абзаце я бы удостоверился, что прямоугольник фона НЕ является визуальным родителем ящиков для фотографий. Сделайте так, чтобы они накладывались друг на друга, с картинками впереди, используя Panel.Zindex.

Тогда вы можете просто изменить непрозрачность прямоугольника, не затрагивая значки. Также убедитесь, что файлы исходных изображений значков имеют прозрачный фон.

Должен работать, я думаю.

 22 апр. 2012 г., 19:45
Да, я отправил свой ответ, прежде чем заметил, что вы не используете WPF. Я уже делал подобные вещи в WPF, но думаю, что это не применимо. Удачи!
 Cheese22 апр. 2012 г., 18:45
(Я нажал клавишу ввода, чтобы начать новый абзац для удобства чтения, но он закончил комментарий. Я только начну новый.) Я еще ничего не пробовал в WPF. Я видел, как он использовался чаще, чем в предыдущие годы, когда имел дело с некоторыми графическими вещами. Я думаю, что часть xml (xaml?) Должна немного упростить настройку. Я могу попробовать это, как только получу эту версию своего проекта.
 22 апр. 2012 г., 12:56
Обратите внимание, мой ответ должен работать в WPF. Не уверен, что в Winforms все по-другому.
 Cheese22 апр. 2012 г., 18:42
Ах, я как раз собирался сказать, что я уже в значительной степени справился с тем, что вы описали в своем комментарии. Моя проблема в том, что я не могу заставить прозрачность пройти весь путь через форму. Я могу получить различные элементы поверх формы, которые будут вести себя так, как я хочу. Однако из-за фона формы у меня возникли проблемы с тем, чтобы обеспечить прозрачность всего приложения, которую я хочу.

Ваш ответ на вопрос