0

I have a custom TabControl control. Here's the OnPaint method:

Protected Overrides Sub OnPaint(e As PaintEventArgs)

        G = e.Graphics
        G.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
        G.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit

        MyBase.OnPaint(e)

        G.Clear(ColorFromHex("#343843"))

        For I As Integer = 0 To TabPages.Count - 1

            Rect = GetTabRect(I)

            Dim Data As AccountData = DirectCast(TabPages(I).Tag, AccountData)

            If Data IsNot Nothing Then
                TabPages(I).ImageIndex = Data.Icon / 2
            End If

            If SelectedIndex = I Then

                Using B1 As New SolidBrush(ColorFromHex("#3A3E49"))
                    G.FillRectangle(B1, New Rectangle(Rect.X - 4, Rect.Y + 1, Rect.Width + 6, Rect.Height))
                End Using

            End If

            Using B1 As New SolidBrush(ColorFromHex("#737A8A"))

                If UpperText Then

                    Using F1 As New Font("Segoe UI", 7.75, FontStyle.Bold)
                        G.DrawString(TabPages(I).Text.ToUpper, F1, B1, New Point(Rect.X + 70, Rect.Y + 10))

                        If Data Is Nothing Then
                            G.DrawString("Idle", F1, B1, New Point(Rect.X + 70, Rect.Y + 20))
                        Else
                            G.DrawString(Data.Status, F1, B1, New Point(Rect.X + 70, Rect.Y + 20))
                            G.DrawString("Lv. " & Data.Level, F1, B1, New Point(Rect.X + 70, Rect.Y + 30))
                            G.DrawString(Data.IP & " IP / " & Data.RP & " RP", F1, B1, New Point(Rect.X + 70, Rect.Y + 40))
                        End If
                    End Using

                Else

                    Using F1 As New Font("Segoe UI semibold", 9)
                        G.DrawString(TabPages(I).Text, F1, B1, New Point(Rect.X + 50, Rect.Y + 11))
                    End Using

                End If

            End Using

            If Not I = 0 Then

                Using P1 As New Pen(ColorFromHex("#3B3D49")), P2 As New Pen(ColorFromHex("#2F323C"))
                    G.DrawLine(P1, New Point(Rect.X - 4, Rect.Y + 1), New Point(Rect.Width + 4, Rect.Y + 1))
                    G.DrawLine(P2, New Point(Rect.X - 4, Rect.Y + 2), New Point(Rect.Width + 4, Rect.Y + 2))
                End Using

            End If

            If Not IsNothing(ImageList) Then
                If Not TabPages(I).ImageIndex < 0 Then
                    G.DrawImage(ImageList.Images(TabPages(I).ImageIndex), New Rectangle(Rect.X + 10, Rect.Y + 10, 48, 48))
                End If
            End If

        Next

    End Sub

As you can see, it checks for the tag. If the tag is not null, it draws the Status property, the Level property and the IP / RP properties. Each tab is associated with a player, so when the player logs in the tag is set to the appropriate AccountData value and then I call the following to update it:

public void UpdateAccountData(int index, AccountData data)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(() => this.UpdateAccountData(index, data)));

                return;
            }

            this.aetherTabControl1.TabPages[index].Tag = data;
            this.aetherTabControl1.TabPages[index].Invalidate(true);
            this.aetherTabControl1.TabPages[index].Update();
            this.aetherTabControl1.TabPages[index].Refresh();
        }

I know this is bad, but I'm not sure how to redraw it everytime I update a property of AccountData. Is there a better way to do this instead of repainting it everytime?

Thanks.

Gilbert Williams
  • 970
  • 2
  • 10
  • 24
  • 1
    If you don't repaint it then you can't see the change, doesn't get more basic than that. Just do this properly, don't repaint it twice and don't force it. And use the proper Invalidate() call, it needs to be this.aetherTabControl1.Invalidate() since you want the tab control's OnPaint() method to run, not the tabpage's. And surely you got the advice before to do this the correct way with TabControl.DrawItem? – Hans Passant Dec 18 '15 at 11:42

1 Answers1

-1

Yes there is a better way.
Way 1:Your AccountData properties are reflected in the screen via labels or textboxes or other controls, right?!? if, upon AccountData update, you reset the values of such controls, they will automatically repaint...

Way 2: sticking with your "repaint by myself" approach, you can buffer up a bunch of stuff, such as Brushers, Colors and perhaps turn the images in a sprite dynamically, so in the end of the repaint, you only need to paint a different part of the sprite, instead of the whole thing...

Leonardo
  • 10,737
  • 10
  • 62
  • 155