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
![]() |
0 |
![]() |
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
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote in message news:lfolg51dqo43v288g7k8v7ahd7fv5f2gce@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
![]() |
0 |
![]() |
"Webbiz" <nospam@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
![]() |
0 |
![]() |
On Mon, 23 Nov 2009 21:54:23 -0000, "Mike Williams" <Mike@WhiskyAndCoke.com> wrote: >"Webbiz" <nospam@forme.thanks.com> wrote in message >news:lfolg51dqo43v288g7k8v7ahd7fv5f2gce@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
![]() |
0 |
![]() |
Thanks Larry. :-) This code is very instructional. Best regards, Webbiz On Mon, 23 Nov 2009 17:04:08 -0600, "Larry Serflaten" <serflaten@usinternet.com> wrote: > >"Webbiz" <nospam@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 >
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote in message news:lfolg51dqo43v288g7k8v7ahd7fv5f2gce@4ax.com... > 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 If all you want to do is move the image about when scrolled another option is to put a very big picture box inside a much smaller picture box, plot your stuff on the large one then with scroll bars you can move the whole box but only the part visible through the smaller box would be seen. Dave O.
![]() |
0 |
![]() |
"Dave O." <nobody@nowhere.com> wrote in message news:%232QL0pObKHA.5544@TK2MSFTNGP02.phx.gbl... > If all you want to do is move the image about when scrolled another option > is to put a very big picture box inside a much smaller picture box, plot > your stuff on the large one then with scroll bars you can move the whole > box but only the part visible through the smaller box would be seen. The sample that Larry Serflaten posted did just that, except he used a large PictureBox and the form.
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote > Thanks Larry. :-) > > This code is very instructional. You're welcome. However, typical for one-off replies, there was a line that needs replacement: If imgLeft < (Me.Width - Picture1.Width) Then imgLeft = (Me.Width - Picture1.Width) Because different people have different form borders, that Me.Width should have been Me.ScaleWidth, with the apporpreate adjustments to the boundry checks.... Have fun! LFS
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote in message news:to9mg59copm54b0iiscqtupri01q4khaik@4ax.com... > Drawing the whole picturebox each time. Right. In that case perhaps you might like to consider drawing it just once into an offscreen Autoredraw PictureBox and painting or positioning only the required part into the display as you scroll, as has already been suggested by Dave and Larry. I do seem to vaguely recall you posting something about your stock chart drawing program a long time ago and saying that there was a reason you could not do that when I suggested it at the time, but I can't remember what that reason was now. Was there a specific reason that you could not do that, something to do with the data changing on the fly or something? I can't remember now. If not then it certainly is a good way of doing it, and you will be able to use more than one offscreen PictureBox to predraw a very large amount of data, perhaps about 30 or 40 screen widths of data, before you begin to eat too much into the RAM available for other applications, and much more than that if you use DIBs instead of PictureBoxes or other screen compatible bitmaps, because DIBs will quite happily live in the swapfile. > Mostly, I use the Picturebox.Line method. Just drawing > a line from here to there, here to there, here to there. The PictureBox Line method is about as fast as the alternative API MoveTo / LineTo method (which is understandable of course because that's what it uses under the hood), but the only problem is that (as with all native VB drawing methods) it effectively triggers a Refresh on an Autoredraw PictureBox, which is somehting that you often do not want. But as far as actual drawing speed is concerned it is much the same. One thing to note is that according to the video you posted you are using lines more than one pixel wide. These are drawn slower than single pixel lines of course, but in Vista (which disables the video card's accelerated GDI hardware) the speed is comparable with drawing more than one separate single pixel line (although this was not the case in XP as I recall, which does use the video card's accelerated GDI functions and in which the drawing of single pixel thick lines was blindingly fast). In Vista, also, the speed of the different GDI drawing functions is affected by whether or not the system is currently running at the "disable desktop composition" setting, but generally it is faster to draw horizontal or vertical lines of more than one pixel thickness using the API FillRect function rather than the API LineTo function (or the VB Line method). The amount of extra speed you get from using FillRect is not a lot when Vista is running its standard Aero desktop, and is much more when Vista is running in "disable desktop composition" mode, but in all cases (in Vista) it is faster than LineTo, at least on the systems I've personally tried it on. In XP things were very different of course, but the Win32 GDI is now effectively crippled on almost all Vista machines. How sad :-( > [in respnse to a statement regarding the keyboard repeat > rate] Ah...no. I'm not that sophisticated, remember. :-0 You can overcome that by creating a keymap in memory (a simple array) and using a Key event to set the curreent state of the keys as they are pressed and released by the user. In that way your code can examine the key map at any time you wish and you will know whether any specific key is currently down or up. So, instead of using an arrow key event to scroll your image you can use a timer or a code loop to repeatedly react to the current state of the required key. Mike
![]() |
0 |
![]() |
On 23/11/2009 19:36, Webbiz wrote: > rolling 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 Firstly, use double buffering so you don't draw bits at a time. You draw the data to an off screen buffer, then draw when needed. Even with this, I was getting some flickering as VB insisted on redrawing some parts of the screen in WM_PAINT before firing the Paint event, despite me eating the WM_ERASEBACKGROUND message. I ended up handling WM_PAINT myself then passing direct to the paint event: Case WM_PAINT 'We handle WM_PAINT ourselves as VB6 seems to explicitly draw the background in its handler hDC = BeginPaint(hWnd, PaintInfo) GraphFrame_Paint EndPaint hWnd, PaintInfo 'We've handled it so VB doesn't do anything further SubClassed_WindowProc = 0 Handled = True -- Dee Earley (dee.earley@icode.co.uk) i-Catcher Development Team iCode Systems
![]() |
0 |
![]() |
"Mike Williams" <Mike@WhiskyAndCoke.com> wrote in message news:%23w5aJMQbKHA.2188@TK2MSFTNGP04.phx.gbl... .. . . the other thing I wanted to mention as far as the drawing side of your code is concerned (except that it went out of my mind as I began to get more and more angry thinking about how GDI hardware acceleration has been destroyed on almost all Vista machines!) is the GDI PolyLine function, which even in Vista can be faster than the equivalent bunch of Line (or LineTo) methods. PolyLine draws a set of continuously connected lines, but if that does not suit your purposes then you can instead use the PolyPolyLine function, which can draw any number of separate groups of lines at different places. The only problem with that, judging by the video you posted, is you are using a number of different line colours, and PolyLine (or PolyPolyLine) draws all lines the same specified colour. You could get around that though by using one call to PolyPolyLine to first draw all black lines, then another call to PolyPolyLine to draw all red lines, etc, etc. This might add a bit of complexity to your drawing logic (setting up the different POINTAPI arrays) but it might still be worth it. You'd need to try it in practice on your own specific drawings though, to see whether it ends up with a speed increase worth bothering about. Also, you still need to look at the offscreen buffer that has been suggested by a number of people, but even when you have done that it is still best to get the most speed you can out of whatever drawing operations you perform, regardless of when you actually perform them. Mike
![]() |
0 |
![]() |
On Tue, 24 Nov 2009 13:44:22 -0000, "Mike Williams" <Mike@WhiskyAndCoke.com> wrote: >"Mike Williams" <Mike@WhiskyAndCoke.com> wrote in message >news:%23w5aJMQbKHA.2188@TK2MSFTNGP04.phx.gbl... > >. . . the other thing I wanted to mention as far as the drawing side of your >code is concerned (except that it went out of my mind as I began to get more >and more angry thinking about how GDI hardware acceleration has been >destroyed on almost all Vista machines!) is the GDI PolyLine function, which >even in Vista can be faster than the equivalent bunch of Line (or LineTo) >methods. PolyLine draws a set of continuously connected lines, but if that >does not suit your purposes then you can instead use the PolyPolyLine >function, which can draw any number of separate groups of lines at different >places. The only problem with that, judging by the video you posted, is you >are using a number of different line colours, and PolyLine (or PolyPolyLine) >draws all lines the same specified colour. You could get around that though >by using one call to PolyPolyLine to first draw all black lines, then >another call to PolyPolyLine to draw all red lines, etc, etc. This might add >a bit of complexity to your drawing logic (setting up the different POINTAPI >arrays) but it might still be worth it. You'd need to try it in practice on >your own specific drawings though, to see whether it ends up with a speed >increase worth bothering about. Also, you still need to look at the >offscreen buffer that has been suggested by a number of people, but even >when you have done that it is still best to get the most speed you can out >of whatever drawing operations you perform, regardless of when you actually >perform them. > >Mike > > Now I remember the headache I had trying to assimilate all that high tech talk in my head. Ooh. I'm going to try the two pic box idea first, just to see what happens. So if I undertand correctly, I should replace the picturebox being referenced by my current drawing code to one that is not visible and has Autoredraw = true, correct? And then, when the drawing is completed, have it sent to the picture box I'm currently using. Is that right? Webbiz
![]() |
0 |
![]() |
On Tue, 24 Nov 2009 09:42:33 -0000, "Dave O." <nobody@nowhere.com> wrote: > >"Webbiz" <nospam@forme.thanks.com> wrote in message >news:lfolg51dqo43v288g7k8v7ahd7fv5f2gce@4ax.com... >> 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 > >If all you want to do is move the image about when scrolled another option >is to put a very big picture box inside a much smaller picture box, plot >your stuff on the large one then with scroll bars you can move the whole box >but only the part visible through the smaller box would be seen. > >Dave O. > Unfortunately, that would be one very large picturebox. The chart may show only 120 price bars, but if all the price bars are drawn ahead of time on that larger picturebox, you'd be talking a minimum of 3000 bars. Thanks. Webbiz
![]() |
0 |
![]() |
On Tue, 24 Nov 2009 13:02:22 +0000, Dee Earley <dee.earley@icode.co.uk> wrote: >On 23/11/2009 19:36, Webbiz wrote: >> rolling 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 > >Firstly, use double buffering so you don't draw bits at a time. >You draw the data to an off screen buffer, then draw when needed. > >Even with this, I was getting some flickering as VB insisted on >redrawing some parts of the screen in WM_PAINT before firing the Paint >event, despite me eating the WM_ERASEBACKGROUND message. > >I ended up handling WM_PAINT myself then passing direct to the paint event: > Case WM_PAINT > 'We handle WM_PAINT ourselves as VB6 seems to explicitly draw the >background in its handler > hDC = BeginPaint(hWnd, PaintInfo) > GraphFrame_Paint > EndPaint hWnd, PaintInfo > 'We've handled it so VB doesn't do anything further > SubClassed_WindowProc = 0 > Handled = True Forgive my inexperience, but exactly where did you place this Select...Case code? Thx. Webbiz
![]() |
0 |
![]() |
On 25/11/2009 04:30, Webbiz wrote: > On Tue, 24 Nov 2009 13:02:22 +0000, Dee Earley > <dee.earley@icode.co.uk> wrote: >> Even with this, I was getting some flickering as VB insisted on >> redrawing some parts of the screen in WM_PAINT before firing the Paint >> event, despite me eating the WM_ERASEBACKGROUND message. >> >> I ended up handling WM_PAINT myself then passing direct to the paint event: >> Case WM_PAINT >> 'We handle WM_PAINT ourselves as VB6 seems to explicitly draw the >> background in its handler >> hDC = BeginPaint(hWnd, PaintInfo) >> GraphFrame_Paint >> EndPaint hWnd, PaintInfo >> 'We've handled it so VB doesn't do anything further >> SubClassed_WindowProc = 0 >> Handled = True > > > Forgive my inexperience, but exactly where did you place this > Select...Case code? It's in a subclass handler for the picturebox. Exactly where/how you use it depends on the sub class handler you're using. -- Dee Earley (dee.earley@icode.co.uk) i-Catcher Development Team iCode Systems
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote in message news:q97pg5h5kfp2q0s1168mbabi9os593ng55@4ax.com... > So if I undertand correctly, I should replace the picturebox > being referenced by my current drawing code to one that is > not visible and has Autoredraw = true, correct? > And then, when the drawing is completed, have it sent to > the picture box I'm currently using. > Is that right? You could do it that way if you wish to, but you don't actually need to use a separate PictureBox. Using just one PictureBox will be fine (subject to certain limitations). The important thing is that you create your drawing in a non visible memory bitmap and then transfer the bitmap to the display only when the drawing is fully complete. This is possible using just a single Autoredraw PictureBox because all drawings using either native VB drawing methods or API drawing methods are drawn into the hidden memory bitmap of an Autoredraw PictureBox. If you're using only API drawing methods on the PictureBox then the finished drawing will never be sent from the hidden memory bitmap into the "screen presence" of the PictureBox until you do something to specifically cause it to do so (using Picture1.Refresh is the standard way of doing this, and so you should use Picture1.Refresh as soon as your API drawing code has fully finished the drawing). However, if your drawing code uses any native VB drawing methods on the Autoredraw PictureBox (Picture1.Line etc) then each of those methods will effectively tell the PictureBox to Refresh itself (tell it to transfer the hidden memory bitmap into its screen presence) as soon as it gets the chance to do so. As it happens, the "Refresh when you get the chance" message simply ends up sitting in a queue whilst your code is actually running, and so the message will not be actioned until your drawing code finishes, at which point the completed drawing will be sent to the "screen presence" of the PictureBox, giving exactly the same results as the "API only drawing" outlines above, but without you needing to explicity issue a Picture1.Refresh at the end of your drawing code. This is fine, but there are things that can upset it. For example, if anywhere in your drawing code there is a DoEvents statement then the "queued PictureBox Refresh" message will be actioned by the DoEvents, which is not what you want because your drawing code has not yet finished the drawing. By the way, in Vista drawing into an Autoredraw PictureBox (or into any other similar memory DC) is generally faster than the same drawing into a non Autoredraw PictureBox (directly to the display), so you should see an increase in speed even though it takes a little time at the end for the Refresh to occur. Also, in Vista using the FillRect API to draw vertical or horizontal lines of more than one pixel thickness is faster than either the API LineTo or the VB Line method (using either one two-pixel thick line or more than one single pixel thick lines) and when drawing into an Autoredraw PictureBox the speed advantage of FillRect is even more pronounced. To give you an idea of the difference, here are the results of some tests I've just carried out which draws a lot of long vertical and horizontal two pixel thick lines (although I've only tried it on this one specific Vista machine at the moment): NON Autoredraw PictureBox: VB Line / API LineTo method: 7.6 to 9.6 milliseconds (Aero / Not Aero) API FillRect method: 5.5 to 3.3 milliseconds (Aeor / Not Aero) Autoredraw PictureBox: VB Line / API LineTo method: 5.7 to 5.7 milliseconds (Aero / Not Aero) API FillRect method: 1.6 to 1.5 milliseconds (Aeor / Not Aero) As you can see, FillRect into an Autoredraw PictureBox (on this specific Vista machine) is about 5 times faster than the VB Line / API LineTo method into a non Autoredraw PictureBox. Mike
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote in message news:vkcpg5h1pp45tc0daljhgtsuqfuec7ti36@4ax.com... >> On Tue, 24 Nov 2009 13:02:22 +0000, Dee Earley >> <dee.earley@icode.co.uk> wrote: >> Even with this, I was getting some flickering as VB insisted on >> redrawing some parts of the screen in WM_PAINT before >> firing the Paint event . . . I ended up handling WM_PAINT >> myself then passing direct to the paint event: >> Case WM_PAINT >> hDC = BeginPaint(hWnd, PaintInfo) >> . . . etc > > Forgive my inexperience, but exactly where did you > place this Select...Case code? Don't worry too much about that, Webbiz. I think Dee was deliberately being a little bit obtuse when she told you to just place it in your subclass handler . . . but then that's what you can expect of Londoners ;-) (Sorry, Dee, just a little Scouse joke!). I think Dee was referring to problems she needed to solve in certain circumstances concerning drawings in the PictureBox (or Form) Paint event, which fires /after/ VB has itself dealt with the system WM_PAINT event, and /after/ VB has effectively cleared out the "dirty rectangle" information, which can then not effectively be read in the VB Paint event, even if you use the GetUpdateRect API. This can result in any VB Paint event drawing causing some flicker if for some reason you perform a Cls or clear an area as part of a transparent blit or whatever during your drawing, because your drawing is not clipped to the "dirty rectangle" and fills parts of the PictureBox (or Form) other than the parts that actually required painting (the usually very small "dirty rectangle" for example as a user drags a Form off the edges of the display and back again). Subclassing the WM_PAINT (which effectively means "getting at it" at a fairly low level and before the VB Paint event fires, and whilst the "dirty rectangle" information is still available and valid, enables you to do things that you could not otherwise do. This should not be a problem in your own code though, and should not be required, because I assume you will be using an Autoredraw PictureBox, and VB Paint events do not actually fire in a PictureBox whilst Autoredraw is True (although the lower level WM_PAINT events still fires of course, and is handled by VB itself). In an Autoredraw PictureBox VB very effectively handles the redrawing of the "dirty rectangle" for you in the WM_PAINT event as the user moves the Form (PictureBox) on and off the edges of the display, and in other circumstances. VB is quite good at this, painting /only/ the required dirty rectangle from the contents of the hidden Autoredraw memory bitmap (the Autoredraw bitmap that I mentioned in my previous response), so as far as maintaining the contents of the PictureBox as the user drags the Form on and off the edges of the display (and other things) you can effectively forget all about it when using an Autoredraw PictureBox and simply let the VB Autoredraw mechanism get on with the job for you. The only thing you need to concern yourself with is the initial drawing of the new PictureBox contents each time the user uses the scroll bar (or arrow keys or whatever) to require a different part of your stock and share data to be drawn, which is something I covered in my previous response,. Mike
![]() |
0 |
![]() |
On 25/11/2009 22:27, Mike Williams wrote: > "Webbiz" <nospam@forme.thanks.com> wrote in message > news:vkcpg5h1pp45tc0daljhgtsuqfuec7ti36@4ax.com... >>> On Tue, 24 Nov 2009 13:02:22 +0000, Dee Earley >>> <dee.earley@icode.co.uk> wrote: >>> Even with this, I was getting some flickering as VB insisted on >>> redrawing some parts of the screen in WM_PAINT before >>> firing the Paint event . . . I ended up handling WM_PAINT >>> myself then passing direct to the paint event: >>> Case WM_PAINT >>> hDC = BeginPaint(hWnd, PaintInfo) >>> . . . etc >> >> Forgive my inexperience, but exactly where did you >> place this Select...Case code? > > Don't worry too much about that, Webbiz. I think Dee was deliberately > being a little bit obtuse when she told you to just place it in your > subclass handler . . . but then that's what you can expect of Londoners > ;-) (Sorry, Dee, just a little Scouse joke!). Londoner!! I'm from further south than that :) > I think Dee was referring to problems she needed to solve in certain > circumstances concerning drawings in the PictureBox (or Form) Paint > event, which fires /after/ VB has itself dealt with the system WM_PAINT > event, and /after/ VB has effectively cleared out the "dirty rectangle" > information, which can then not effectively be read in the VB Paint > event, even if you use the GetUpdateRect API. I seemed to get this even when redrawing quickly when I tried to draw things the "Windows" way. I was invalidating the rect when I knew there was an update, then left it up to windows to tell me when it needed to redraw (the windows weren't always visible) As for using AutoRedraw, I'd forgotton about it as I stopped using it long ago as a lot of the data we rendered was "live" or at least frequently updating and wanted to improve performance. -- Dee Earley (dee.earley@icode.co.uk) i-Catcher Development Team iCode Systems
![]() |
0 |
![]() |
On Wed, 25 Nov 2009 11:41:50 -0000, "Mike Williams" <Mike@WhiskyAndCoke.com> wrote: >"Webbiz" <nospam@forme.thanks.com> wrote in message >news:q97pg5h5kfp2q0s1168mbabi9os593ng55@4ax.com... > >> So if I undertand correctly, I should replace the picturebox >> being referenced by my current drawing code to one that is >> not visible and has Autoredraw = true, correct? >> And then, when the drawing is completed, have it sent to >> the picture box I'm currently using. >> Is that right? > >You could do it that way if you wish to, but you don't actually need to use >a separate PictureBox. Using just one PictureBox will be fine (subject to >certain limitations). The important thing is that you create your drawing in >a non visible memory bitmap and then transfer the bitmap to the display only >when the drawing is fully complete. > >This is possible using just a single Autoredraw PictureBox because all >drawings using either native VB drawing methods or API drawing methods are >drawn into the hidden memory bitmap of an Autoredraw PictureBox. If you're >using only API drawing methods on the PictureBox then the finished drawing >will never be sent from the hidden memory bitmap into the "screen presence" >of the PictureBox until you do something to specifically cause it to do so >(using Picture1.Refresh is the standard way of doing this, and so you should >use Picture1.Refresh as soon as your API drawing code has fully finished the >drawing). > >However, if your drawing code uses any native VB drawing methods on the >Autoredraw PictureBox (Picture1.Line etc) then each of those methods will >effectively tell the PictureBox to Refresh itself (tell it to transfer the >hidden memory bitmap into its screen presence) as soon as it gets the chance >to do so. As it happens, the "Refresh when you get the chance" message >simply ends up sitting in a queue whilst your code is actually running, and >so the message will not be actioned until your drawing code finishes, at >which point the completed drawing will be sent to the "screen presence" of >the PictureBox, giving exactly the same results as the "API only drawing" >outlines above, but without you needing to explicity issue a >Picture1.Refresh at the end of your drawing code. This is fine, but there >are things that can upset it. For example, if anywhere in your drawing code >there is a DoEvents statement then the "queued PictureBox Refresh" message >will be actioned by the DoEvents, which is not what you want because your >drawing code has not yet finished the drawing. > >By the way, in Vista drawing into an Autoredraw PictureBox (or into any >other similar memory DC) is generally faster than the same drawing into a >non Autoredraw PictureBox (directly to the display), so you should see an >increase in speed even though it takes a little time at the end for the >Refresh to occur. Also, in Vista using the FillRect API to draw vertical or >horizontal lines of more than one pixel thickness is faster than either the >API LineTo or the VB Line method (using either one two-pixel thick line or >more than one single pixel thick lines) and when drawing into an Autoredraw >PictureBox the speed advantage of FillRect is even more pronounced. To give >you an idea of the difference, here are the results of some tests I've just >carried out which draws a lot of long vertical and horizontal two pixel >thick lines (although I've only tried it on this one specific Vista machine >at the moment): > >NON Autoredraw PictureBox: >VB Line / API LineTo method: 7.6 to 9.6 milliseconds (Aero / Not Aero) >API FillRect method: 5.5 to 3.3 milliseconds (Aeor / Not >Aero) > >Autoredraw PictureBox: >VB Line / API LineTo method: 5.7 to 5.7 milliseconds (Aero / Not Aero) >API FillRect method: 1.6 to 1.5 milliseconds (Aeor / Not >Aero) > >As you can see, FillRect into an Autoredraw PictureBox (on this specific >Vista machine) is about 5 times faster than the VB Line / API LineTo method >into a non Autoredraw PictureBox. > >Mike > > Hello Mike. Here is a section of my 'current' code that draws a bar chart using the .Line method. ========== For i = gFirstBarRecNum To gLastBarRecNum If i > 1 Then If MarketData(i - 1).TTCLow <> 0 Then sngLastLow = MarketData(i - 1).TTCLow sngLastHigh = MarketData(i - 1).TTCHigh End If End If If MarketData(i).TTCHigh <> 0 And MarketData(i).TTCLow <> 0 Then dblLowPoint = frmChart.pctChart.ScaleHeight - ((MarketData(i).TTCLow - gMinValue) * sngInterval) dblHighPoint = frmChart.pctChart.ScaleHeight - ((MarketData(i).TTCHigh - gMinValue) * sngInterval) dblOpenPoint = frmChart.pctChart.ScaleHeight - ((MarketData(i).TTCOpen - gMinValue) * sngInterval) dblClosePoint = frmChart.pctChart.ScaleHeight - ((MarketData(i).TTCClose - gMinValue) * sngInterval) If dblHighPoint < -300000 Or dblLowPoint > 300000 Then: Exit Sub 'we now draw the bar lines using the info we just calculated for the bar 'each bar is separated horizontally by gHSpace in screen coordinates 'last two lines draw the Open and Close horizontal lines with different colors If giChartType = ColorBars And i > 1 Then If MarketData(i).TTCHigh > sngLastHigh And MarketData(i).TTCLow >= sngLastLow Then lngColor = Green ElseIf MarketData(i).TTCLow < sngLastLow And MarketData(i).TTCHigh <= sngLastHigh Then lngColor = Red ElseIf MarketData(i).TTCHigh > sngLastHigh And MarketData(i).TTCLow < sngLastLow Then lngColor = Blue Else lngColor = BLACK 'inside bar End If Else lngColor = BLACK End If 'Draw the main bar frmChart.pctChart.Line ((i - (gFirstBarRecNum)) * gHSpace, dblLowPoint)-((i - (gFirstBarRecNum)) * gHSpace, dblHighPoint), lngColor frmChart.pctChart.Line ((i - (gFirstBarRecNum)) * gHSpace, dblOpenPoint)-(((i - (gFirstBarRecNum)) * gHSpace) - Int(gHSpace / 2), dblOpenPoint), lngColor frmChart.pctChart.Line ((i - (gFirstBarRecNum)) * gHSpace, dblClosePoint)-(((i - (gFirstBarRecNum)) * gHSpace) + Int(gHSpace / 2), dblClosePoint), lngColor End If Next i ============= When you discussed the thinkness of the line being more than 1 pixel, I suppose you are referring to when my app sets the DrawWidth > 1, right? Let's take one of these line draws as an example. 'Draw the main vertical bar frmChart.pctChart.Line ((i - (gFirstBarRecNum)) * gHSpace, dblLowPoint)-((i - (gFirstBarRecNum)) * gHSpace, dblHighPoint), lngColor Break it down to... X1 = (i - (gFirstBarRecNum)) * gHSpace Y1 = dblLowPoint X2 = ((i - (gFirstBarRecNum)) * gHSpace) - Int(gHSpace / 2) Y2 = dblHighPoint frmChart.pctChartLine (X1, Y1) - (X2, Y2) If I were to replace the above line with the FillRect API code, what would be the approach? This ... Dim r as RECT Dim retval as Long Dim brush as Long ' Set the coordinates of the bar/rectangle retval = SetRect(r, X1, Y1, X2, Y2) brush = CreateSolidBrush(lngColor) retval = FillRect(frmChart.pctChart.hDC, r, brush) I would assume that the 'brush' is set once if all the bars will have the same color. Then for every .Line code, replace it with two lines, the SetRect and FillRect lines. Does that fit what you are suggesting? Thanks. Webbiz
![]() |
0 |
![]() |
On Wed, 25 Nov 2009 10:44:35 +0000, Dee Earley <dee.earley@icode.co.uk> wrote: >On 25/11/2009 04:30, Webbiz wrote: >> On Tue, 24 Nov 2009 13:02:22 +0000, Dee Earley >> <dee.earley@icode.co.uk> wrote: >>> Even with this, I was getting some flickering as VB insisted on >>> redrawing some parts of the screen in WM_PAINT before firing the Paint >>> event, despite me eating the WM_ERASEBACKGROUND message. >>> >>> I ended up handling WM_PAINT myself then passing direct to the paint event: >>> Case WM_PAINT >>> 'We handle WM_PAINT ourselves as VB6 seems to explicitly draw the >>> background in its handler >>> hDC = BeginPaint(hWnd, PaintInfo) >>> GraphFrame_Paint >>> EndPaint hWnd, PaintInfo >>> 'We've handled it so VB doesn't do anything further >>> SubClassed_WindowProc = 0 >>> Handled = True >> >> >> Forgive my inexperience, but exactly where did you place this >> Select...Case code? > >It's in a subclass handler for the picturebox. >Exactly where/how you use it depends on the sub class handler you're using. I'm sorry, but that went over my head. You should see the look on my face...dumbfounded. Kind of a 'huh?' look, if you know what I mean. Subclass handler? Guess I'll have to add that to my list of homework for later. Thanks. :-)
![]() |
0 |
![]() |
On Wed, 25 Nov 2009 22:27:31 -0000, "Mike Williams" <Mike@WhiskyAndCoke.com> wrote: >"Webbiz" <nospam@forme.thanks.com> wrote in message >news:vkcpg5h1pp45tc0daljhgtsuqfuec7ti36@4ax.com... >>> On Tue, 24 Nov 2009 13:02:22 +0000, Dee Earley >>> <dee.earley@icode.co.uk> wrote: >>> Even with this, I was getting some flickering as VB insisted on >>> redrawing some parts of the screen in WM_PAINT before >>> firing the Paint event . . . I ended up handling WM_PAINT >>> myself then passing direct to the paint event: >>> Case WM_PAINT >>> hDC = BeginPaint(hWnd, PaintInfo) >>> . . . etc >> >> Forgive my inexperience, but exactly where did you >> place this Select...Case code? > >Don't worry too much about that, Webbiz. I think Dee was deliberately being >a little bit obtuse when she told you to just place it in your subclass >handler . . . but then that's what you can expect of Londoners ;-) (Sorry, >Dee, just a little Scouse joke!). > >I think Dee was referring to problems she needed to solve in certain >circumstances concerning drawings in the PictureBox (or Form) Paint event, >which fires /after/ VB has itself dealt with the system WM_PAINT event, and >/after/ VB has effectively cleared out the "dirty rectangle" information, >which can then not effectively be read in the VB Paint event, even if you >use the GetUpdateRect API. This can result in any VB Paint event drawing >causing some flicker if for some reason you perform a Cls or clear an area >as part of a transparent blit or whatever during your drawing, because your >drawing is not clipped to the "dirty rectangle" and fills parts of the >PictureBox (or Form) other than the parts that actually required painting >(the usually very small "dirty rectangle" for example as a user drags a Form >off the edges of the display and back again). Subclassing the WM_PAINT >(which effectively means "getting at it" at a fairly low level and before >the VB Paint event fires, and whilst the "dirty rectangle" information is >still available and valid, enables you to do things that you could not >otherwise do. > >This should not be a problem in your own code though, and should not be >required, because I assume you will be using an Autoredraw PictureBox, and >VB Paint events do not actually fire in a PictureBox whilst Autoredraw is >True (although the lower level WM_PAINT events still fires of course, and is >handled by VB itself). In an Autoredraw PictureBox VB very effectively >handles the redrawing of the "dirty rectangle" for you in the WM_PAINT event >as the user moves the Form (PictureBox) on and off the edges of the display, >and in other circumstances. VB is quite good at this, painting /only/ the >required dirty rectangle from the contents of the hidden Autoredraw memory >bitmap (the Autoredraw bitmap that I mentioned in my previous response), so >as far as maintaining the contents of the PictureBox as the user drags the >Form on and off the edges of the display (and other things) you can >effectively forget all about it when using an Autoredraw PictureBox and >simply let the VB Autoredraw mechanism get on with the job for you. > >The only thing you need to concern yourself with is the initial drawing of >the new PictureBox contents each time the user uses the scroll bar (or arrow >keys or whatever) to require a different part of your stock and share data >to be drawn, which is something I covered in my previous response,. > >Mike > > Up to this point, let me see if I get what has been suggested. 1. Since I am using an AutoRedraw picturebox (frmChart.pctChart), there is no need for me to do the 'double-buffer' technique because the picturebox will already be doing this when AutoRedraw = True. 2. For matters of performance, replace my .Line code (VB) in favor of the FillRect code (API). Just so I'm clear on this. Thank you Mike. Webbiz
![]() |
0 |
![]() |
"Dee Earley" <dee.earley@icode.co.uk> wrote in message news:OFAfRpnbKHA.4780@TK2MSFTNGP04.phx.gbl... > As for using AutoRedraw, I'd forgotton about it as I stopped > using it long ago as a lot of the data we rendered was "live" or > at least frequently updating and wanted to improve performance. Perhaps you might like to look at that again. In Vista, at least on the systems I've tested it on, drawing into an Autoredraw PictureBox is on average between 50 and 75 per cent faster than drawing into a non Autoredraw PictureBox, which can often more than compensate for the time taken to Refresh it to the display, and which of course is "extra speed for nothing" if you need to perform double buffering anyway. Mike
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote in message news:rjjtg5ps8bd3mqo743np3pt5gb54f7c7fi@4ax.com... > Up to this point, let me see if I get what has been suggested. > > 1. Since I am using an AutoRedraw picturebox (frmChart.pctChart) > there is no need for me to do the 'double-buffer' technique because > the picturebox will already be doing this when AutoRedraw = True. Yep. That's about it. > 2. For matters of performance, replace my .Line code (VB) in > favor of the FillRect code (API). Yes, if you're drawing vertical or horizontal lines more than one pixel wide (which you appear to be) and if you want your code to run as quickly as possible in Vista. I haven't tested the comparative speed of Line and FillRect on XP machines when drawing vertical and horizontal lines of more than one pixel thickness (and I don't currently have an XP machine to perform any tests on) but I seem to vaguely recall lines of more than one pixel thickness not being hardware accelerated even on XP machines, so I imagine using FillRect instead (which may or may not be accelerated on XP, depending on the hardware) will be okay on those machines as well. If you have an XP machine then perhaps you might like to perform some speed tests yourself. Mike
![]() |
0 |
![]() |
"Mike Williams" <Mike@WhiskyAndCoke.com> wrote > > 1. Since I am using an AutoRedraw picturebox (frmChart.pctChart) > > there is no need for me to do the 'double-buffer' technique because > > the picturebox will already be doing this when AutoRedraw = True. > > Yep. That's about it. I would raise an objection there. The difference between drawing the chart once (to an off screen buffer) and painting in place compared to drawing the chart in every Resize event is going to increase as the drawing work load increases. For simple (say less than 50 lines) images, the difference may be neglegible, but for several hundred lines, the difference will be signifcantly more noticable. If you're only talking about drawing the visible portion of the chart on each Resize (or Scroll) event, then I would agree, there is no gain in using a second buffer if VB already does it for you. But I would suggest that drawing the chart once and painting to the form as needed will be more responsive to user input.... LFS
![]() |
0 |
![]() |
"Webbiz" <nospam@forme.thanks.com> wrote in message news:2rhtg5t0qaq95h56u3f4t1p1ke331g7163@4ax.com... > When you discussed the thinkness of the line being more > than 1 pixel, I suppose you are referring to when my app > sets the DrawWidth > 1, right? Yes. DrawWidth sets the thickness of the line in pixels, regardless of the VB ScaleMode you might be using. > Let's take one of these line draws as an example. > 'Draw the main vertical bar > frmChart.pctChart.Line ((i - (gFirstBarRecNum)) * gHSpace, > dblLowPoint)-((i - (gFirstBarRecNum)) * gHSpace, dblHighPoint), > lngColor > Break it down to... > X1 = (i - (gFirstBarRecNum)) * gHSpace > Y1 = dblLowPoint > X2 = ((i - (gFirstBarRecNum)) * gHSpace) - Int(gHSpace / 2) > Y2 = dblHighPoint > frmChart.pctChartLine (X1, Y1) - (X2, Y2) It looks as though you have broken that down wrongly (which is probably just a typo) because the former appears to draw a vertical line (your main bar) whereas the latter appears to draw a small horizontal line (either your opening or closing price marker), so they are not equivalent, but I think I can see what you mean . . . > . . . frmChart.pctChartLine (X1, Y1) - (X2, Y2) > If I were to replace the above line with the FillRect > API code, what would be the approach? This ... > Dim r as RECT, retval as Long, brush as Long > ' Set the coordinates of the bar/rectangle > retval = SetRect(r, X1, Y1, X2, Y2) > brush = CreateSolidBrush(lngColor) > retval = FillRect(frmChart.pctChart.hDC, r, brush) Not quite, because the Line coordinates represent the two ends of a line whereas the FillRect coordinates represent the coordinates of the top left corner and the bottom right corner of a rectangle. As far as the FillRect coordinates are concerned (as they relate to the coordinates you would use for the Line method) it depends on the thickness of the line and on its orientation (vertical or horizontal). It also depends on the pctChart.ScaleMode you are using, because the VB Line method uses ScaleMode units for the X1, Y1, etc coordinates whereas the FillRect function (as with all other GDI drawing functions) defaults to using Pixels. So, if you're not using pixels as your ScaleMode then you would need to perform the appropriate conversion (or alternatively you can force the GDI functions to use something other than pixels, but that's another story and is best avoided for now). On the assumption that your pctChart.ScaleMode is vbPixels (if not then there will be a little more math) then, using your own VB Line method example, here are the equivalent FillRect methods ("wide" is a Long variable containing the desired line thickness in pixels) . . . frmChart.pctChartLine.DrawWidth = wide frmChart.pctChartLine (X1, Y1) - (X2, Y2) .. . . the equivalent for a vertical line would be SetRect r, X1 - wide \ 2, Y1, X2 + wide - wide \ 2, Y2 + 1 FillRect frmChart.pctChart.hdc, r, brush1 .. . . and for a horizontal line it would be: SetRect r, X1, Y1 - wide \ 2, X2 + 1, Y2 + wide - wide \ 2 FillRect frmChart.pctChart.hdc, r, brush1 You also need to remember that the VB Line method draws rounded ends on lines thicker than one pixel (or at least it attempts to do so, with the degree of success depending on the thickness of the line). These rounded ends are generally added to each end of what would otherwise be a flat edged line, thereby making it slightly longer than your coordinates when you are drawing fairly thick lines. The FillRect function will of course not do that, and will produce a perfectly squared off line of exactly the size and thickness you require. Personally I think that for your own purposes you are better off without those rounded ends anyway, but that's a personal choice of course. > I would assume that the 'brush' is set once if all the bars will > have the same color. Then for every .Line code, replace it > with two lines, the SetRect and FillRect lines. Yes. You need create only one brush and you can use it to draw as many "lines" (FillRects) as you wish. When you have finally finished with the brush (and certainly before your program ends) you must delete it (using the DeleteObject function), otherwise you will have a memory and resource leak. Since you will be using the brush over and over again for as long as your program is running I would suggest that you declare it as Private in your frmChart declarations section (Private BrushBlack as Long, for example) and create it (CreateSolidBrush) in your frmChart Load event and delete it (DeleteObject) in your frmChart Unload event. In that way you will be able to use it in all blocks of code in that Form. You can of course create as many different colour brushes as you wish, in exactly the same way, so for example you could have BrushBlack, BrushRed, BrushGreen, BrushBlue etc, all declared as Private in the declarations section of frmChart and all created in the Load event and deleted in the Unload event. There were a number of points raised in your post and I'm not sure whether I have covered them all here, and of course I may have forgotten to mention some things that I had intended to mention, but I think that about covers it. Mike
![]() |
0 |
![]() |
"Larry Serflaten" <serflaten@usinternet.com> wrote in message news:OcGvpPvbKHA.5976@TK2MSFTNGP05.phx.gbl... > I would raise an objection there. The difference between drawing > the chart once (to an off screen buffer) and painting in place > compared to drawing the chart in every Resize event . . . > . . . If you're only talking about drawing the visible portion of the > chart on each Resize (or Scroll) event, then I would agree, there > is no gain in using a second buffer if VB already does it for you. > [Autoredraw] But I would suggest that drawing the chart once > and painting to the form as needed will be more responsive to > user input.... Yes it would. I agree, and in fact that is the way I would prefer to do it myself, perhaps using code very similar to the code you posted yourself which uses a large pre-drawn offscreen bitmap and which moves the required portion of it into view in response to user scrolling. That method (and other similar methods) is very quick as far as scrolling is concerned. In fact Webbiz took your own code on board and thanked you for it . . . .. . . But Webbiz has said that he has an extremely large chart, apparently about the height of the screen but as wide as at least 25 screens and possibly many more, which if you drew it in its entirety into a buffer using the code you posted yourself could be more than 40,000 pixels wide and which would need a bitmap of about 160 MB on my own machine, or about 120 MB if you used a DIB and accepted the slightly slower copying to the display that a DIB would give you. And Webbiz has said that is the minimum size he is talking about. It could be much more than that from what he has said. That is still "doable" of course using youur own suggested method (as long as Webbiz does not want very much larger charts than he has suggested as his minimum), and you might even be able to modify it so that it draws just half a dozen screenfulls as a buffer and kind of "plans ahead" replacing parts of it with other sections on the fly that it thinks might be needed next (similar to a typical picture viewer), although that might cause you to lose much of the responsiveness that the basic method you have already outlined would otherwise give you. I do like the idea of a full and complete chart already pre-drawn into a backbuffer as you have suggested, but personally in view of the very large size of Webbiz's chart and in view of other of his requirements I think my own current suggestion of drawing only the currently visible part of the graph in response to user input is the way I would advise Webbiz to go about it in this specific case. The more input and alternative suggestions that Webbiz has from yourself and from others can only be for the good of course, and I welcome all your comments about my own suggested method, both negative and positive, but at the moment considering Webbiz's requirements I am still leaning towards my own suggestion of drawing only the currently required portion of the chart, and drawing the other required portions on the fly as the user scrolls. In this specific case there is also the problem of the requirement to respond to the user's request to magnify portions of the chart, which as I vaguely recall (although I could be wrong on that point) from some very much earlier postings by Webbiz (in different threads quite some time ago) required not just a simple magnification of an existing ready drawn portion of the chart but needed to draw various elements so that they gained in visible data resolution when they were magnified, a bit like a metafile drawing would . . . .. . . now there's a thought :-) Mike
![]() |
0 |
![]() |
"Mike Williams" <Mike@WhiskyAndCoke.com> wrote in message news:%23k9GN9ybKHA.4024@TK2MSFTNGP06.phx.gbl... > ... so that they gained in visible data resolution when > they were magnified, a bit like a metafile drawing > would . . . . . now there's a thought :-) .. . . by the way, just in case the smiley didn't give it away, the remark about the metafile /was/ a joke :-) Mike
![]() |
0 |
![]() |
"Mike Williams" <Mike@WhiskyAndCoke.com> wrote > . . . But Webbiz has said that he has an extremely large chart, apparently > about the height of the screen but as wide as at least 25 screens and > possibly many more, While I saw that 120 / 3000 post, it simply did not register as being so massive. I don't know about you, but I think I'd get dizzy looking at 25 screens worth of vertical lines scrolling by.... Might there may be a user interface issue there? Perhaps they should be categorized, or a favorites list, or something to bring that down to a more manageable size. Similar to what is somethimes done when a list has thousands of items, etc... We'll see.... LFS
![]() |
0 |
![]() |
"Larry Serflaten" <serflaten@usinternet.com> wrote in message news:et2cOI4bKHA.1596@TK2MSFTNGP06.phx.gbl... > > "Mike Williams" <Mike@WhiskyAndCoke.com> wrote > >> . . . But Webbiz has said that he has an extremely large chart, >> apparently about the height of the screen but as wide as at least >> 25 screens and possibly many more, > > While I saw that 120 / 3000 post, it simply did not register > as being so massive. I thought you might have missed it Larry, or perhaps it just hadn't registered properly in amongst all the other stuff. That extremely large chart is why my own suggestion has so far been that he draws only the part of it that is currently visible, redrawing the newly selected part each time the user scrolls. Normally, for charts which are not as large as Webbiz's, I would agree with your own previously suggested method of predrawing the lot, before you realised the amount of data he was working with. But drawing a new frame each time the user scrolls would seem to be quite suitable for the OP, although not as fast as scrolling a pre-drawm memory bitmap of course. Looking at the demo at the link posted by Webbiz I can't see anything there that should take more than about 5 or 6 milliseconds to draw on a fairly modest machine. > I don't know about you, but I think I'd get dizzy looking at > 25 screens worth of vertical lines scrolling by.... I certainly would! It's not so bad with other drawings, expanded views of sound waveforms or whatever, but closely spaced fairly thin vetical lines are just about the worst! But is should be okay if the line and background colours are chosen wisely. > Might there may be a user interface issue there? Perhaps they > should be categorized, or a favorites list, or something to bring > that down to a more manageable size. Yes, that's another option. But I have an idea that Webbiz might want to stick to his scrolling viewport with each screen of data drawn on the fly. It is after all the way lots of things with large data sets are arranged, such as waveform editors and the like. The main problem as far as reducing perceived flicker is concerned is the display of the large bunch of very similar and closely spaced vertical lines, so it remains to be seen how it all works in practice with that sort of arrangement. Mike
![]() |
0 |
![]() |
Hi Mike Sorry for the long delay in response. I spent the weekend installing Windows 7 on my main (developer) machine and it's been a slow process from XP Professional. Anyway... (responses between text below) On Fri, 27 Nov 2009 05:30:04 -0000, "Mike Williams" <Mike@WhiskyAndCoke.com> wrote: >"Webbiz" <nospam@forme.thanks.com> wrote in message >news:2rhtg5t0qaq95h56u3f4t1p1ke331g7163@4ax.com... > >> When you discussed the thinkness of the line being more >> than 1 pixel, I suppose you are referring to when my app >> sets the DrawWidth > 1, right? > >Yes. DrawWidth sets the thickness of the line in pixels, regardless of the >VB ScaleMode you might be using. > >> Let's take one of these line draws as an example. >> 'Draw the main vertical bar >> frmChart.pctChart.Line ((i - (gFirstBarRecNum)) * gHSpace, >> dblLowPoint)-((i - (gFirstBarRecNum)) * gHSpace, dblHighPoint), >> lngColor >> Break it down to... >> X1 = (i - (gFirstBarRecNum)) * gHSpace >> Y1 = dblLowPoint >> X2 = ((i - (gFirstBarRecNum)) * gHSpace) - Int(gHSpace / 2) >> Y2 = dblHighPoint >> frmChart.pctChartLine (X1, Y1) - (X2, Y2) > >It looks as though you have broken that down wrongly (which is probably just >a typo) because the former appears to draw a vertical line (your main bar) >whereas the latter appears to draw a small horizontal line (either your >opening or closing price marker), so they are not equivalent, but I think I >can see what you mean . . . Would not doubt it. I broke it down for the post only. In the code itself, it's not broken down. Just wanted to try and make it read easier here. > >> . . . frmChart.pctChartLine (X1, Y1) - (X2, Y2) >> If I were to replace the above line with the FillRect >> API code, what would be the approach? This ... >> Dim r as RECT, retval as Long, brush as Long >> ' Set the coordinates of the bar/rectangle >> retval = SetRect(r, X1, Y1, X2, Y2) >> brush = CreateSolidBrush(lngColor) >> retval = FillRect(frmChart.pctChart.hDC, r, brush) > >Not quite, because the Line coordinates represent the two ends of a line >whereas the FillRect coordinates represent the coordinates of the top left >corner and the bottom right corner of a rectangle. That's right. I better keep that point in mind. ;-) >As far as the FillRect >coordinates are concerned (as they relate to the coordinates you would use >for the Line method) it depends on the thickness of the line and on its >orientation (vertical or horizontal). It also depends on the >pctChart.ScaleMode you are using, because the VB Line method uses ScaleMode >units for the X1, Y1, etc coordinates whereas the FillRect function (as with >all other GDI drawing functions) defaults to using Pixels. So, if you're not >using pixels as your ScaleMode then you would need to perform the >appropriate conversion (or alternatively you can force the GDI functions to >use something other than pixels, but that's another story and is best >avoided for now). On the assumption that your pctChart.ScaleMode is vbPixels >(if not then there will be a little more math) then, using your own VB Line >method example, here are the equivalent FillRect methods ("wide" is a Long >variable containing the desired line thickness in pixels) . . . > >frmChart.pctChartLine.DrawWidth = wide >frmChart.pctChartLine (X1, Y1) - (X2, Y2) > >. . . the equivalent for a vertical line would be > >SetRect r, X1 - wide \ 2, Y1, X2 + wide - wide \ 2, Y2 + 1 >FillRect frmChart.pctChart.hdc, r, brush1 > >. . . and for a horizontal line it would be: > >SetRect r, X1, Y1 - wide \ 2, X2 + 1, Y2 + wide - wide \ 2 >FillRect frmChart.pctChart.hdc, r, brush1 > >You also need to remember that the VB Line method draws rounded ends on >lines thicker than one pixel (or at least it attempts to do so, with the >degree of success depending on the thickness of the line). These rounded >ends are generally added to each end of what would otherwise be a flat edged >line, thereby making it slightly longer than your coordinates when you are >drawing fairly thick lines. The FillRect function will of course not do >that, and will produce a perfectly squared off line of exactly the size and >thickness you require. Personally I think that for your own purposes you are >better off without those rounded ends anyway, but that's a personal choice >of course. This is did not know as well. Rounded ends? How odd. Yes, my chart app would be better served with square edges. > >> I would assume that the 'brush' is set once if all the bars will >> have the same color. Then for every .Line code, replace it >> with two lines, the SetRect and FillRect lines. > >Yes. You need create only one brush and you can use it to draw as many >"lines" (FillRects) as you wish. When you have finally finished with the >brush (and certainly before your program ends) you must delete it (using the >DeleteObject function), otherwise you will have a memory and resource leak. >Since you will be using the brush over and over again for as long as your >program is running I would suggest that you declare it as Private in your >frmChart declarations section (Private BrushBlack as Long, for example) and >create it (CreateSolidBrush) in your frmChart Load event and delete it >(DeleteObject) in your frmChart Unload event. In that way you will be able >to use it in all blocks of code in that Form. You can of course create as >many different colour brushes as you wish, in exactly the same way, so for >example you could have BrushBlack, BrushRed, BrushGreen, BrushBlue etc, all >declared as Private in the declarations section of frmChart and all created >in the Load event and deleted in the Unload event. So in other words, I could create all the color brushes I will need (and there are a few I would need... Red, Blue, Green, Black). This brings up something else. Currently, in order to show the user which bar on the chart the mouse is currently associated with, I have been using a line control (lnPriceBar) that is moved over the vertical bar on the chart, causing it to change color (currently to Fuchsia - I didn't pick it ;). '======= HIGHLITE PRICE BAR If lRecNum <= gLastBarRecNum Then 'change current selected into Fuchsia With lnPricebar .BorderWidth = pctChart.DrawWidth + 2 .x1 = gCurrentBar * gHSpace .y1 = dblHighPoint .x2 = .x1 .y2 = dblLowPoint .Visible = True End With End If I'm assuming I'll need to do this differently if I'm going to use FillRect. The whole idea here is that the vertical bar needs to change colors when the mouse is moved to the same X coordinate as the bar, letting the user which bar is currently selected as the mouse is moved left to right. The data of the bar is currently displayed in the panel below the chart for the highlighted bar. When the mouse is moved off that vertical bar, it must return to the original color. Any thoughts on that? > >There were a number of points raised in your post and I'm not sure whether I >have covered them all here, and of course I may have forgotten to mention >some things that I had intended to mention, but I think that about covers >it. That's me. Always with a number of posts raised. Of all the aspects of VB, the graphics part always seem to be the stickler for me. Pixels, Twips, blah blah. Oh, as to your question on whether my picbox is set to Twips or Pixels, BOTH. When the chart is drawn with the vertical bars, it is set to Twips. Public Sub DrawChart(Optional ByVal x As Long) frmChart.pctChart.ScaleMode = 1 'twips However, various routines in this project will change this scalemode to Pixels, such as the routine to 'clip' part of the picturebox for insertion into posts, emails, etc. Why can't life be simple and one size fits all? LOL Thanks. Webbiz > >Mike > >
![]() |
0 |
![]() |
On Thu, 26 Nov 2009 17:55:24 -0600, "Larry Serflaten" <serflaten@usinternet.com> wrote: > >"Mike Williams" <Mike@WhiskyAndCoke.com> wrote >> > 1. Since I am using an AutoRedraw picturebox (frmChart.pctChart) >> > there is no need for me to do the 'double-buffer' technique because >> > the picturebox will already be doing this when AutoRedraw = True. >> >> Yep. That's about it. > >I would raise an objection there. The difference between drawing the chart >once (to an off screen buffer) and painting in place compared to drawing >the chart in every Resize event is going to increase as the drawing work >load increases. For simple (say less than 50 lines) images, the difference >may be neglegible, but for several hundred lines, the difference will be >signifcantly more noticable. > >If you're only talking about drawing the visible portion of the chart on >each Resize (or Scroll) event, then I would agree, there is no gain in using >a second buffer if VB already does it for you. But I would suggest that >drawing the chart once and painting to the form as needed will be more >responsive to user input.... > >LFS > On average, a complete chart based on all the data loaded would be about 20-30 years worth. At about 200+ bars per year, that would be a complete chart of about 5000 vertical bars. Usually, the user will only view about 100 - 200 at a time in a single view. Most times, the user may scroll back another 100 - 200 bars, but not the whole 5000. Yet, sometimes they might. Assuming a display setting of 200 bars, the app will start out displaying the last 200 bars of the chart. So the DrawChart routine simply gets the data index for the first bar of that last 200 and starts drawing the chart from there. FirstBarRecNum to LastBarRecNum FirstBarRecNum contains the data array index for X = 0 on the picturebox. LastBarRecNum would be the 200th data array index for X = gHSpace * 200 (gHSpace is the horizontal increment from left to right of the picturebox to draw the vertical bars) If the user SCROLLS this chart, the picturebox is cleared, and the chart is redrawn with a new FirstBarRecNum and LastBarRecNum. For example, with a single bar scroll, the FirstBarRecNum is incremented or decremented by 1. LastBarRecNum is then the result of FirstBarRecNum + 200, if there is data for it. LastBarRecNum never exceeds the UBound of the data array. =============== So are you suggesting that the app should paint all 5000 bars on the non-visible picturebox and then display only a portion of it at any given time? What about the lines and other drawings the user may add to the chart and will likely save with the chart for later reload/display? Thanks. Webbiz
![]() |
0 |
![]() |
On Fri, 27 Nov 2009 07:00:34 -0000, "Mike Williams" <Mike@WhiskyAndCoke.com> wrote: >In this specific case there is also the problem of the requirement to >respond to the user's request to magnify portions of the chart, which as I >vaguely recall (although I could be wrong on that point) from some very much >earlier postings by Webbiz (in different threads quite some time ago) >required not just a simple magnification of an existing ready drawn portion >of the chart but needed to draw various elements so that they gained in >visible data resolution when they were magnified, a bit like a metafile >drawing would . . . > >. . . now there's a thought :-) > >Mike Ah, good memory there Mike. Yes, the app has a routine that ZOOMS a portion of the chart with a sort of MagnifyingGlass. As the mouse moves, that part of the chart is magnified. Works really nice. :-) Webbiz
![]() |
0 |
![]() |
On Fri, 27 Nov 2009 10:52:54 -0600, "Larry Serflaten" <serflaten@usinternet.com> wrote: > >"Mike Williams" <Mike@WhiskyAndCoke.com> wrote > >> . . . But Webbiz has said that he has an extremely large chart, apparently >> about the height of the screen but as wide as at least 25 screens and >> possibly many more, > >While I saw that 120 / 3000 post, it simply did not register as being so massive. > >I don't know about you, but I think I'd get dizzy looking at 25 screens worth >of vertical lines scrolling by.... > >Might there may be a user interface issue there? Perhaps they should be >categorized, or a favorites list, or something to bring that down to a more >manageable size. Similar to what is somethimes done when a list has thousands >of items, etc... > >We'll see.... >LFS > > Users may wish to view price data going back years. They may wish to increase the vertical bar density with the "+" key in order to see more years at once, or the "-" key to spread the vertical bars apart to see a certain time frame closer up. Sort of a ZOOM IN and ZOOM OUT scenario. Some users have data going back to the early 1900's. I personally use data files going back to 1980. I may have to see it all at once, or bounce around to different years to do comparisons, etc. As a matter of a cut-off, however, data cannot be loaded prior to 1901. :-) Webbiz
![]() |
0 |
![]() |
On Mon, 30 Nov 2009 14:23:01 -0600, nospam@noway.com wrote: >On Thu, 26 Nov 2009 17:55:24 -0600, "Larry Serflaten" ><serflaten@usinternet.com> wrote: > >> >>"Mike Williams" <Mike@WhiskyAndCoke.com> wrote >>> > 1. Since I am using an AutoRedraw picturebox (frmChart.pctChart) >>> > there is no need for me to do the 'double-buffer' technique because >>> > the picturebox will already be doing this when AutoRedraw = True. >>> >>> Yep. That's about it. >> >>I would raise an objection there. The difference between drawing the chart >>once (to an off screen buffer) and painting in place compared to drawing >>the chart in every Resize event is going to increase as the drawing work >>load increases. For simple (say less than 50 lines) images, the difference >>may be neglegible, but for several hundred lines, the difference will be >>signifcantly more noticable. >> >>If you're only talking about drawing the visible portion of the chart on >>each Resize (or Scroll) event, then I would agree, there is no gain in using >>a second buffer if VB already does it for you. But I would suggest that >>drawing the chart once and painting to the form as needed will be more >>responsive to user input.... >> >>LFS >> > >On average, a complete chart based on all the data loaded would be >about 20-30 years worth. At about 200+ bars per year, that would be a >complete chart of about 5000 vertical bars. > >Usually, the user will only view about 100 - 200 at a time in a single >view. Most times, the user may scroll back another 100 - 200 bars, but >not the whole 5000. Yet, sometimes they might. > >Assuming a display setting of 200 bars, the app will start out >displaying the last 200 bars of the chart. So the DrawChart routine >simply gets the data index for the first bar of that last 200 and >starts drawing the chart from there. > >FirstBarRecNum to LastBarRecNum > >FirstBarRecNum contains the data array index for X = 0 on the >picturebox. LastBarRecNum would be the 200th data array index for X = >gHSpace * 200 > >(gHSpace is the horizontal increment from left to right of the >picturebox to draw the vertical bars) > >If the user SCROLLS this chart, the picturebox is cleared, and the >chart is redrawn with a new FirstBarRecNum and LastBarRecNum. > >For example, with a single bar scroll, the FirstBarRecNum is >incremented or decremented by 1. LastBarRecNum is then the result of >FirstBarRecNum + 200, if there is data for it. LastBarRecNum never >exceeds the UBound of the data array. > >=============== > >So are you suggesting that the app should paint all 5000 bars on the >non-visible picturebox and then display only a portion of it at any >given time? What about the lines and other drawings the user may add >to the chart and will likely save with the chart for later >reload/display? > >Thanks. > >Webbiz > Seems my alias got a bit mucked when I reinstalled the reader into Windows 7. Here's to hoping it's back to Webbiz. :-b
![]() |
0 |
![]() |
Test. On Mon, 30 Nov 2009 14:23:01 -0600, nospam@noway.com wrote: >On Thu, 26 Nov 2009 17:55:24 -0600, "Larry Serflaten" ><serflaten@usinternet.com> wrote: > >> >>"Mike Williams" <Mike@WhiskyAndCoke.com> wrote >>> > 1. Since I am using an AutoRedraw picturebox (frmChart.pctChart) >>> > there is no need for me to do the 'double-buffer' technique because >>> > the picturebox will already be doing this when AutoRedraw = True. >>> >>> Yep. That's about it. >> >>I would raise an objection there. The difference between drawing the chart >>once (to an off screen buffer) and painting in place compared to drawing >>the chart in every Resize event is going to increase as the drawing work >>load increases. For simple (say less than 50 lines) images, the difference >>may be neglegible, but for several hundred lines, the difference will be >>signifcantly more noticable. >> >>If you're only talking about drawing the visible portion of the chart on >>each Resize (or Scroll) event, then I would agree, there is no gain in using >>a second buffer if VB already does it for you. But I would suggest that >>drawing the chart once and painting to the form as needed will be more >>responsive to user input.... >> >>LFS >> > >On average, a complete chart based on all the data loaded would be >about 20-30 years worth. At about 200+ bars per year, that would be a >complete chart of about 5000 vertical bars. > >Usually, the user will only view about 100 - 200 at a time in a single >view. Most times, the user may scroll back another 100 - 200 bars, but >not the whole 5000. Yet, sometimes they might. > >Assuming a display setting of 200 bars, the app will start out >displaying the last 200 bars of the chart. So the DrawChart routine >simply gets the data index for the first bar of that last 200 and >starts drawing the chart from there. > >FirstBarRecNum to LastBarRecNum > >FirstBarRecNum contains the data array index for X = 0 on the >picturebox. LastBarRecNum would be the 200th data array index for X = >gHSpace * 200 > >(gHSpace is the horizontal increment from left to right of the >picturebox to draw the vertical bars) > >If the user SCROLLS this chart, the picturebox is cleared, and the >chart is redrawn with a new FirstBarRecNum and LastBarRecNum. > >For example, with a single bar scroll, the FirstBarRecNum is >incremented or decremented by 1. LastBarRecNum is then the result of >FirstBarRecNum + 200, if there is data for it. LastBarRecNum never >exceeds the UBound of the data array. > >=============== > >So are you suggesting that the app should paint all 5000 bars on the >non-visible picturebox and then display only a portion of it at any >given time? What about the lines and other drawings the user may add >to the chart and will likely save with the chart for later >reload/display? > >Thanks. > >Webbiz >
![]() |
0 |
![]() |
test On Mon, 30 Nov 2009 14:23:01 -0600, nospam@noway.com wrote: >On Thu, 26 Nov 2009 17:55:24 -0600, "Larry Serflaten" ><serflaten@usinternet.com> wrote: > >> >>"Mike Williams" <Mike@WhiskyAndCoke.com> wrote >>> > 1. Since I am using an AutoRedraw picturebox (frmChart.pctChart) >>> > there is no need for me to do the 'double-buffer' technique because >>> > the picturebox will already be doing this when AutoRedraw = True. >>> >>> Yep. That's about it. >> >>I would raise an objection there. The difference between drawing the chart >>once (to an off screen buffer) and painting in place compared to drawing >>the chart in every Resize event is going to increase as the drawing work >>load increases. For simple (say less than 50 lines) images, the difference >>may be neglegible, but for several hundred lines, the difference will be >>signifcantly more noticable. >> >>If you're only talking about drawing the visible portion of the chart on >>each Resize (or Scroll) event, then I would agree, there is no gain in using >>a second buffer if VB already does it for you. But I would suggest that >>drawing the chart once and painting to the form as needed will be more >>responsive to user input.... >> >>LFS >> > >On average, a complete chart based on all the data loaded would be >about 20-30 years worth. At about 200+ bars per year, that would be a >complete chart of about 5000 vertical bars. > >Usually, the user will only view about 100 - 200 at a time in a single >view. Most times, the user may scroll back another 100 - 200 bars, but >not the whole 5000. Yet, sometimes they might. > >Assuming a display setting of 200 bars, the app will start out >displaying the last 200 bars of the chart. So the DrawChart routine >simply gets the data index for the first bar of that last 200 and >starts drawing the chart from there. > >FirstBarRecNum to LastBarRecNum > >FirstBarRecNum contains the data array index for X = 0 on the >picturebox. LastBarRecNum would be the 200th data array index for X = >gHSpace * 200 > >(gHSpace is the horizontal increment from left to right of the >picturebox to draw the vertical bars) > >If the user SCROLLS this chart, the picturebox is cleared, and the >chart is redrawn with a new FirstBarRecNum and LastBarRecNum. > >For example, with a single bar scroll, the FirstBarRecNum is >incremented or decremented by 1. LastBarRecNum is then the result of >FirstBarRecNum + 200, if there is data for it. LastBarRecNum never >exceeds the UBound of the data array. > >=============== > >So are you suggesting that the app should paint all 5000 bars on the >non-visible picturebox and then display only a portion of it at any >given time? What about the lines and other drawings the user may add >to the chart and will likely save with the chart for later >reload/display? > >Thanks. > >Webbiz >
![]() |
0 |
![]() |
<nospam@noway.com> wrote > So are you suggesting that the app should paint all 5000 bars on the > non-visible picturebox and then display only a portion of it at any > given time? What about the lines and other drawings the user may add > to the chart and will likely save with the chart for later > reload/display? No, on further understanding of the situation, the large data set precludes trying to draw it all to memory first. One thing you might be able to make use of is the perminent nature of the AutoRedraw image. If your chart has a bit of border trimmings, in addition to the vertical lines, you could draw the lines at the desired scale, and then only redraw the data. In other words, you can draw the perminent parts of the chart with AutoRedraw set to True, and then set AutoRedraw to False. After that, you only need to draw the parts that change using Cls to erase the old data, leaving the perminent parts intact. Those perminent parts could be your vertical lines and any other border trim you have that never changes. Just a thought to reduce the actual amount of work you need to do for each redraw.... LFS
![]() |
0 |
![]() |
<nospam@noway.com> wrote in message news:lv68h5lgpeiedah0mo7oeavi3qui8hqmuu@4ax.com... > Currently, in order to show the user which bar on the chart > the mouse is currently associated with, I have been using a > line control (lnPriceBar) that is moved over the vertical bar > on the chart, causing it to change color (currently to Fuchsia > - I didn't pick it ;). > If lRecNum <= gLastBarRecNum Then > 'change current selected into Fuchsia > With lnPricebar > .BorderWidth = pctChart.DrawWidth + 2 > .x1 = gCurrentBar * gHSpace > .y1 = dblHighPoint > .x2 = .x1 > .y2 = dblLowPoint > .Visible = True > End With > End If > I'm assuming I'll need to do this differently if I'm going to > use FillRect. Not really. The code I posted the other day (the code which uses FillRect to draw a vertical or horizontal line) uses the same variables (X1, Y1, X2, Y2) that your original VB Line method code used, and it draws the line in exactly the same position, pixel perfect, as would your original VB Line method. The FillRect "line" will be in exactly the same place and will be exactly the same length and width. The only difference is that for lines greater than two pixels in thickness (DrawWidth > 2) the VB Line method would produce a line that is very slightly longer than the FillRect "line" because of the extra "rounding at the line ends" (which varies with thickness) that the VB Line method produces at such thicknesses. So, a line drawn using the VB Line method (using the same DrawWidth) at X1, Y1, X2, Y2 will be guaranteed to cover the line that was drawn at the same X1, Y1, X2, Y2 coordinates using the FillRect method I posted. Does that answer your question? Mike
![]() |
0 |
![]() |
On Mon, 30 Nov 2009 15:55:17 -0600, "Larry Serflaten" <serflaten@usinternet.com> wrote: > ><nospam@noway.com> wrote >> So are you suggesting that the app should paint all 5000 bars on the >> non-visible picturebox and then display only a portion of it at any >> given time? What about the lines and other drawings the user may add >> to the chart and will likely save with the chart for later >> reload/display? > >No, on further understanding of the situation, the large data set precludes >trying to draw it all to memory first. One thing you might be able to make >use of is the perminent nature of the AutoRedraw image. If your chart has >a bit of border trimmings, in addition to the vertical lines, you could draw >the lines at the desired scale, and then only redraw the data. > >In other words, you can draw the perminent parts of the chart with AutoRedraw >set to True, and then set AutoRedraw to False. After that, you only need to draw >the parts that change using Cls to erase the old data, leaving the perminent parts >intact. Those perminent parts could be your vertical lines and any other border >trim you have that never changes. > >Just a thought to reduce the actual amount of work you need to do for each >redraw.... >LFS > Sorry for being a dummy, but I don't follow. Border "trimmings"? Using Cls to erase old data but leaving permanent parts intact? Cls erases the whole picturebox, doesn't it? How would any part of it remain intact? A bit confused overall. o|__| Webbiz
![]() |
0 |
![]() |
"Webbiz" <nospam@noway.com> wrote > >Just a thought to reduce the actual amount of work you need to do for each > >redraw.... > > Sorry for being a dummy, but I don't follow. Border "trimmings"? Using > Cls to erase old data but leaving permanent parts intact? Cls erases > the whole picturebox, doesn't it? How would any part of it remain > intact? Border timmings, those items that are drawn, regardless of the position of the data. Such as a vertical scale, captions, a box around the chart, etc. anything that is drawn in the same position, time after time. No time for an example now, you can easily work one up yourself. Whatever you draw while AutoRedraw is True will not be erased by Cls when AutoRedraw is set to False. You can use that feature to pre-draw your vertical lines (and trimmings) such that you only need to draw the data as the user scrolls the chart. LFS
![]() |
0 |
![]() |
On Mon, 30 Nov 2009 20:53:50 -0600, "Larry Serflaten" <serflaten@usinternet.com> wrote: >Whatever you draw while AutoRedraw is True will not be erased by >Cls when AutoRedraw is set to False. Well that is pretty cool. :-) Thx. Webbiz
![]() |
0 |
![]() |