none
GDI+ "Dor de cabeça"

    Question

  • Ola.

     

    Estou usando GDI+ para gerar duas barras com efeito gradiente, o efeito funciona, mas meu problema é com o onpaint.

     

    Code Snippet

    //Classe que gera o Gradiente:

     

    class Gradiente

    {

    ///

    /// Monta a barra de design

    ///

    /// Recebe a picturebox que irá receber a alteração

    /// Recebe o texto a ser impresso na imagem

    public void MontaBarraDesign(PictureBox pic, string Texto)

    {

    try

    {

    Brush m_Brush;

    Graphics myGraphics ;

    Rectangle m_BrushSize = new Rectangle(0, 0, pic.Width, pic.Height);

    pic.CreateGraphics().Clear(Color.White);

    pic.Refresh();

    // Gera o gradiente

    LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(

    m_BrushSize,

    Color.FromArgb(Convert.ToInt32(Resources.CorRedPrimeira),

    Convert.ToInt32(Resources.CorGreenPrimeira),

    Convert.ToInt32(Resources.CorBluePrimeira)),

    Color.FromArgb(Convert.ToInt32(Resources.CorRedSegunda),

    Convert.ToInt32(Resources.CorGreenSegunda),

    Convert.ToInt32(Resources.CorBlueSegunda)),

    LinearGradientMode.Vertical);

    // Gera o Shape

    myLinearGradientBrush.SetBlendTriangularShape(Convert.ToSingle(0.9));

    m_Brush = myLinearGradientBrush;

    myGraphics = pic.CreateGraphics();

    myGraphics.FillRectangle(m_Brush, m_BrushSize);

     

    // gera o Texto

    Brush myShadowBrush = Brushes.GhostWhite;

    Brush myForeBrush = Brushes.Black;

    SizeF textSize;

    Font myFont = new Font("Tahoma", Convert.ToSingle(9), FontStyle.Bold);

    Single xLocation, yLocation;

    textSize = myGraphics.MeasureString(Texto, myFont);

    xLocation = (50);

    yLocation = (pic.Height - textSize.Height) / 2;

    myGraphics.DrawString(Texto, myFont, myShadowBrush,

    xLocation + Convert.ToSingle(1),

    yLocation + Convert.ToSingle(1));

    myGraphics.DrawString(Texto, myFont, myForeBrush, xLocation, yLocation);

    }

    finally

    { }

    }

    }

     

    Code Snippet

    //Codigo OnPaint

     

    protected override void OnPaint(PaintEventArgs e)

    {

    base.OnPaint(e);

    try

    {

    //if (!teste)

    //{

    Gradiente ObjGradiente = new Gradiente();

    // Barra do titulo

    ObjGradiente.MontaBarraDesign(picTitulo, this.Titulo);

    // Barra acima da listview

    ObjGradiente.MontaBarraDesign(picPesquisa, ((Single)9), this.BarraListview);

    // teste = true;

    //}

    }

    finally

    { }

    }

     

    O problema é o seguinte.

     

    O grafico fica piscando quando eu passo por cima de um controle.

    Utilizando um flag o grafico para de piscar, mas quando maximizo o form o grafico não mantem.

    Fica o desenho até um pedaço e o restante que foi redimensionado fica branco(cor do fundo da picturebox).

    Li alguns posts dizendo para utilizar o metodo Invalidate() da picturebox, mas não consegui fazer funcionar.

    A imagem nao aparece.

     

     

    Monday, June 04, 2007 2:53 PM

All replies

  • Leolima,

     

    Em geral você soluciona o problema de flicker (essa piscada de tela) se você usar double buffer. No .Net Framework é só mudar a propriedade DoubleBuffer do form para true.

     

    Abraços,
    Francisco
    OK, Computer - http://thespoke.net/blogs/fbcjunior/default.aspx

    Monday, June 04, 2007 4:00 PM
  • Francisco.

    Acho que posso nao ter me feito entender.

     

    Não é a tela que pisca, mas sim a picturebox.

    Creio que quando eu movo o mouse sobre um button(por exemplo) o evento OnPaint do form é chamado e a picturebox e preenchida novamente.

     

    Pelo que li o metodo Invalidade do picturebox resolveria o meu problema, mas não sei como aplica-lo.

    Quando tentei a imagem não aparecia.

    Monday, June 04, 2007 4:51 PM
  • leolima,

     

    Basta você chamar o método e ele vai redesenhar o controle:

     

    seuPictureBox.Invalidate();

     

    Mas se você vai continuar usando o seu flag teste, mude para false antes de disparar o Invalidate.

     

    Abraços,
    Francisco
    OK, Computer - http://thespoke.net/blogs/fbcjunior/default.aspx

    Monday, June 04, 2007 4:56 PM
  • Francisco.

    Resolvi da seguinte forma:

     

    Retire as seguintes linhas do metodo

    MontaBarraDesign();

     

    //pic.CreateGraphics().Clear(Color.White);

    //pic.Refresh();

     

    Como não tem refresh e não é dado clear no grafico, não pisca.

    No resize das picturebox, adicionei o this.Invalidate();

     

    Mas isto me cheira a gambiarra....

    Caso alguem possa me informar uma solução mas tecnica!

     

    Monday, June 04, 2007 6:10 PM
  • Leo,

     

    Para que o controle se redesenhe quando você redimensioná-lo sem que você precise chamar o Invalidate no evento Resize, você tem que usar o método SetStyle com a opção ResizeRedraw. O problema é que o PictureBox não expõe o método SetStyle, então você vai ter que invocá-lo via reflection.

     

    Fiz um teste aqui e aparentemente funcionou corretamente. Coloquei um PictureBox num form, mudei a propriedade Dock para Fill e no evento Paint:

     

    e.Graphics.DrawEllipse(Pens.Green, pictureBox1.ClientRectangle);

     

    No evento Load do Form:

     

    System.Reflection.MethodInfo mi;

    mi = pictureBox1.GetType().GetMethod("SetStyle",

                                                                 System.Reflection.BindingFlags.NonPublic |

                                                                 System.Reflection.BindingFlags.Instance);

    mi.Invoke(pictureBox1, new object[] {ControlStyles.ResizeRedraw, true});

     

    Execute o aplicativo, mude o form de tamanho e perceba que a elipse é redesenhada.

    Comente o código acima e faça o teste sem ele para perceber a diferença.

     

    Abraços,
    Francisco
    OK, Computer - http://thespoke.net/blogs/fbcjunior/default.aspx

    Monday, June 04, 2007 6:45 PM