Re: Why must I paint the form background for an owner-draw control?
From: Mick Doherty (EXCHANGE#WITH_at_AND.REMOVE.SQUAREBRACKETS.[mdaudi100#ntlworld.com)
Date: 10/08/04
- Next message: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- Previous message: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- In reply to: Stoitcho Goutsev \(100\) [C# MVP]: "Re: Why must I paint the form background for an owner-draw control?"
- Next in thread: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- Reply: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- Messages sorted by: [ date ] [ thread ]
Date: Fri, 8 Oct 2004 17:00:23 +0100
His problem stems from the fact that the button base Class has
ControlStyles.Opaque set to true by default so his setting it to true makes
no difference. This problem does not appear in a class based upon Control
because in a Control/UserControl ControlStyles.Opaque is false by default.
This is the only modification that is necessary to cure the black
background.
OnPaintBackground() is called to draw the controls parent in any non opaque
regions of the control. If the control is fully opaque then this method is
not called, that is why there is a black background.
I have created a button derived from button and have not set the region of
the control, doing so causes nasty jagged edges around curves. By not
setting the region you can set the Graphics.SmoothingMode to High and see
nice smooth edges around the button.
Without Doublebuffer, AllPaintingInWMPaint does not need to be set.
-- Mick Doherty http://dotnetrix.co.uk/nothing.html "Stoitcho Goutsev (100) [C# MVP]" <100@100.com> wrote in message news:OUSeQNUrEHA.2340@TK2MSFTNGP11.phx.gbl... > Hi Tim, > > So here is how to fix the problem with the black background: > 1. Take off those lines form the form constructor > > SetStyle(ControlStyles.AllPaintingInWmPaint, true); > SetStyle(ControlStyles.Opaque, true); > > Let only UserPaint and SupprtTransparentBackColor stay. > > 2. As long as (you mentioned yourself) this is simulated transparency it > means that the control class does some work to make this happen. In other > words in the OnPaint method you need to call the > base.OnPaint in order to let the control do it's work. Put that call as > the first line in the OnPaint method (you don't want the default method to > overdraw you fancy button, do you) > > Here you go... the transparent backgroung. That was easy. However your > troubles doesn't stop here. The default OnPaint draws some stuff that you > don't want. Like (button 3d appearance, focus rectangle, Balck rectangle > around the default button). Among this only the focused rectangle I > managed to get rid of. > I did that by overriding ShowFocusCues. In my override I return *false*. > 3D appearnace you can kind of remove by setting the button's FlatStyle. > Default-button black rectangle I removed by overriding NotifyDefault > method and calling the base method with *false* as a parameter. It has > side effect that the button cannot be default > > Anyways, the result is far from perfect. > > So my suggestion is to go with the Control as a base class. So, do what I > told you erlier (stpes 1 and 2) and change the base class to Control. It > works just fine. The problem here is that the FancyButton cannot be used > where Button type is expected. > > If you still want to use the button as a base class then take a look in > the Contol.Region property. Setting the region of the control to match > exactly your button's outline shape will make all that crappy adornments > to be clipped off. > > -- > HTH > Stoitcho Goutsev (100) [C# MVP] > > > "Tim Crews" <tim-junk@crews-family.org> wrote in message > news:MPG.1bcf6c43dfef5be4989682@news.cox.net... >> In article <updaiLJrEHA.736@tk2msftngp13.phx.gbl>, >> EXCHANGE#WITH@AND.REMOVE.SQUAREBRACKETS.[mdaudi100#ntlworld.com] says... >>> when overriding the button control you must also set >>> ControlStyles.Opaque to >>> false. >>> >>> \\\ >>> SetStyle(ControlStyles.AllPaintingInWmPaint >>> | ControlStyles.DoubleBuffer >>> | ControlStyles.UserPaint >>> | ControlStyles.SupportsTransparentBackColor, true); >>> >>> SetStyle(ControlStyles.Opaque, false); >>> >>> this.BackColor = Color.Transparent; >>> /// >>> >>> >> >> I sincerely thank everyone for taking the time to look at this. >> >> I added Opaque as you suggested, and _still_ get black backgrounds. I >> also added the DoubleBuffer style as you suggested, although I had not >> originally planned to double buffer the drawing. Either way, black >> backgrounds around the buttons. >> >> I'm going to go for broke and post all of the button subclass code. >> >> To test this, create a form, give it a background image, create a button >> on the form, then change the declaration and creation of the Button to >> FancyButton. To see what the button should look like (i.e. without >> black background), uncomment the code segment starting with "if >> (Parent.BackgroundImage == null)". But the performance will be terrible >> if you do that. >> >> Thank you for your assistance, >> >> Tim Crews >> GECO, Inc. >> >> #################################################### >> >> public class FancyButton : Button >> { >> >> private int PenWidth; >> private int ShadowHeight; >> private int ButtonThickness; >> private bool ButtonPressed; >> >> public FancyButton() : base() >> { >> PenWidth = 1; >> ButtonPressed = false; >> >> // All of the following added per suggestions of newsgroup >> // respondents. >> SetStyle(ControlStyles.UserPaint, true); >> SetStyle(ControlStyles.SupportsTransparentBackColor, true); >> SetStyle(ControlStyles.AllPaintingInWmPaint, true); >> SetStyle(ControlStyles.Opaque, true); >> this.BackColor = Color.FromArgb(0,this.BackColor); >> } >> >> >> public void SpecialRoundRect (Rectangle rect, >> Color BaselineColor, >> System.Windows.Forms.PaintEventArgs e, >> bool Shade3D, >> bool LoOutline, >> bool HiOutline) >> { >> >> rect.Inflate(-1*PenWidth,-1*PenWidth); >> >> int CurveSize = Math.Min(rect.Width, rect.Height) / 2; >> int CurveHalfSize = CurveSize/2; >> int CurveHalfLeft = rect.Left + CurveHalfSize; >> int CurveHalfRight = rect.Right-CurveHalfSize; >> int CurveHalfTop = rect.Top + CurveHalfSize; >> int CurveHalfBottom = rect.Bottom-CurveHalfSize; >> >> Rectangle TopLeft = new Rectangle >> (rect.Left,rect.Top,CurveSize,CurveSize); >> Rectangle TopRight = new Rectangle >> (rect.Right-CurveSize,rect.Top,CurveSize,CurveSize); >> Rectangle BottomLeft = new Rectangle >> (rect.Left,rect.Bottom-CurveSize,CurveSize,CurveSize); >> Rectangle BottomRight = new Rectangle >> (rect.Right-CurveSize, >> rect.Bottom-CurveSize, >> CurveSize,CurveSize); >> >> int MiddleX = (rect.Right + rect.Left) / 2; >> int MiddleY = (rect.Top + rect.Bottom) / 2; >> >> SolidBrush BaselineBrush, LoBrush, MedBrush, HiBrush; >> Pen BaselinePen, LoPen, MedPen, HiPen; >> >> BaselineBrush = new SolidBrush(BaselineColor); >> BaselinePen = new Pen(BaselineBrush, PenWidth); >> >> if (Shade3D) >> { >> // The low color should be a lot darker version of the >> // specified BaselineColor >> byte ShadowR, ShadowG, ShadowB; >> ShadowR = (byte)((int)BaselineColor.R*2/3); >> ShadowG = (byte)((int)BaselineColor.G*2/3); >> ShadowB = (byte)((int)BaselineColor.B*2/3); >> Color ShadowColor = Color.FromArgb >> (ShadowR, ShadowG, ShadowB); >> LoBrush = new SolidBrush(ShadowColor); >> LoPen = new Pen(LoBrush, PenWidth); >> >> // The medium color should be a somewhat darker version of >> // the specified BaselineColor >> byte MediumR, MediumG, MediumB; >> MediumR = (byte)((int)BaselineColor.R*4/5); >> MediumG = (byte)((int)BaselineColor.G*4/5); >> MediumB = (byte)((int)BaselineColor.B*4/5); >> Color MediumColor = Color.FromArgb >> (MediumR, MediumG, MediumB); >> MedBrush = new SolidBrush(MediumColor); >> MedPen = new Pen(MedBrush, PenWidth); >> >> // The high color should be a brighter version of the button >> // BaselineColor >> byte HighlightR, HighlightG, HighlightB; >> HighlightR = (byte)( >> (int)BaselineColor.R >> + ( >> (255-BaselineColor.R) >> *1/3 >> ) >> ); >> HighlightG = (byte)( >> (int)BaselineColor.G >> + ( >> (255-BaselineColor.G) >> *1/3 >> ) >> ); >> HighlightB = (byte)( >> (int)BaselineColor.B >> + ( >> (255-BaselineColor.B) >> *1/3 >> ) >> ); >> >> Color HighlightColor = Color.FromArgb >> (HighlightR, HighlightG, HighlightB); >> HiBrush = new SolidBrush(HighlightColor); >> HiPen = new Pen(HiBrush, PenWidth); >> >> } >> else >> { >> LoBrush = BaselineBrush; >> LoPen = BaselinePen; >> MedBrush = BaselineBrush; >> MedPen = BaselinePen; >> HiBrush = BaselineBrush; >> HiPen = BaselinePen; >> } >> >> Pen OutlinePen; >> if (LoOutline) >> OutlinePen = new Pen(Color.Black,PenWidth); >> else if (HiOutline) >> OutlinePen = new Pen(Color.White,PenWidth); >> else >> OutlinePen = new Pen (Color.Black,PenWidth); >> // unused, but prevents compiler warning >> >> if (Shade3D) >> { >> GraphicsPath PathUpperLeft = new GraphicsPath(); >> PathUpperLeft.StartFigure(); >> PathUpperLeft.AddArc(TopLeft,180,90); >> PathUpperLeft.AddLine >> (CurveHalfLeft,rect.Top,MiddleX,MiddleY); >> PathUpperLeft.CloseFigure(); >> e.Graphics.FillPath(HiBrush,PathUpperLeft); >> e.Graphics.DrawPath(MedPen,PathUpperLeft); >> >> GraphicsPath PathUpper = new GraphicsPath(); >> PathUpper.StartFigure(); >> PathUpper.AddLine >> (CurveHalfLeft,rect.Top,CurveHalfRight,rect.Top); >> PathUpper.AddLine(CurveHalfRight,rect.Top,MiddleX,MiddleY); >> PathUpper.CloseFigure(); >> e.Graphics.FillPath(HiBrush,PathUpper); >> e.Graphics.DrawPath(MedPen,PathUpper); >> >> GraphicsPath PathUpperRight = new GraphicsPath(); >> PathUpperRight.StartFigure(); >> PathUpperRight.AddArc(TopRight,270,90); >> PathUpperRight.AddLine >> (rect.Right,CurveHalfTop,MiddleX,MiddleY); >> PathUpperRight.CloseFigure(); >> e.Graphics.FillPath(MedBrush,PathUpperRight); >> e.Graphics.DrawPath(MedPen,PathUpperRight); >> >> GraphicsPath PathRight = new GraphicsPath(); >> PathRight.StartFigure(); >> PathRight.AddLine >> (rect.Right,CurveHalfTop,rect.Right,CurveHalfBottom); >> PathRight.AddLine >> (rect.Right,CurveHalfBottom,MiddleX,MiddleY); >> PathRight.CloseFigure(); >> e.Graphics.FillPath(LoBrush,PathRight); >> e.Graphics.DrawPath(MedPen,PathRight); >> >> GraphicsPath PathLowerRight = new GraphicsPath(); >> PathLowerRight.StartFigure(); >> PathLowerRight.AddArc(BottomRight,0,90); >> PathLowerRight.AddLine >> (CurveHalfRight,rect.Bottom,MiddleX,MiddleY); >> PathLowerRight.CloseFigure(); >> e.Graphics.FillPath(LoBrush,PathLowerRight); >> e.Graphics.DrawPath(MedPen,PathLowerRight); >> >> GraphicsPath PathLower = new GraphicsPath(); >> PathLower.StartFigure(); >> PathLower.AddLine >> (CurveHalfRight,rect.Bottom,CurveHalfLeft,rect.Bottom); >> PathLower.AddLine >> (CurveHalfLeft,rect.Bottom,MiddleX,MiddleY); >> PathLower.CloseFigure(); >> e.Graphics.FillPath(LoBrush,PathLower); >> e.Graphics.DrawPath(MedPen,PathLower); >> >> GraphicsPath PathLowerLeft = new GraphicsPath(); >> PathLower.StartFigure(); >> PathLowerLeft.AddArc (BottomLeft,90,90); >> PathLowerLeft.AddLine >> (rect.Left,CurveHalfBottom,MiddleX,MiddleY); >> PathLowerLeft.CloseFigure(); >> e.Graphics.FillPath(MedBrush,PathLowerLeft); >> e.Graphics.DrawPath(MedPen,PathLowerLeft); >> >> GraphicsPath PathLeft = new GraphicsPath(); >> PathLeft.StartFigure(); >> PathLeft.AddLine >> (rect.Left,CurveHalfBottom,rect.Left,CurveHalfTop); >> PathLeft.AddLine(rect.Left,CurveHalfTop,MiddleX,MiddleY); >> PathLeft.CloseFigure(); >> e.Graphics.FillPath(HiBrush,PathLeft); >> e.Graphics.DrawPath(MedPen,PathLeft); >> >> >> } >> >> GraphicsPath PathWhole = new GraphicsPath(); >> PathWhole.StartFigure(); >> PathWhole.AddArc(TopLeft,180,90); >> PathWhole.AddArc(TopRight,270,90); >> PathWhole.AddArc(BottomRight,0,90); >> PathWhole.AddArc(BottomLeft,90,90); >> PathWhole.CloseFigure(); >> >> if (!Shade3D) >> { >> e.Graphics.FillPath(BaselineBrush,PathWhole); >> } >> >> if (LoOutline || HiOutline) >> { >> e.Graphics.DrawPath(OutlinePen,PathWhole); >> } >> >> } >> >> protected override void OnPaint (PaintEventArgs e) >> { >> if ((Width>50) && (Height>50)) >> { >> ShadowHeight=10; >> ButtonThickness=20; >> } >> else >> { >> ShadowHeight = 3; >> ButtonThickness = 7; >> } >> >> Rectangle ButtonRectangle = new Rectangle(0,0,Width,Height); >> >> // Start by filling in the background image of the parent form. >> // This is necessary so that the parts of the bounding rectangle >> // that are not actually occupied by any part of the button will >> // look like they show the form's background. >> // if (Parent.BackgroundImage == null) >> // { >> // SolidBrush SolBrush = new SolidBrush >> // (Parent.BackColor); >> // e.Graphics.FillRectangle (SolBrush,ButtonRectangle); >> // } >> // else >> // { >> // // Note: "Bounds" coordinates are relative to parent >> // // form, while ButtonRectangle coordinates are >> // // relative to the button. >> // TextureBrush TexBrush = new TextureBrush >> // (Parent.BackgroundImage, Bounds); >> // e.Graphics.FillRectangle (TexBrush,ButtonRectangle); >> // } >> >> ButtonRectangle.Inflate >> (-1*(ShadowHeight/2),-1*(ShadowHeight/2)); >> >> // Move the button if it is pressed >> if (ButtonPressed) >> { >> ButtonRectangle.Offset(ShadowHeight/3,ShadowHeight/3); >> } >> else >> { >> ButtonRectangle.Offset >> (-1*(ShadowHeight/2),-1*(ShadowHeight/2)); >> } >> >> // Draw button shadow >> Rectangle ShadowRectangle = e.ClipRectangle; >> ShadowRectangle.Inflate >> (-1*(ShadowHeight/2),-1*(ShadowHeight/2)); >> ShadowRectangle.Offset(ShadowHeight/2,ShadowHeight/2); >> SpecialRoundRect >> (ShadowRectangle,Color.Black,e,false,false,false); >> >> // Draw button edges >> SpecialRoundRect >> (ButtonRectangle,this.BackColor,e,true,true,false); >> >> // Draw button face >> ButtonRectangle.Inflate >> (-1*(ButtonThickness/2),-1*(ButtonThickness/2)); >> SpecialRoundRect >> (ButtonRectangle,this.BackColor,e,false,false,true); >> >> // Draw the button text in the specified font and color >> if (this.Text.Length > 0) >> { >> StringFormat textFormat = new StringFormat(); >> textFormat.Alignment = StringAlignment.Center; >> textFormat.LineAlignment = StringAlignment.Center; >> e.Graphics.DrawString(this.Text, this.Font, >> new SolidBrush(this.ForeColor), >> ButtonRectangle, textFormat); >> } >> } >> >> protected override void OnMouseDown >> (System.Windows.Forms.MouseEventArgs e ) >> { >> ButtonPressed = true; >> this.Invalidate(); >> this.OnClick(e); >> } >> >> protected override void OnMouseUp >> (System.Windows.Forms.MouseEventArgs e) >> { >> ButtonPressed = false; >> this.Invalidate(); >> } >> >> protected override void OnClick(System.EventArgs e) >> { >> base.OnClick(e); >> } >> } > > --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.742 / Virus Database: 495 - Release Date: 19/08/2004
- Next message: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- Previous message: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- In reply to: Stoitcho Goutsev \(100\) [C# MVP]: "Re: Why must I paint the form background for an owner-draw control?"
- Next in thread: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- Reply: Tim Crews: "Re: Why must I paint the form background for an owner-draw control?"
- Messages sorted by: [ date ] [ thread ]