Set image as background for Button as default, hover and click

leorob88

Well-known member
Joined
Dec 31, 2020
Messages
81
Programming Experience
1-3
I have a file watcher which basically detects some edits on stuff. When that happens, this method is called. This basically hides for a brief moment the form (and the button that has its same size) so it can capture the screen beneath and make the button's color as default, hover and click, taking the dominant color of the captured area. That, in practical terms, makes the button "almost transparent". More about the matter down below.


C#:
Expand Collapse Copy
        private void colorupdate()
        {
            this.Invoke((MethodInvoker)delegate
            {
                this.Visible = false;
            });
            Dictionary<Color, int[]> colori = new Dictionary<Color, int[]>();
            using (Bitmap pixel = new Bitmap(this.Width, this.Height))
            {
                using (Graphics captureGraphics = Graphics.FromImage(pixel))
                {
                    captureGraphics.CopyFromScreen(new Point(this.Location.X, this.Location.Y), Point.Empty, new Size(this.Width, this.Height));
                }
                for (int x = 0; x < this.Width; x++)
                {
                    for (int y = 0; y < this.Height; y++)
                    {
                        Color colore = pixel.GetPixel(x, y);
                        if (!colori.ContainsKey(colore)) { colori.Add(colore, new int[] { 1, x, y }); }
                        else { colori[colore][0]++; }
                    }
                }
            }
            int dss = colori.OrderByDescending(set => set.Value[0]).First().Value[0];
            int[] ds = colori.OrderByDescending(set => set.Value[0]).First().Value;
            Color color = colori.OrderByDescending(set => set.Value[0]).First().Key;
            this.Invoke((MethodInvoker)delegate
            {
                button1.BackColor = color;
                button1.FlatAppearance.MouseOverBackColor = color;
                button1.FlatAppearance.MouseDownBackColor = color;
                button1.FlatStyle = FlatStyle.Flat;
                button1.FlatAppearance.BorderSize = 0;
                this.Visible = true;
            });
        }

I wish to make the button actually transparent but I cannot because using Color.Transparent makes the button only clickable if the user clicks exactly where the click registers any color that is NOT transparent- i.e. if you click on a transparent area of the button, nothing happens. So, I wish to capture instead the area beneaht the button and the form and use it to set the button's "look" (lke, background image). In particular, i would need to set it as look even when clicked and hovered, because i don't want its default behavior change its appearance when interacting with the mouse (it's only supposed to be interacted with the mouse). Do you know perhaps a simple way to use the screenshot (in this code is already there, it's basically "pixel") as a perennial look and not get overwritten by mouse behavior?
 
I wonder if you are doing something weird with the way you implemented your transparent form. With the code below, I can click on the button -- either on the text itself or in the non-text area and still get the click even for the button. And of course, the panel also still works as previously shown.

1759457935593.png


C#:
Expand Collapse Copy
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Windows.Forms;

namespace TestTransparent.NetFramework
{
    class MainForm : Form
    {
        readonly Panel _panel;
        readonly Button _button;

        MainForm()
        {
            Text = "WinForms .NET Core";
            Width = 800;
            Height = 600;
            BackColor = Color.GreenYellow;
            TransparencyKey = Color.GreenYellow;

            _panel = new Panel
            {
                Bounds = new Rectangle(50, 50, 700, 100),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = Color.Transparent,
                ForeColor = Color.Fuchsia,
                Text = "Panel Click Me",
                Font = new Font("Arial", 72, FontStyle.Italic),
            };
            _panel.Click += (s, e) => MessageBox.Show("Panel clicked!");
            _panel.Paint += (s, e) =>
            {
                var panel = (Panel)s;
                var g = e.Graphics;
                var textSize = g.MeasureString(panel.Text, panel.Font).ToSize();
                var center = panel.Size - textSize;
                using (var brush = new SolidBrush(panel.ForeColor))
                {
                    g.DrawString(panel.Text, panel.Font, brush, center.Width / 2, center.Height / 2);
                }
            };

            _button = new Button
            {
                Bounds = new Rectangle(50, 200, 700, 100),
                ForeColor = Color.SkyBlue,
                Text = "Button Click Me",
                Font = new Font("Arial", 72, FontStyle.Italic),
            };
            _button.Click += (s, e) => MessageBox.Show("Button clicked");

            SuspendLayout();
            Controls.Add(_panel);
            Controls.Add(_button);
            ResumeLayout();
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new MainForm();
            Application.Run(form);
        }
    }
}
 
In posts #15 and #16, the Text = "WinForms .NET Core"; should be replaced with Text = "WinForms .NET Framework";. Just got a little too carried away with the copy and paste between projects. Sorry. It's just a visual bug. It doesn't affect actual functionality.
 
in a new project, it does work, even if i put this in the form constructor as i told before. so at this point i suppose it's definitely something in my code to prevent the effect. time for serious code full read and doublecheck.
to reply your question, just like before, in my program if i click an area where there's not purple text, it won't react.
 
Update: i think that's something very very more basic than it seems.
while i commented out most of my code, i noticed though one strange thing. i had form.tranparencykey = form.backcolor. which in theory is consistent. but does not work.

i tried setting both backcolor and transparencykey to color.black. does not work.

i tried both with color.yellow, it does work.

it seems, i don't know why, that some colors set as transparencykey for the form make it work, whilst some other colors don't. my form had a default color, so i think probably it's one of the "culprit" colors. so yeah, this has been the reason all along for the issue. using a panel will be a solution. i also had a graphic issue about using "colored" colors as transparency key but i just found a working solution for that, it seems.
just for knowledge and cutiosity: your text is quite "big" so this issue is not to be seen, but if you use a font small as mine (more or less the size is around 10 pixel for the font), when you set a "colored" transparencykey for the form you get a graphic issue which is basically "the text shown on the form is surrounded by a thin contour with the same color". i'm just refreshing both form and panel after setting the transparencykey and that seems to work.
 
Last edited:
The "thin contour with the same color" is the font renderer doing anti-aliasing to make the fonts looks smoother, particularly on modern LCD monitors. It was not needed back when we used CRTs. Basically some alpha is removed from the foreground color to fill in the jaggies between sharp corners. The transparency implementation in WinForms does an exact color match for the pixels. Pixels with a different alpha value will fail the color match.
 
Back
Top Bottom