Pergunta

eu ter derivado de um TabControl com o propósito expresso de permitir que o buffer duplo, exceto nada está funcionando como esperado. Aqui está o código TabControl:

class DoubleBufferedTabControl : TabControl
{
    public DoubleBufferedTabControl() : base()
    {
        this.DoubleBuffered = true;
        this.SetStyle
            (
                ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.ResizeRedraw |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.SupportsTransparentBackColor,
                false
            );
    }
}

Esta tabcontrol é, então, definir com o seu modo de desenho como 'OwnerDrawnFixed' para que eu possa mudou as cores. Aqui está o método desenho personalizado:

    private void Navigation_PageContent_DrawItem(object sender, DrawItemEventArgs e)
    {
        //Structure.
        Graphics g = e.Graphics;
        TabControl t = (TabControl)sender;
        TabPage CurrentPage = t.TabPages[e.Index];

        //Get the current tab
        Rectangle CurrentTabRect = t.GetTabRect(e.Index);

        //Get the last tab.
        Rectangle LastTab = t.GetTabRect(t.TabPages.Count - 1);

        //Main background rectangle.
        Rectangle BackgroundRect = new Rectangle(LastTab.Width, t.Bounds.Y - 4, t.Width - (LastTab.Width), t.Height);

        //Tab background rectangle.
        Rectangle TabBackgroundRect = new Rectangle(0, LastTab.Y + LastTab.Height, LastTab.Width, t.Bounds.Height - (LastTab.Y + LastTab.Height));

        //Set anitialiasing for the text.
        e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

        //String format for the text.
        StringFormat StringFormat = new StringFormat();
        StringFormat.Alignment = StringAlignment.Center;
        StringFormat.LineAlignment = StringAlignment.Center;

        //Fill the background.
        g.FillRectangle(Brushes.LightGray, BackgroundRect);
        g.FillRectangle(Brushes.Bisque, TabBackgroundRect);

        //Draw the selected tab.
        if(e.State == DrawItemState.Selected)
        {
            g.FillRectangle(Brushes.White, e.Bounds);
            Rectangle SelectedTabOutline = new Rectangle(e.Bounds.X + 2, e.Bounds.Y + 2, e.Bounds.Width, e.Bounds.Height - 4);
            g.DrawRectangle(new Pen(Brushes.LightGray, 4f), SelectedTabOutline);
            g.DrawString(CurrentPage.Text, new Font("Arial", 12f, FontStyle.Bold, GraphicsUnit.Point), new SolidBrush(Color.FromArgb(70, 70, 70)), CurrentTabRect, StringFormat);
        }
        else
        {
            g.FillRectangle(new SolidBrush(Color.FromArgb(230, 230, 230)), e.Bounds);
            g.DrawString(CurrentPage.Text, new Font("Arial", 12f, FontStyle.Regular, GraphicsUnit.Point), Brushes.Gray, CurrentTabRect, StringFormat);
        }

    }

Todos sem sucesso no entanto, como este controle não é duplo em buffer e ainda treme quando redimensionado.

Alguma idéia?

Foi útil?

Solução

Se você ler a documentação, ele diz: "Este membro não é significativo para esse controle." Se você deseja que o controle a ser desenhado utilizando buffer duplo, você vai ter que implementá-lo. Além do fato de que, se você proprietário-desenhar o controle, você teria que implementar o buffer duplo-se de qualquer maneira.

Outras dicas

Em primeiro lugar, você pode se livrar de seu código-lo TabControl ligar o buffer e, em seguida, desligue-a imediatamente, para que ele não está realmente fazendo alguma coisa útil.

Parte do seu problema é que você está tentando pintar apenas parte do TabControl.

A solução mais fácil que dá sobre uma solução de 90% (ainda é possível obter um flicker) é adicionar isto a sua classe de formulário:

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
    }
}

Se você quer ser muito certeza de obter nenhuma cintilação, você precisa desenhar todo o TabControl si mesmo, e certifique-se de ignorar os pedidos do fundo da pintura.

Edit:. Note que isto só irá funcionar no XP e mais tarde

Eu tive problemas com o buffer duplo em controles no passado e que a única maneira de parar a cintilação era assegurar o método OnPaintBackground herdou não estava sendo chamado. (Ver código abaixo) Você também vai precisar para assegurar todo o backgound é pintada durante a chamada tinta.

protected override void OnPaintBackground( PaintEventArgs pevent )
{
    //do not call base - I don't want the background re-painted!
}

Não tenho certeza, mas você pode tentar buffer duplo o controle que contém o controle guia.

Eu olhei ao redor um pouco, tentou o seu código e qualquer outra coisa que eu poderia pensar, mas eu não vejo uma maneira de se livrar do flicker. Infelizmente, em meus testes, mesmo um regular (não-proprietário desenhado) controle de guia pisca durante o redimensionamento.

Por que vale a pena, desligando "Mostrar conteúdo da janela ao arrastar" irá corrigi-lo, mas eu percebo que pode não ser útil.

Eu acho que ele não funciona porque você está desativando o buffer duplo!

Todos os this.DoubleBuffered = true não está definido ControlStyles.OptimizedDoubleBuffer para true. Desde que você está desativando essa bandeira na próxima linha do seu programa, você está realmente fazendo nada. Remover ControlStyles.OptimizedDoubleBuffer (e talvez ControlStyles.AllPaintingInWmPaint) e ele deve funcionar para você.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top