0

I need a custom TabControl with different TabPage Header. I've set the DrawMode Property to "OwnerDrawFixed" in order to get the OnDrawItem Method called.

In The OnDrawItem Method I do this:

        protected override void OnDrawItem(DrawItemEventArgs e)
    {
        base.OnDrawItem(e);

        var tabPage = TabPages[e.Index];
        if (tabPage != null) 
        {
            if (tabPage is BackOfficeTabPage) 
            {
                ((BackOfficeTabPage)tabPage).DrawTab(e.Graphics, GetTabRect(e.Index));
            }
        }
    }

The code will be called for each existing Page, also with the matching index. But whatever I do it's always the same Header who it's drawing on.

The rectangle he is drawing onto seems to be correct. I also tried it that way:

        protected override void OnDrawItem(DrawItemEventArgs e)
    {
        base.OnDrawItem(e);

        var tabPage = TabPages[e.Index];
        if (tabPage != null) 
        {
            if (tabPage is BackOfficeTabPage) 
            {
                ((BackOfficeTabPage)tabPage).DrawTab(e.Graphics, e.Bounds);
            }
        }
    }

Same Result. That's my DrawTab function:

        internal void DrawTab(Graphics g, Rectangle rect) 
    {
        if (State != null) 
        {
            if (State.HasInvalidBuffers()) 
            {
                CreateFrames(rect);
            }
            if (State.IsInvalidate) 
            {
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                if (State.IsHover)
                {
                    g.DrawImage(State.HoverBufferFrame, rect);
                }
                else if (State.IsSelected)
                {
                    g.DrawImage(State.SelectionBufferFrame, rect);
                }
                else 
                {
                    g.DrawImage(State.DefaultBufferFrame, rect);
                }
                if (State.IsCloseFocused)
                {
                    g.DrawImage(State.FocusedCloseButtonBufferFrame, State.CloseButtonRectangle);
                }
                else 
                {
                    g.DrawImage(State.DefaultCloseButtonBufferFrame, State.CloseButtonRectangle);
                }
                State.IsInvalidate = false;
            }
        }
    }

every tab should be orange. But only the first one will displayed correctly. (link to pic)

I don't get my mistake.

I hope somebody can enlight me :)

Best Regards,

Simon

