0

I am trying to create a program that is able to analyze DNA data and visualize the differences compared to a reference sequence of DNA. This involves a big number of letters that I want drawn on a Panel with each base (A, C, G, T) having a different background color. So horizontal lines would represent a single line of DNA.

Up to now I have this as a test :

Creating the bitmap

    Bitmap bit;

    public Form1()
    {
        InitializeComponent();

        bit = new Bitmap(15, 15);
        Graphics g = Graphics.FromImage(bit);
        g.FillRectangle(new SolidBrush(Color.Red), new Rectangle(1, 1, 13, 13));
        g.Dispose();
    }

And this is the Onpaint handler of the Panel i am drawing on:

    private void p_Paint(object sender, PaintEventArgs e)
    {
        int x_Start = e.ClipRectangle.X;
        int x_Length = e.ClipRectangle.Width;
        int y_Start = e.ClipRectangle.Y;
        int y_Length = e.ClipRectangle.Height;

        Bitmap insb = new Bitmap(RoundUp(x_Length), RoundUp(y_Length));
        Panel p = (Panel)sender;

        Graphics g = p.CreateGraphics();
        Graphics bmp = Graphics.FromImage(insb);

        for (int y = 0; y < insb.Height; y += 15)
        {
            for (int x = 0; x < insb.Width; x += 15)
            {
                bmp.DrawImage(bit, x, y);
            }
        }
        g.DrawImage(insb, x_Start, y_Start);
        bmp.Dispose();
        g.Dispose();
   }

This creates a grid of squares but when I scroll this it flickers like crazy...

I have set the Doublebuffered property of the Panel to true like this :

        typeof(Panel).InvokeMember("DoubleBuffered",
        BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
        null, listHolder.Controls[0], new object[] { true });

And this made a slight improvement but it is still far from where I want it to be. What am i doing wrong? (Also this is my first post so be gentle please ;))

  • Did you set the `DoubleBuffered` of the `Form` to `true`? There's no real need to reflect into the panel to do it. It might even mean it is ignored - not sure. You should just set the form's property instead. – SimpleVar Sep 15 '14 at 20:19
  • 1
    Don't use `p.CreateGraphics()`. Grab the graphics from `PaintEventArgs e` and don't dispose it afterwards. – TyCobb Sep 15 '14 at 20:20
  • And if its only letters with altering background colors, they really don't have to be images. – SimpleVar Sep 15 '14 at 20:21
  • 3
    Using CreateGraphics() for painting is wrong 99.9% of the time. Especially when you use double-buffering, whatever you draw will be quickly erased again when the back-buffer is blitted to the screen. Looks like flicker as well, the drastic kind. You *must* use e.Graphics in the Paint event handler so you draw into the back buffer instead of the screen. Using InvokeMember() is a hack, just derive your own class from Panel. You also need to set the ResizeRedraw property to *true* in the constructor or resizing will look rather badly. Give you bitmaps the 32bppPArgb pixel format, x10 faster – Hans Passant Sep 15 '14 at 20:24
  • I have done everything you suggested @HansPassant but its still flickering... I've created a custom extension on the Panel class and set the doublebuffered property to true. I've changed all the bitmaps to the correct pixelformat. I've now got the e.Graphics.DrawImage instead of p.DrawImage so I should be ok... Any other ideas of what I am doing wrong ? Or maybe a different route I should take all together ? Thanks for all the help anyways! – Sjoerd Redeker Sep 16 '14 at 07:15
  • @YoryeNathan I have set the doublebuffered property on the form aswell but that didnt make any difference... – Sjoerd Redeker Sep 16 '14 at 08:30
  • Have you considered using labels with background colors dynamically created instead of images? – SimpleVar Sep 16 '14 at 16:27
  • @yoryeNathan Yes I have tried that but that seems to be way slower than drawing the items yourself... – Sjoerd Redeker Sep 16 '14 at 17:25
  • Moving labels is slower than moving images? Drawing labels is slower than drawing images? No. Surely not. Show the code you used, it must've been flawed. – SimpleVar Sep 16 '14 at 17:47
  • @Yoryenathan I have tried adding those labels but its about 8000 labels and adding those labels to the form takes a long time. Or is there a faster way to do this? – Sjoerd Redeker Sep 17 '14 at 08:10
  • Adding 8000 labels might indeed not be fluent, but I can't imagine drawing 8000 images will be faster. – SimpleVar Sep 17 '14 at 10:40

1 Answers1

0

Found the answer: The whole double buffering was not working. Eventually I added this to my Form Load :

System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
aProp.SetValue(canvas, true, null);

And I added this to my form contructor

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();

And in this the canvas beeing the panel to wich I draw everything... Thanks for all the help!