Re: Which component to use to display mathematical graphs with VB6
- From: Mike Williams <gagamomo@xxxxxxxxxxx>
- Date: Sat, 10 Jan 2009 05:11:40 -0800 (PST)
On 10 Jan, 03:01, Stefan Mueller <seekw...@xxxxxxxxx> wrote:
Mike, you are great!
I wish you'd tell my wife that ;-)
After some testing it works perfect even in my
code ;-) I've only some minor questions?
1) If I run your code and click the 'X' on the
right top corner of the Form, the Form closes
but the program is somehow still running. I see
this because I'm still able to click 'Run - End'
(in Microsoft Visual Basic) and also because
VB6.EXE is still using around 50% of the CPU.
Do you know a way to finish the program properly?
These are the kind of things you need to be careful of, especially
when using continuous loops and if those loops contain Dovents, and
also sometimes when not using loops but when using Timers. In fact it
is worse when you run such a program as a compiled exe instead of in
the VB IDE, because then when you close the Form it looks as though
the application has completely closed, because the Form disappears
from view, but the code is actually still there and if it is still
running it will slow down other applications on the machine. In fact
your continuous loop will be
taking as much processor time as it can get its hands on, which will
cause the processor to go to full 100% on a single processor single
core mnachine, and to 50% on a two core machine (because VB code uses
only one core at a time), so I assume that your own machine is a dual
core.
Anyway, it is easy to fix. When I write code examples for posting to
the group I usually concentrate just on the task at hand, because I
really don't know how you will "knit" the example into your own
existing code, and so I usually leave out what I would call "the
housekeeping stuff". What you need to do is allow the loop to finish
when the user closes the Form. One very easy way to do this is to use
a Form level Boolean variable (which of course defaults to False) and
check that variable within the loop, exiting the loop if it ever goes
True. Then in the Form's QueryUnload event you set the Boolean
variable to True. Have a look at the example I've included at the end
of this post, which will also answer your ther question:
2) Do you know a way to move the transparent image? I
tried to change '50, 50' (TransparentBlt) in your code
with a Slider. It works but the image at the old position
does not get removed. Is there an easy way to move the
transparent image without flickering?
Yes. You are already erasing the old set of lines before you draw the
new set, so that you see just the current set of lines on the display.
You need to deal with the drawing of the image in a similar way,
erasing the old image before you draw the new one if you want it to be
drawn at a new position. In fact it's probably simplest to erase the
old image every time, whether you intend to change the position or
not, unless you are using an extremely slow machine. For example, at
the moment for each frame you are doing:
EXISTING METHOD:
1. Erase old lines by redrawing in back colour.
2. Draw new lines at their new positions.
3. Draw picture at its fixed position.
You just change that to:
NEW METHOD 1:
1. Erase old lines by redrawing in back colour.
2. Erase picture at its old position (draw a filled rectangle)
3. Draw new lines at their new positions.
4. Draw picture at its new position.
An alternative method would be:
NEW METHOD 2:
1. Erase entire Form (draw a large filled rectangle)
3. Draw new lines at their new positions.
4. Draw picture at its new position.
The first of the suggested methods (NEW METHOD 1) is best if you are
nor drawing many lines (perhaps less than a few hundred) and there are
not too many images (perhaps less than ten) and they are not too large
and the second suggested method (NEW METHOD 1) is best if you are
drawing thousands of lines and lots of images. There are of course, as
is always the case, various other alternative methods which are useful
in various circumstances, some of which are fairly complicated to
arrange (what many people call the "dirty rectangle" method). The
example at the bottom of this post uses NEW METHOD 2.
3) You mentioned twice that you would draw the lines into a
PictureBox rather then to the Form itself. Is there a reason for
that or is it just not common to draw lines directly to the Form?
What's the advantage of using a PictureBox?
It is just more flexible. For example, if you deciude later that you
want it to fill just part of the Form (rather than all of it) so that
you can use other parts of the Form for other things then you can do
so simply by changing the size (and possibly placement) of the
PictureBox with minimal code changes. Also, if you ever wish to save
the contents of the main PictureBox to file then you can simply save
its Image property using SavePicture and the saved bitmap will
automatically be the same pixel size as the pixel size of the
PictureBox (except under certain conditions which I won't go into here
and which can easily be coded around anyway) whereas if you are
drawing your stuff to the Form instead (a standard resizable Form) and
you save the Form's Image property as a bitmap the saved bitmap will
always be the same as the total screen size, regardless of the actual
pixel size of the Form. Essentially you can draw either to the Form or
to a PictureBox, but a PictureBox would be my own personal choice.
If you advise me to use a PictureBox how do I have to use it?
- I add a PictureBox (e.g. PictureBox1) on the Form
Yes.
- I add several other PictureBoxes (for my transparent
images) into PictureBox1
You can place those other PictureBoxes anywhere. They do not need to
be contained in the main PictureBox. They should all be set to Visible
= False and Autoredraw = True so that we can use their hidden
Autoredraw bitmap and draw it to the appropriate position in the main
displayed PictureBox.
- I do
With Me.PictureBox1
.Visible = True
.ScaleMode = vbPixels
.AutoRedraw = True
.Left = 0
.Top = 0
.Width = Me.ScaleWidth
.Height = Me.ScaleHeight
End With
Me.AutoRedraw = False ('True' is not necessary anymore.
Correct?) Is this correct?
Pretty much what you have sugfgested. And you're right about the Form.
There would no longer be any need for the Form's Autoredraw property
to be True. In fact you would be wasting memory if you did set it to
True and if you drew anything into it. I'm in a bit of a rush at the
moment (wife is dragging me out shopping!) but I think I've covered
most of your questions. Post again if I've left anything out. The
example code is as follows (it uses a Form simply because that's how
the original code example was). Start a new project and place one
PictureBox (used for the image) and paste in the following code
(changing the hard coded picture path as appropriate):
Mike
Option Explicit
Private Declare Function Polyline Lib "gdi32" _
(ByVal hdc As Long, lpPoint As PointAPI, _
ByVal nCount As Long) As Long
Private Type PointAPI
x As Long
y As Long
End Type
Private Declare Function TransparentBlt Lib "msimg32.dll" _
(ByVal hdc As Long, _
ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal hSrcDC As Long, _
ByVal xSrc As Long, ByVal ySrc As Long, _
ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, _
ByVal crTransparent As Long) As Boolean
Private Declare Function Rectangle Lib "gdi32" _
(ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, _
ByVal X2 As Long, ByVal Y2 As Long) As Long
Private WantsClosing As Boolean
Private keymap(0 To 255) As Byte
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
keymap(KeyCode) = True
End Sub
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
keymap(KeyCode) = False
End Sub
Private Sub Form_Load()
Me.WindowState = vbMaximized
Me.ScaleMode = vbPixels
Me.AutoRedraw = True
With Picture1
.Visible = False
.ScaleMode = vbPixels
.AutoRedraw = True
.BackColor = vbWhite
.AutoSize = True
' the picture can be a transparent gif or a
' non transparent gif on a white background
' or a standard bitmap which contains white
' pixels in the parts you wish to be
' transparent. Colours other than white
' can be used as the transparent colour
' by modifying the last parameter of the
' TransparentBlt call appropriately
.Picture = LoadPicture("c:\temp\mustang.gif")
End With
End Sub
Private Sub Form_Activate()
Dim PolyPoints() As PointAPI
Dim n As Long, p As Long
Dim t1 As Long, t2 As Long
Dim xPic As Long, yPic As Long
Caption = "Press arrow keys to move image " _
& "(Make sure that this Form is the active window)"
p = 100
ReDim PolyPoints(1 To p)
Do
If keymap(38) Then yPic = yPic - 1
If keymap(40) Then yPic = yPic + 1
If keymap(37) Then xPic = xPic - 1
If keymap(39) Then xPic = xPic + 1
' Remove old lines
' (The following method which has been commented
' out removes the old lines by redrawing them in
' the back colour
' Me.ForeColor = &H8000000F
' Polyline Me.hdc, PolyPoints(1), p
' (The following alternative method removes evrything
' including the lines of course by drawing a solid
' back colour rectangle covering the whole Form)
Me.FillStyle = vbFSSolid
Me.FillColor = Me.BackColor
Rectangle Me.hdc, -1, -1, Me.ScaleWidth + 1, Me.ScaleHeight + 1
' create a new PolyLine with p lines
For n = 1 To p
PolyPoints(n).x = Int(Rnd * 1150)
PolyPoints(n).y = Int(Rnd * 850)
Next n
' Draw new lines
Me.ForeColor = &HFF0000
Polyline Me.hdc, PolyPoints(1), p
' draw an image such that any part of the image which
' is white will be drawn as transparent
TransparentBlt Me.hdc, xPic, yPic, Picture1.ScaleWidth, _
Picture1.ScaleHeight, Picture1.hdc, 0, 0, _
Picture1.ScaleWidth, Picture1.ScaleHeight, vbWhite
' Now that the graph and the overlying transparent
' picture have been drawn into the Form's hidden Autoredraw
' memory bitmap (effectively our back buffer) issue a
' Me.Refresh to cause the system to transfer the Autoredraw
' memory bitmap to the display
Me.Refresh
DoEvents
If WantsClosing Then Exit Sub
Loop
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, _
UnloadMode As Integer)
WantsClosing = True
End Sub
.
- References:
- Re: Which component to use to display mathematical graphs with VB6
- From: Stefan Mueller
- Re: Which component to use to display mathematical graphs with VB6
- From: Mike Williams
- Re: Which component to use to display mathematical graphs with VB6
- From: Stefan Mueller
- Re: Which component to use to display mathematical graphs with VB6
- From: Mike Williams
- Re: Which component to use to display mathematical graphs with VB6
- From: Stefan Mueller
- Re: Which component to use to display mathematical graphs with VB6
- From: Mike Williams
- Re: Which component to use to display mathematical graphs with VB6
- From: Stefan Mueller
- Re: Which component to use to display mathematical graphs with VB6
- From: Mike Williams
- Re: Which component to use to display mathematical graphs with VB6
- From: Stefan Mueller
- Re: Which component to use to display mathematical graphs with VB6
- Prev by Date: Re: Which component to use to display mathematical graphs with VB6
- Next by Date: Re: Which component to use to display mathematical graphs with VB6
- Previous by thread: Re: Which component to use to display mathematical graphs with VB6
- Next by thread: Re: Which component to use to display mathematical graphs with VB6
- Index(es):
Relevant Pages
|