*****Update***** This is the entire code of the TabPage Control which is doing the tab painting. I am not sure why but the buffer Images from the second tab are always transparent.

    public sealed class BackOfficeTabPage : TabPage
{
    #region Fields
    private string _text = string.Empty;
    private string _imageKey = string.Empty;
    private TabState _tabstate = new TabState();
    private Brush _regluarBrush = new SolidBrush(Color.Transparent);
    private Brush _selectedBrush = null;
    private Brush _hoverBrush = null;
    private int _imageIndex = 0;
    #endregion
    #region Properties
    public Brush RegularBrush 
    {
        get 
        { 
            return _regluarBrush; 
        }
        set 
        {
            _regluarBrush = value;
            _tabstate.InvalidateImageBuffers();
            _tabstate.IsInvalidate = true;
            if (ParentTabControl != null)
                ParentTabControl.Invalidate();
        }
    }
    public Brush SelectedBrush 
    {
        get 
        {
            return _selectedBrush;
        }
        set 
        {
            _selectedBrush = value;
            _tabstate.InvalidateImageBuffers();
            _tabstate.IsInvalidate = true;
            if (ParentTabControl != null)
                ParentTabControl.Invalidate();
        }
    }
    public Brush HoverBrush 
    {
        get 
        {
            return _hoverBrush;
        }
        set 
        {
            _hoverBrush = value;
            _tabstate.InvalidateImageBuffers();
            _tabstate.IsInvalidate = true;
            if (ParentTabControl != null)
                ParentTabControl.Invalidate();
        }
    }
    public BackOfficeTabControl ParentTabControl
    {
        get 
        {
            if (Parent != null && Parent is BackOfficeTabControl)
                return (BackOfficeTabControl)Parent;
            return null;
        }
    }
    public new int ImageIndex
    {
        get
        {
            return _imageIndex;
        }
        set
        {
            _tabstate.InvalidateImageBuffers();
            _tabstate.IsInvalidate = true;
            if (OnPropertyChanged != null)
                OnPropertyChanged(this, new PropertyChangedEventArgs("ImageIndex", _imageIndex, value));
            _imageIndex = value;
            base.ImageIndex = value;
        }
    }
    public new string ImageKey
    {
        get
        {
            return _imageKey;
        }
        set
        {
            _tabstate.InvalidateImageBuffers();
            _tabstate.IsInvalidate = true;
            if (OnPropertyChanged != null)
                OnPropertyChanged(this, new PropertyChangedEventArgs("ImageKey", _imageKey, value));
            _imageKey = value;
            base.ImageKey = value;
        }
    }
    public TabState State 
    {
        get 
        {
            return _tabstate;
        }
        set 
        {
            if (OnPropertyChanged != null)
                OnPropertyChanged(this, new PropertyChangedEventArgs("State", _tabstate, value));
            _tabstate = value;
        }
    }
    public new string Text
    {
        get { return _text; }
        set
        {
            _tabstate.InvalidateImageBuffers();
            _tabstate.IsInvalidate = true;
            if (OnPropertyChanged != null)
                OnPropertyChanged(this, new PropertyChangedEventArgs("Text", _text, value));
            _text = value;
            base.Text = value;
        }
    }
    public Image AssocImage 
    {
        get 
        {
            Image image = null;
            if ((!string.IsNullOrEmpty(ImageKey) || ImageIndex >= 0) && ParentTabControl.ImageList != null)
            {
                if (!string.IsNullOrEmpty(ImageKey))
                    image = ParentTabControl.ImageList.Images[ImageKey];
                else
                    image = ParentTabControl.ImageList.Images[ImageIndex];
            }
            return null;
        }

    }
    #endregion
    #region Events
    public event EventHandler<PropertyChangedEventArgs> OnPropertyChanged = null;
    #endregion

