From: Webbiz on
I use a picturebox to draw lines and such within.

I would like to plot some arrows on this picturebox.

Two kinds. A small blue UP arrow, and a small red DOWN arrow, at
various spots on this picturebox.

What is the best way to do this?

Should I create my two arrow pictures and save as a bitmap or
something, then have them appear on the picturebox where I want them?

Should I use drawing commands to draw point-to-point lines and fill?

My picturebox is redrawn each time I scroll the items drawn within. So
the arrows will also have to follow along. Which approach would be
best for such an application?

Thanks.

Webbiz
From: Ivar on


If scrolling is involved then speed of drawing is an issue, for that reason
I would not use bitmaps etc. Instead create yourself a sub that you can pass
the needed arguments to, such as the HDC, the X and the Y and something to
indentify the type of arrow to draw and call it as needed. I would look to
CreatePolygonRgn and similar APIs for the drawing of shapes.
With this method you can have total control of what is drawn with very fast
speeds. Just needs a bit more coding from you.
Have fun

Ivar

From: Mike Williams on
"Webbiz" <nospam(a)noway.com> wrote in message
news:i2epo5lqmsbcf1e9smt060n61fvlg770jk(a)4ax.com...

> I use a picturebox to draw lines and such within.
> I would like to plot some arrows on this picturebox.
> Two kinds. A small blue UP arrow, and a small red
> DOWN arrow, at various spots on this picturebox.
> What is the best way to do this?

If the arrow is a complex 3D effect drawing then you would probably be
better off holding an image and a mask of the drawing in a couple of
offscreen DCs and drawing it "transparently" to the display using a couple
of GDI BitBlt operations, typically a vbMergePaint Blit of the mask followed
by a vbSrcAnd Blit of the image.

Alternatively, if the arrow is a simple line drawing (either filled or
unfilled), then it would probably be faster to draw it using the GDI Polygon
function, which is capable of drawing either filled or unfilled polygons in
a single call depending on the current FillStyle and FillColor properties.
You could hold your set of fixed polygon (x, y) point data that describes
the shape of the arrow in a VB array of POINTAPIs and you could use the same
data, the same array of (x, y) coordinates, regardless of where you want
the arrow drawing to appear simply by using the GDI SetWindowOrgEx function
to set the drawing origin of your PictureBox to the appropriate value
depending on where you want the arrow to be drawn and then using the GDI
Polygon function to draw the filled arrow followed by another call to
SetWindowOrgEx to set the drawing origin back to its default condition of
(0, 0).

The speed of these operations will depend on the machine on which it is
running of course, particularly if it is running on Vista which will slow it
down because Vista will have totally disabled the video card's GDI hardware
acceleration, but for your small arrows it will be quite fast in both cases
(BitBlt or Polygon). As an example, I've just tried both methods on my quite
humble (by today's standards) 1.6 Ghz Celeron Vista laptop, drawing a filled
arrow about 20 pixels wide by 50 pixels high (which is probably larger than
the arrows you wish to draw) and these are the results:

BitBlt : 62 microseconds
(one MergPaint and one SrcAnd)

Polygon : 36 microseconds
(two SetWindowOrgEx and one Polygon)

As you will see, Polygon is significantly faster than BitBlt although both
methods are quite fast. Even on my own humble 1.6 Ghz Celeron laptop on
which the GDI functions are being "strangled" by Vista it is possible to
draw about thirty 20 x 50 pixel filled arrows in one millisecond.

Mike



From: Nobody on
"Webbiz" <nospam(a)noway.com> wrote in message
news:i2epo5lqmsbcf1e9smt060n61fvlg770jk(a)4ax.com...
>I use a picturebox to draw lines and such within.
>
> I would like to plot some arrows on this picturebox.
>
> Two kinds. A small blue UP arrow, and a small red DOWN arrow, at
> various spots on this picturebox.
>
> What is the best way to do this?
>
> Should I create my two arrow pictures and save as a bitmap or
> something, then have them appear on the picturebox where I want them?
>
> Should I use drawing commands to draw point-to-point lines and fill?
>
> My picturebox is redrawn each time I scroll the items drawn within. So
> the arrows will also have to follow along. Which approach would be
> best for such an application?

Some code template like Ivar suggested(The Enum helps providing Intelisis):

Public Enum enumShapes
eShapeUpArrow
eShapeDownArrow
eShapeCircle
End Enum

Public Sub DrawShape(ByVal Shape As enumShapes, ByVal hDC As Long, ByVal x
As Single, ByVal y As Single, ByVal r As Single, ByVal Color As Long)
Select Case Shape
Case eShapeUpArrow:
Case eShapeDownArrow:
Case eShapeCircle:
End Select
End Sub



From: Mike Williams on
"Mike Williams" <Mike(a)WhiskyAndCoke.com> wrote in message
news:%23ubQdAfuKHA.812(a)TK2MSFTNGP06.phx.gbl...

> . . if the arrow is a simple line drawing (either filled or unfilled),
> then it would probably be faster to draw it
> using the GDI Polygon function . .

One thing I forgot to mention in my previous response is if you decide to
use the Polygon and SetWindowOrgEx method to draw your arrows then it might
be best to make the first data item in the array of poly points the
coordinates of the point of the arrow (rather than the coordinates of any
other position around its shape) and set the "point" coordinates in the data
to the values (0, 0). In that way whenever you wish to draw an arrow you
merely need to specify the location of its point (which is probably most
often the part of the arrow you are interested in) and the arrow will be
drawn with its point at the desired location. To see what I mean, try the
following simplified example (into a Form containing a PictureBox and a
Command Button). The outline color of the arrow is determined by the
ForeColor of the PicBox and the fill colour is determined both by the
FillStyle and FillColor properties, all of which you can set using either
the standard VB PictureBox properties or their equivalent GDI methods.

Mike

Option Explicit
Private Declare Function SetWindowOrgEx Lib "gdi32" _
(ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, _
lpPoint As POINTAPI) As Long
Private Declare Function Polygon 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 DownData(1 To 7) As POINTAPI

Private Sub Form_Load()
DownData(1).x = 0: DownData(1).y = 0 ' the arrow point
DownData(2).x = -8: DownData(2).y = -17
DownData(3).x = -3: DownData(3).y = -17
DownData(4).x = -3: DownData(4).y = -48
DownData(5).x = 3: DownData(5).y = -48
DownData(6).x = 3: DownData(6).y = -17
DownData(7).x = 8: DownData(7).y = -17
End Sub

Private Sub DrawDownArrow(pic As PictureBox, x As Single, y As Single)
Dim p1 As POINTAPI, x1 As Long, y1 As Long
x1 = pic.ScaleX(x - pic.ScaleLeft, pic.ScaleMode, vbPixels)
y1 = pic.ScaleY(y - pic.ScaleTop, pic.ScaleMode, vbPixels)
SetWindowOrgEx pic.hdc, -x1, -y1, p1 ' set origin
Polygon pic.hdc, DownData(1), 7
SetWindowOrgEx pic.hdc, p1.x, p1.y, p1 ' restore original origin
End Sub

Private Sub Command1_Click()
Picture1.ScaleWidth = 1000
Picture1.ScaleHeight = 1000
' draw a "down arrow" with its point at the centre
DrawDownArrow Picture1, 500, 500
End Sub