Laden...

GDI Problem: abgerundetes Rechteck über weißem Control hat farbige Ecken

Erstellt von uNki vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.995 Views
U
uNki Themenstarter:in
58 Beiträge seit 2011
vor 12 Jahren
GDI Problem: abgerundetes Rechteck über weißem Control hat farbige Ecken

hi!

im anhang ist ein 32kb bild, das mein problem sofort verdeutlicht.

das sind zwei custom buttons, die ich im Form_Load() so erstelle:


CustomButton button1 = new CustomButton();
button1.Parent = this;
button1.Location = new System.Drawing.Point(100, 90);
button1.Size = new System.Drawing.Size(150, 150);
button1.BringToFront();

CustomButton button2 = new CustomButton();
button2.Parent = this;
button2.Location = new System.Drawing.Point(400, 90);
button2.Size = new System.Drawing.Size(150, 150);
button2.BringToFront();

ist der button auf Form1 ist alles okay, da diese die gleiche hintergrundfarbe hat. ist der button über einer textbox oder jedem anderen weißen steuerelement, habe ich einen unschönen, rechteckigen rand.

hier die kleine klasse dazu:


    class CustomButton : Button
    {
        public CustomButton()
        {
            this.DoubleBuffered = true;
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
            this.BackColor = Color.Transparent;
        }         
      
		protected override CreateParams CreateParams
		{
			get
			{
				CreateParams cp = base.CreateParams;
				cp.ExStyle|= 0x00000020; //WS_EX_TRANSPARENT
				return cp;
			}
		}

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //has to be empty!!!
        }
        
        protected override void OnPaint(PaintEventArgs e)
        {
            base.InvokePaintBackground(this, e);

            Graphics g = e.Graphics;
            ButtonRenderer.DrawParentBackground(g, ClientRectangle, this);
            g.SmoothingMode = SmoothingMode.HighQuality;

            //Funktion zum Zeichnen des abgerundeten Rechtecks aufrufen
            using (GraphicsPath outerPath = RoundedRectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height, 20.00F))
            {
                using (SolidBrush outerBrush = new SolidBrush(Color.Black))
                {
                    g.FillPath(outerBrush, outerPath);
                }               
            }                    
        }                   
                
        //abgerundetes Rechteck erstellen
        private GraphicsPath RoundedRectangle(float x, float y, float width, float height, float radius)
        {
            GraphicsPath gp = new GraphicsPath();
            gp.AddLine(x + radius, y, x + width - (radius * 2), y); // Line
            gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90); // Corner
            gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2)); // Line
            gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90); // Corner
            gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height); // Line
            gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90); // Corner
            gp.AddLine(x, y + height - (radius * 2), x, y + radius); // Line
            gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); // Corner
            gp.CloseFigure();
            return gp;
        }
    }

wie ihr seht, habe ich schon versucht einige tipps aus anderen threads zu befolgen, leider wird das rechteckt mit der farbe der Form1 nicht ausgeblendet.
habt ihr eine idee?

danke!!

B
387 Beiträge seit 2005
vor 12 Jahren

Hi,

base.InvokePaintBackground(this, e);

Graphics g = e.Graphics;
ButtonRenderer.DrawParentBackground(g, ClientRectangle, this);
g.SmoothingMode = SmoothingMode.HighQuality;

Ich vermute mal stark, dass es schlicht an der falschen Hintergrundfarbe liegt. Schau mal, was bei dem Button als BackColor eingestellt ist.

Gruß
Roland

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Blacal,

ich würde nicht sagen, an der Hintergrundfarbe, sondern überhaupt daran, dass ParentBackground gezeichnet wird.

herbivore

795 Beiträge seit 2006
vor 12 Jahren

Das ist imho ein Bug (Feature?) in GDI, dass Controls auf der gleichen Ebene nicht als Background behandelt werden. Sprich, Parent von der TextBox und dem Button sind beide Male die Form, also wird auch nur der Background der Form gezeichnet, und nicht die TextBox.

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
49.485 Beiträge seit 2005
vor 12 Jahren

Hallo TheBrainiac,

Das ist imho ein Bug (Feature?) in GDI, dass Controls auf der gleichen Ebene nicht als Background behandelt werden.

das ist ein Feature. Mit anderen Worten: works as designed. Das Design stammt ja noch aus einer Zeit, als eine andere Entscheidung performance-kritisch gewesen wäre. Mit anderen Worten: Transparenz wird in Windows Forms nach einem vereinfachten Modell berechnet, nämlich so wie du sagst, dass man durch ein Control hindurch nicht die dahinerlegenden Controls sieht, sondern nur den Background des Parents. Anderseits könnte man natürlich die TextBox als Parent wählen, dann würde man sie bzw. ihren Background auch sehen.

herbivore

U
uNki Themenstarter:in
58 Beiträge seit 2011
vor 12 Jahren

hi!

die hintergrundfarbe habe ich bereits auf transparent gesetzt:

public CustomButton()
        {
            this.DoubleBuffered = true;
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
            this.BackColor = Color.Transparent;
        }

es ist richtig, dass die hintergrundfarbe der hintergrundfarbe des parent-steuerelementes entspricht. bei einer textbox mag das noch gehen (so lange kein text drin steht, dann würde sich das rechteck wieder abzeichnen), aber bei einem datagridview mit den gridlines dazwischen, sieht man das rechteck dann wiederum sehr deutlich, da es die gridlines überdeckt.

es muss doch eine möglichkeit geben, dieses hintergrund-rechteck auszublenden oder wirklich transparent zu machen!? 8o

btw: wenn ich "ButtonRenderer.DrawParentBackground(g, ClientRectangle, this);" rausnehme, ist das rechteck dahinter einfach schwarz, aber immer noch existent.

grüße!

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo uNki,

es muss doch eine möglichkeit geben, dieses hintergrund-rechteck auszublenden oder wirklich transparent zu machen!?

wie schon gesagt, funktioniert Transparenz unter Windows Forms nach einem vereinfachten Modell. Wenn man nicht gerade alle Controls selber zeichnet, kriegt man das Verhalten auch nicht geändert. Du willst ja allerdings ein Control nur abrunden. Das sollte gehen. Suche nach runder Button oder rundes Form.

wenn ich "ButtonRenderer.DrawParentBackground(g, ClientRectangle, this);" rausnehme, ist das rechteck dahinter einfach schwarz

Ja, stimmt. Ich hatte nicht bedacht, dass der Bereich aufgrund des Clippings vom dahinterliegenden Control gar nicht erst gezeichnet wird.

herbivore