    #region Functions
    internal void test(Rectangle rect) 
    {
        if (State.HasInvalidBuffers())
        {
            CreateFrames(rect);
        }
    }
    internal void DrawTab(Graphics g, Rectangle rect) 
    {
        if (State != null) 
        {
            if (State.HasInvalidBuffers()) 
            {
                CreateFrames(rect);
            }
            if (State.IsInvalidate) 
            {
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                if (State.IsHover)
                {
                    g.DrawImage(State.HoverBufferFrame,rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
                }
                else if (State.IsSelected)
                {
                    g.DrawImage(State.SelectionBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
                }   
                else 
                {
                    g.DrawImage(State.DefaultBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
                }
                if (State.IsCloseFocused)
                {
                    g.DrawImage(State.FocusedCloseButtonBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
                }
                else 
                {
                    g.DrawImage(State.DefaultCloseButtonBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
                }
                State.IsInvalidate = false;
            }
        }
    }
    internal void CreateFrames(Rectangle rect) 
    {
        Image image = AssocImage;
        Rectangle imageRectangle = Rectangle.Empty, textRectangle = Rectangle.Empty, closeButtonRectangle = Rectangle.Empty;
        if (image != null) 
        {
            imageRectangle = new Rectangle(rect.X + 2, rect.Y + 2, ParentTabControl.ImageScaling.Width, ParentTabControl.ImageScaling.Height);
        }
        if (ParentTabControl != null && ParentTabControl.ShowCloseButton && ParentTabControl.CloseButtonImage != null) 
        {
            closeButtonRectangle = new Rectangle(rect.X + rect.Width - (16), rect.Y + 2, 14, 14);
        }
        if (!string.IsNullOrEmpty(Text)) 
        {
            if (imageRectangle != Rectangle.Empty)
            {

                if (closeButtonRectangle != Rectangle.Empty)
                {
                    textRectangle = new Rectangle(imageRectangle.X + imageRectangle.Width + 1, rect.Y, closeButtonRectangle.X - (imageRectangle.X + imageRectangle.Width + 2), rect.Height);
                }
                else 
                {
                    textRectangle = new Rectangle(imageRectangle.X + imageRectangle.Width + 1, rect.Y, rect.X + rect.Width - (imageRectangle.X + imageRectangle.Width + 2), rect.Height);                    
                }

            }
            else 
            {
                if (closeButtonRectangle != Rectangle.Empty)
                {
                    textRectangle = new Rectangle(rect.X + 1, rect.Y, closeButtonRectangle.X - (rect.X + 2), rect.Height);
                }
                else 
                {
                    textRectangle = new Rectangle(rect.X + 1, rect.Y, rect.Width - 2, rect.Height);
                }
            }
        }
        State.ImageRectangle = rect;
        State.CloseButtonRectangle = closeButtonRectangle;
        CreateSelectionFrame(rect, imageRectangle, textRectangle);
        CreateHoverFrame(rect, imageRectangle, textRectangle);
        CreateDefaultFrame(rect, imageRectangle, textRectangle);
        CreateCloseButtonFrames(closeButtonRectangle);

    }

    internal void CreateSelectionFrame(Rectangle rect, Rectangle imageRect, Rectangle textRect)
    {
        if (rect != Rectangle.Empty) 
        {
            Image buffer = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
            using (Graphics g = Graphics.FromImage(buffer)) 
            {
                g.Clear(Color.Transparent);
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                Color light = SystemColors.Window, dark = Color.FromArgb(229, 195, 101);
                g.FillRectangle(new LinearGradientBrush(rect, light, dark, LinearGradientMode.Vertical), rect);
                if (imageRect != Rectangle.Empty)
                {
                    Image img = AssocImage;
                    if (img != null)
                    {
                        g.DrawImage(img, imageRect);
                    }
                }
                if (!string.IsNullOrEmpty(Text) && textRect != Rectangle.Empty)
                {
                    StringFormat format = new StringFormat();
                    format.Alignment = StringAlignment.Center;
                    format.Trimming = StringTrimming.EllipsisCharacter;
                    g.DrawString(Text, this.Font, new SolidBrush(ForeColor), new RectangleF(textRect.X, textRect.Y, textRect.Width, textRect.Height), format);
                }
            }
            State.SelectionBufferFrame = buffer;
        }
    }

    internal void CreateHoverFrame(Rectangle rect, Rectangle imageRect, Rectangle textRect)
    {
        if (rect != Rectangle.Empty)
        {
            Image buffer = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
            using (Graphics g = Graphics.FromImage(buffer)) 
            {
                g.Clear(Color.Transparent);
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                Color light = Color.FromArgb(108, 116, 118), dark = Color.FromArgb(108, 116, 118);
                g.FillRectangle(new LinearGradientBrush(rect, light, dark, LinearGradientMode.Vertical), rect);
                if (imageRect != Rectangle.Empty)
                {
                    Image img = AssocImage;
                    if (img != null)
                    {
                        g.DrawImage(img, imageRect);
                    }
                }
                if (!string.IsNullOrEmpty(Text) && textRect != Rectangle.Empty)
                {
                    StringFormat format = new StringFormat();
                    format.Alignment = StringAlignment.Center;
                    format.Trimming = StringTrimming.EllipsisCharacter;
                    g.DrawString(Text, this.Font, new SolidBrush(ForeColor), new RectangleF(textRect.X, textRect.Y, textRect.Width, textRect.Height), format);
                }
            }
            State.HoverBufferFrame = buffer;
        }
    }
    internal void CreateDefaultFrame(Rectangle rect, Rectangle imageRect, Rectangle textRect)
    {
        if (rect != Rectangle.Empty)
        {
            Image buffer = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
            using (Graphics g = Graphics.FromImage(buffer)) 
            {
                g.Clear(Color.Transparent);
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                Color light = Color.Orange, dark = Color.Orange;
                g.FillRectangle(new LinearGradientBrush(rect, light, dark, LinearGradientMode.Vertical), rect);
                if (imageRect != Rectangle.Empty)
                {
                    Image img = AssocImage;
                    if (img != null)
                    {
                        g.DrawImage(img, imageRect);
                    }
                }
                if (!string.IsNullOrEmpty(Text) && textRect != Rectangle.Empty)
                {
                    StringFormat format = new StringFormat();
                    format.Alignment = StringAlignment.Center;
                    format.Trimming = StringTrimming.EllipsisCharacter;
                    g.DrawString(Text, this.Font, new SolidBrush(ForeColor), new RectangleF(textRect.X, textRect.Y, textRect.Width, textRect.Height), format);
                }
            }
            State.DefaultBufferFrame = buffer;

        }
    }
    internal void CreateCloseButtonFrames(Rectangle closeBtnRect)
    {
        if (closeBtnRect != Rectangle.Empty)
        {
            if (ParentTabControl != null && ParentTabControl.CloseButtonImage != null && ParentTabControl.ShowCloseButton) 
            {
                //closeBtnRect
                Image buffer = new Bitmap(closeBtnRect.Width, closeBtnRect.Height, PixelFormat.Format32bppArgb);
                using (Graphics g = Graphics.FromImage(buffer)) 
                {
                    g.Clear(Color.Transparent);
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    g.FillRectangle(new SolidBrush(Color.Transparent), closeBtnRect);
                    g.DrawImage(SetImageOpacity(ParentTabControl.CloseButtonImage, 0.5f), closeBtnRect.X, closeBtnRect.Y, closeBtnRect.Width, closeBtnRect.Height);
                }
                State.DefaultCloseButtonBufferFrame = buffer;

                buffer = new Bitmap(closeBtnRect.Width, closeBtnRect.Height, PixelFormat.Format32bppArgb);
                using (Graphics g = Graphics.FromImage(buffer))
                {
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    g.FillRectangle(new SolidBrush(Color.Transparent), closeBtnRect);
                    g.DrawImage(ParentTabControl.CloseButtonImage, closeBtnRect.X, closeBtnRect.Y, closeBtnRect.Width, closeBtnRect.Height);
                }
                State.FocusedCloseButtonBufferFrame = buffer;

            }                
        }
    }
    /// <summary>  
    /// method for changing the opacity of an image  
    /// </summary>  
    /// <param name="image">image to set opacity on</param>  
    /// <param name="opacity">percentage of opacity</param>  
    /// <returns></returns>  
    private Image SetImageOpacity(Image image, float opacity)
    {
        try
        {
            //create a Bitmap the size of the image provided  
            Bitmap bmp = new Bitmap(image.Width, image.Height);

            //create a graphics object from the image  
            using (Graphics gfx = Graphics.FromImage(bmp))
            {

                //create a color matrix object  
                ColorMatrix matrix = new ColorMatrix();

                //set the opacity  
                matrix.Matrix33 = opacity;

                //create image attributes  
                ImageAttributes attributes = new ImageAttributes();

                //set the color(opacity) of the image  
                attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

                //now draw the image  
                gfx.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
            }
            return bmp;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            return null;
        }
    } 
    #endregion

    #region Constr
    public BackOfficeTabPage() : base() 
    {

    }
    public BackOfficeTabPage(string text)
        : base(text)
    {

    }
    #endregion
}
Dev86
  • 91
  • 9
  • Looks to me that's exactly the way you coded it. You are only making it orange when the TabPage is a BackOfficeTabPage, the rest remain unpainted. – Hans Passant Oct 27 '16 at 14:50
  • Hi. Yes Sir. No Problem with that cause there are only this type of tab pages in it. :). I get closer to mark the issue but not sure where the Problem is exactly. I've the TabControl and I've written a own TabPage Control. The TabPage own a few image buffers for each visual state it can get. Apperently it filling the buffer Images for the first tab perfectly. But the buffer Images for the second Tab are transparent. I'll post the entire code of the TabPage Control below. Hopefully you see a mistake :) – Dev86 Oct 28 '16 at 11:41

0 Answers0