Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

Apologies if this is obvious...

 

I'm using VB in VS.NET Pro.

 

I want to update a plot of data as the data comes in the serial port.

 

I maintain a Bitmap on which I plot the data. Every time a new point comes in, I update the Bitmap and invalidate the control (a Panel).

 

During the Panel's Paint event, I grab the graphics object and draw

the entire Bitmap image.

 

It works, but the Panel flickers annoyingly as the entire Bitmap is redrawn. My PC runs at 2.4GHz.

 

Is there a way to draw just the new data, without redrawing the old data (axes, tick marks, previous points)?

 

Thanks.

 

P.S. I did try using a Metafile instead of a Bitmap, but I was unsuccessful at appending data to an existing Metafile.

Posted

You can use the method you're currently using to draw a particular section directly to screen, but it's often preferrable to use a backbuffer.

 

To implement a backbuffer, create an image in memory (to which you can grab a handle), draw directly to that, and then draw the entire thing onto your Panel. I'm not too familiar with the Panel control, but the PictureBox control may provide you with a little more flexibility in terms of drawing functionality.

 

Good luck!

zig?
Posted

Thanks for responding...

 

You can use the method you're currently using to draw a particular section directly to screen, ...

 

I'd like to know how to do that.

 

The Paint event, it seems, can be used to paint everything only, not a subset. I did try to draw just a rectangle surrounding the new data, and it did that, but the rest of the Panel was blanked.

 

I don't think a PictureBox would help, since it doesn't support the DrawImage method. By the way, I did this once before in VB6, in which the PictureBox control DOES support DrawImage, and it worked beautifully. Put me down as one of the .NET skeptics.

 

Still stuck... :(

Posted

Similar to drawing to/from a buffer, you'll need to get a handle to the Panel (or PictureBox) and perform a BitBlt directly onto that device context. Finding DC's and performing blt operations are all well-documented in MSDN, but if you're not sure where to start I can find some articles to point you in the right direction.

 

Sorry if any of this stuff I'm suggesting is out of date, I've completely dropped VB.net in favor of C#, and I haven't had much time to dabble in GDI+ yet - though I know what I'm suggesting is still possible (even if it may not be the ".NET way").

 

If someone knows an easier way for rws to accomplish this, feel free to correct me. :)

zig?
Posted

BitBlt looks like a good approach, but I think it is out of VB's scope.

 

I found a solution: I created a new panel, sized to surround the new plot data, and I invalidate it instead of the entire Bitmap. The new panel roams around the larger original panel, which contains it.

 

Kind of clunky, but the flicker is eliminated. I'm sure there's still a better way.

 

Thanks, steved!

Posted

BitBlt isn't out of VB6's scope, so I'm sure it's still around in GDI+ for use in VB.net. ;) It would certainly be perferable to moving controls around within other controls.

 

There might even be a better way than BitBlt, though. Poke around the System.Drawing namespace and see what you can find.

zig?
Posted

Draw the graphics to a bitmap in memory first, then apply it to your object. Thats what I do with my Mp3 players, ect.. that I create music visuals for. I used to get tons of flicker by applying it straight to the picturebox object. Now that I create it in memory first then apply to the object, I have zero flicker and tons of speed to go with it.

 

 

Jason

Posted

Camaro,

 

I think that you are describing what I tried originally. I kept a Bitmap in memory, and kept it up-to-date. Every time I updated the Bitmap, I invalidated the Panel. This would trigger the Paint event for the Panel. In the Paint event I would draw the Bitmap (DrawImage method). The result was a nice real-time graph of my data, with lots of annoying flicker.

 

My current strategy, as I described previously, is to do the same thing on a much smaller Panel (the panel containing the new data). The "big picture" flicker is eliminated.

 

I'm still not happy with the results: there are other side-effects of my current strategy.

 

I'm not quite sure what you mean by "apply it to your object." Your comments make sense to me from a VB6 point of view, but not from a .NET point of view.

 

Thanks for responding.

Guest mutant
Posted
What code are you using in Paint event that it is flickering?
Posted
Public Class PlotArea

' Module-level declarations:
   Private BMap As Bitmap 
   Friend Pen As New Pen(Color.Black, 1)
   Friend WithEvents Window As Panel
'
'Constructor:
Public Sub New (list of dimensional arguments)
'...
       Window = New Panel()
       With Window
           .Left = whatever (derived from the dimensional arguments)
           .Width = ditto
           .Height =  ditto
           .Top = ditto
           .BorderStyle = BorderStyle.FixedSingle
       End With

       'Create a bitmap image of the Window's graphics layer
       BMap = New Bitmap(Window.Width, Window.Height, Window.CreateGraphics())
'...
End Sub
'
'    'Here's the method that does the actual plotting:
   Friend Overloads Sub Plot(ByVal x1 As Single, ByVal y1 As Single, ByVal x2 As Single, ByVal y2 As Single)
       Dim PlotGob As Graphics = Graphics.FromImage(BMap)
       Dim x1point, y1point, x2point, y2point As Integer

       x1point = xpixel(x1)   'converts to pixels
       y1point = ypixel(y1)
       x2point = xpixel(x2)
       y2point = ypixel(y2)
       PlotGob.DrawLine(Pen, x1point, y1point, x2point, y2point)
       PlotGob.Dispose()
       Window.Invalidate()   'triggers the paint event
   End Sub
'
'The Window Paint Event:
   Private Sub Window_Paint(ByVal sender As Object, ByVal pe As System.Windows.Forms.PaintEventArgs) Handles Window.Paint
       Dim PaintGob As Graphics = pe.Graphics
       PaintGob.DrawImage(BMap, 0, 0)
       PaintGob.Dispose()
   End Sub

End Class

  • *Gurus*
Posted
Double-buffering for flicker-free graphics is built in to the .NET framework. All you have to do it call SetStyle to enable the DoubleBuffer and AllPaintingInWmPaint styles for your control, and perform all your drawing in the Paint event, using the Graphics instance supplied. No offscreen bitmap is required, this is taken care of.

MVP, Visual Developer - .NET

 

Now you see why evil will always triumph - because good is dumb.

 

My free .NET Windows Forms Controls and Articles

Posted

That sure sounds like what I've been looking for!

 

However, I'm having a little trouble calling the SetStyle method because it is Protected.

 

My understanding is that a Protected method is callable from a derived class. My object is a Panel, which is derived from Control.

 

What am I missing here?

Guest mutant
Posted

Its not a method of a control. Just simply type:

SetStyle(chooseproperty,trueorfalse)

  • *Gurus*
Posted

Protected means you can only call it from _within_ a derived class. So you'll have to derive from Panel yourself and use SetStyle in the constructor, ideally.

 

It's also a good idea to wrap your existing drawing functionality in the class too, it promotes encapsulation of code.

MVP, Visual Developer - .NET

 

Now you see why evil will always triumph - because good is dumb.

 

My free .NET Windows Forms Controls and Articles

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...