Prev: Snapshot of screen
Next: HTTPS File Uploads
From: Webbiz on 23 Nov 2009 14:36 Hello. An old project of mine draws stock charts on a picturebox called pctChart. On this pctChart, a routine called DrawChart is used to draw OHLC or Candlestick price bars. After the bars are drawn, the chart tools are drawn over them, such as lines, boxes, etc. This is done in RedrawTools. Currently, I can scroll this chart by either double-clicking the chart, holding down the mouse button on the second click, and dragging the mouse to a new location. After the mouse is let up, then the draw is redrawn in the new location. Or, I can press and hold the Left or Right arrow keys and it will scroll the chart (slowly) to the right or left. Problem: With the arrow keys, in order to show the chart actually scrolling, it runs the DrawChart and RedrawTools over and over, one day (bar) at a time. This looks really rickety, and moves so slow. Watching it redraw each time is a flickering hodge-podge. It would be nice if the chart would scroll smoothly and quickly. As for scrolling with the mouse, I'd like it to actually show the bars scrolling, also smoothly and as quick as the mouse is being moved, while the mouse is being moved. Right now, I don't do any of the redraw with the mouse until it has stopped at the new location, because of the flickering issue. There is just all these redraws. Because I have purchased programs that seem to do this without any problem, I believe it should be possible to do the same with my project. Yet, I'm wondering if this is a VB6 problem, and that I'd have to program with C to achieve the above. And yes, I have a decently quick computer and graphics card, so that's not the problem. Any suggestions, tips and otherwise? Thanks. Webbiz
From: Nobody on 23 Nov 2009 14:51 Use the same technique used by games. It's called double buffering. Draw everything on another PictureBox that has AutoRedraw=True, and Visible=False. Once you are done, copy from the off screen PictureBox to the on screen PictureBox. Example copying code: Set pctChartOnScreen.Picture = pctChartOffScreen.Picture pctChartOnScreen.Refresh ' Only use if pctChartOnScreen.AutoRedraw=True
From: Mike Williams on 23 Nov 2009 16:54 "Webbiz" <nospam(a)forme.thanks.com> wrote in message news:lfolg51dqo43v288g7k8v7ahd7fv5f2gce(a)4ax.com... > With the arrow keys, in order to show the chart actually > scrolling and using it runs the DrawChart and RedrawTools > over and over, one day (bar) at a time. If you are using key events then the scroll rate will be limited by the current keyboard repeat rate, but I imagine you are already aware of that and are reading the state of the arrow keys in a way that overcomes that problem? > This looks really rickety, and moves so slow. Are you redrawing the entire PictureBox each time, or are you drawing only the new data and scrolling any unchanged existing data by blitting the unchanged block a little to the left? (although which will be the faster of these two methods depends on the complexity of your drawings). > Watching it redraw each time is a flickering hodge-podge With many kinds of drawings you need to use double buffering in order to eliminate the flicker, as has already been mentioned by "Nobody". By the way, are you using the most appropriate GDI functions for your drawings? For example, are you using PolyLine and Rectangle etc rather than individual LineTo calls? Most GDI drawing functions are very much slower in Vista than they are in XP (because most Vista systems do not use your video card's GDI accelerated hardware, whereas XP systems almost always do) but even in Vista using things like Polyline can be up to two or three times faster than the equivalent bunch of LineTo calls (and of course often very much faster still on the same system running XP). Also, if you are using a system that does use the video card's accelerated 2D hardware (Win98 / XP) you will find that Polyline is very much slower if there is a "clipping hole" in the window that covers even a single pixel of the complete Polyline drawing (a Command Button or other Control or something that VB is displaying on the window whilst its ClipControls property is at its default value of True), because GDI hardware is not usually used by Polyline under such conditions. I think the first thing I would do in your specific case would be to put a high resolution timer on both the DrawChart and RedrawTools functions, to see which of those is taking the most time, on the grounds that it's always best to tackle the biggest bottleneck first before you look at other smaller things. If your system is using your video cards GDI accelerated hardware then it might be wise for test purposes to place a function call at the very end of both of these routines that will cause the routine to wait until the video card hardware has actually finished the drawing that was triggered by your code, otherwise you will get misleading timings (changing the Form's Caption property usually serves to perform the wait). Other than that, it is really hard to think of anything concrete to suggest without being able to actually see and run your code. Mike
From: Larry Serflaten on 23 Nov 2009 18:04 "Webbiz" <nospam(a)forme.thanks.com> wrote <...> > Currently, I can scroll this chart by either double-clicking the > chart, holding down the mouse button on the second click, and dragging > the mouse to a new location. After the mouse is let up, then the draw > is redrawn in the new location. <...> > With the arrow keys, in order to show the chart actually scrolling, it > runs the DrawChart and RedrawTools over and over, one day (bar) at a > time. This looks really rickety, and moves so slow. Watching it redraw > each time is a flickering hodge-podge. It would be nice if the chart > would scroll smoothly and quickly. <...> > Any suggestions, tips and otherwise? As other have said, using a second buffer is going to help. Do remember that your whole application is just so many pixels on a screen. As long as you can draw something that looks like a chart, people will believe its a chart. If you can draw something that looks like a button, people will believe its a button, until shown otherwise. One method to help reduce the flicker would be to draw the whole chart to an invisible picturebox, and then just show what you need to fill the form area. For an example, add a picturebox to a new form and paste in the code below.... As posted it only handles the mouse drag operation, I've left it up to you to handle the others. HTH LFS Option Explicit Private imgLeft As Long Private MX As Single Private Sub Form_Load() Dim X ' Draw chart Picture1.BorderStyle = vbBSNone Picture1.Move 0, 0, 30000, 4000 Picture1.AutoRedraw = True Picture1.BackColor = vbWhite Picture1.Line (90, 90)-(29780, 3920), vbBlack, B For X = 105 To 29800 Step 900 Picture1.PSet (X, 90), vbBlack Picture1.Line -Step(0, 3810), &HCCCCCC Picture1.PSet (X + 30, 1600), vbWhite Picture1.Print CStr(X \ 90 - 1) Next Me.Move 1000, 1000, 8000, 4600 Picture1.Visible = False End Sub Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) MX = X End Sub Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then imgLeft = imgLeft + (X - MX) ' Test boundries If imgLeft > 0 Then imgLeft = 0 If imgLeft < (Me.Width - Picture1.Width) Then imgLeft = (Me.Width - Picture1.Width) MX = X ' Paint chart PaintPicture Picture1.Image, imgLeft, 0 End If End Sub Private Sub Form_Paint() PaintPicture Picture1.Image, imgLeft, 0 End Sub
From: Webbiz on 23 Nov 2009 19:35
On Mon, 23 Nov 2009 21:54:23 -0000, "Mike Williams" <Mike(a)WhiskyAndCoke.com> wrote: >"Webbiz" <nospam(a)forme.thanks.com> wrote in message >news:lfolg51dqo43v288g7k8v7ahd7fv5f2gce(a)4ax.com... > >> With the arrow keys, in order to show the chart actually >> scrolling and using it runs the DrawChart and RedrawTools >> over and over, one day (bar) at a time. > >If you are using key events then the scroll rate will be limited by the >current keyboard repeat rate, but I imagine you are already aware of that >and are reading the state of the arrow keys in a way that overcomes that >problem? Ah...no. I'm not that sophisticated, remember. :-0 > >> This looks really rickety, and moves so slow. > >Are you redrawing the entire PictureBox each time, or are you drawing only >the new data and scrolling any unchanged existing data by blitting the >unchanged block a little to the left? (although which will be the faster of >these two methods depends on the complexity of your drawings). Drawing the whole picturebox each time. >> Watching it redraw each time is a flickering hodge-podge > >With many kinds of drawings you need to use double buffering in order to >eliminate the flicker, as has already been mentioned by "Nobody". That sounds so easy. (Thanks Nobody!). So what I am currently drawing directly to the pctChart, instead draw to a non visible picturebox and THEN copy it over. That's it? >By the way, are you using the most appropriate GDI functions for your >drawings? For example, are you using PolyLine and Rectangle etc rather than >individual LineTo calls? Most GDI drawing functions are very much slower in >Vista than they are in XP (because most Vista systems do not use your video >card's GDI accelerated hardware, whereas XP systems almost always do) but >even in Vista using things like Polyline can be up to two or three times >faster than the equivalent bunch of LineTo calls (and of course often very >much faster still on the same system running XP). Also, if you are using a >system that does use the video card's accelerated 2D hardware (Win98 / XP) >you will find that Polyline is very much slower if there is a "clipping >hole" in the window that covers even a single pixel of the complete Polyline >drawing (a Command Button or other Control or something that VB is >displaying on the window whilst its ClipControls property is at its default >value of True), because GDI hardware is not usually used by Polyline under >such conditions. Mostly, I use the Picturebox.Line method. Just drawing a line from here to there, here to there, here to there. For example, each price bar is simply a vertical line with a small horizontal line off the left side and one on the right side. The chart may show anywhere from 100 to 200 of these vertical lines representing the high/low/open/close of each trading day. Take a look at this video. It will show you what my chart looks like, and also show the redraw stuff. http://www.screencast.com/t/Y2FhMDY2Z I know that it probably doesn't look that bad. But I've seen smoother, faster. The video also shows a couple tools being redrawn as part of RedrawTools. >I think the first thing I would do in your specific case would be to put a >high resolution timer on both the DrawChart and RedrawTools functions, to >see which of those is taking the most time, on the grounds that it's always >best to tackle the biggest bottleneck first before you look at other smaller >things. If your system is using your video cards GDI accelerated hardware >then it might be wise for test purposes to place a function call at the very >end of both of these routines that will cause the routine to wait until the >video card hardware has actually finished the drawing that was triggered by >your code, otherwise you will get misleading timings (changing the Form's >Caption property usually serves to perform the wait). > >Other than that, it is really hard to think of anything concrete to suggest >without being able to actually see and run your code. >Mike > > Thanks. Webbiz |