473,395 Members | 2,796 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Nearest point to the mouse cursor?

I have been developing a little project which draw's a hexgrid on a panel
within a form similar to this - it:s used as a client from a e-mail based
strategy game:
____ ____
/ \ / \
/ (0,0) \____/ (2,0) \____/
\ / \ / \
\____/(1,1) \____/ (3,1) \_
/ \ / \
/ (0,1) \____/ (2,1) \____/
\ / \ / \
\____/(1,2) \____/ (3,2) \_
/ \ / \
/ (0,2) \____/ (2,2) \____/
\ / \ / \
\____/(1,3) \____/ (3,3) \_

The number of hexes can vary depending on the mapsize. now the problem I
currently have is trying to get a label.text to display which hex coord the
mouse is currently in.

Using the mouse move function I can get it to automatically change when it
passes over the lines in the (1,y) columns by using the following formula:

(for these purposes HexHeight = 44 pixels, HexWidth = 50 pixels)

MouseYpos = LocalMousePosition.Y / HexHeight
Label1.text = "Coords: " & MouseXpos & "," & MouseYpos

however, because the colums are staggered any column starting with an even
number get's the new coords changed halfway through it.

So I'm now leaning towards trying mark the centre point of each hex, and
then establishing which one the mousepointer is nearest to. However I'm
having difficulty in figuring out how to do this.

Can anyone help?
Nov 21 '05 #1
16 1928
Hi,
Create a region for each cell. Use the region isvisble to see if
the cursor is in the cell.

Dim rgnCircle As Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Dim pth As New System.Drawing.Drawing2D.GraphicsPath

pth.AddEllipse(100, 100, 50, 50)

rgnCircle = New Region(pth)

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

e.Graphics.FillRegion(Brushes.Blue, rgnCircle)

End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove

Me.Text = String.Format("In Circle {0}", rgnCircle.IsVisible(New Point(e.X,
e.Y)))

End Sub

Ken

-------------------------------------

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote in message
news:9E**********************************@microsof t.com...
I have been developing a little project which draw's a hexgrid on a panel
within a form similar to this - it:s used as a client from a e-mail based
strategy game:
____ ____
/ \ / \
/ (0,0) \____/ (2,0) \____/
\ / \ / \
\____/(1,1) \____/ (3,1) \_
/ \ / \
/ (0,1) \____/ (2,1) \____/
\ / \ / \
\____/(1,2) \____/ (3,2) \_
/ \ / \
/ (0,2) \____/ (2,2) \____/
\ / \ / \
\____/(1,3) \____/ (3,3) \_

The number of hexes can vary depending on the mapsize. now the problem I
currently have is trying to get a label.text to display which hex coord the
mouse is currently in.

Using the mouse move function I can get it to automatically change when it
passes over the lines in the (1,y) columns by using the following formula:

(for these purposes HexHeight = 44 pixels, HexWidth = 50 pixels)

MouseYpos = LocalMousePosition.Y / HexHeight
Label1.text = "Coords: " & MouseXpos & "," & MouseYpos

however, because the colums are staggered any column starting with an even
number get's the new coords changed halfway through it.

So I'm now leaning towards trying mark the centre point of each hex, and
then establishing which one the mousepointer is nearest to. However I'm
having difficulty in figuring out how to do this.

Can anyone help?
Nov 21 '05 #2
Hi,

Thanks for the help so far but I do have one further question - how do
you do it for multiple regions?

I've managed to apply the example you gave me to my program but I now
have another problem... there could be hundreds of Hexregions on the
form at any time - the problem is it's an unknown number of regions as
the person running the server can make a map of any size.

How can I take this to the next step and get the mousemove event to
cover an unknown number of regions on the form?

Niels

Ken Tucker [MVP] wrote:
Hi,
Create a region for each cell. Use the region isvisble to see if
the cursor is in the cell.

Dim rgnCircle As Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Dim pth As New System.Drawing.Drawing2D.GraphicsPath

pth.AddEllipse(100, 100, 50, 50)

rgnCircle = New Region(pth)

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

e.Graphics.FillRegion(Brushes.Blue, rgnCircle)

End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove

Me.Text = String.Format("In Circle {0}", rgnCircle.IsVisible(New Point(e.X,
e.Y)))

End Sub

Ken

-------------------------------------

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote in message
news:9E**********************************@microsof t.com...
I have been developing a little project which draw's a hexgrid on a panel
within a form similar to this - it:s used as a client from a e-mail based
strategy game:
____ ____
/ \ / \
/ (0,0) \____/ (2,0) \____/
\ / \ / \
\____/(1,1) \____/ (3,1) \_
/ \ / \
/ (0,1) \____/ (2,1) \____/
\ / \ / \
\____/(1,2) \____/ (3,2) \_
/ \ / \
/ (0,2) \____/ (2,2) \____/
\ / \ / \
\____/(1,3) \____/ (3,3) \_

The number of hexes can vary depending on the mapsize. now the problem I
currently have is trying to get a label.text to display which hex coord the
mouse is currently in.

Using the mouse move function I can get it to automatically change when it
passes over the lines in the (1,y) columns by using the following formula:

(for these purposes HexHeight = 44 pixels, HexWidth = 50 pixels)

MouseYpos = LocalMousePosition.Y / HexHeight
Label1.text = "Coords: " & MouseXpos & "," & MouseYpos

however, because the colums are staggered any column starting with an even
number get's the new coords changed halfway through it.

So I'm now leaning towards trying mark the centre point of each hex, and
then establishing which one the mousepointer is nearest to. However I'm
having difficulty in figuring out how to do this.

Can anyone help?

Nov 21 '05 #3

"Niels Jensen" <ni***@surf-spot.co.uk> wrote

Thanks for the help so far but I do have one further question - how do
you do it for multiple regions?

I've managed to apply the example you gave me to my program but I now
have another problem... there could be hundreds of Hexregions on the
form at any time - the problem is it's an unknown number of regions as
the person running the server can make a map of any size.

How can I take this to the next step and get the mousemove event to
cover an unknown number of regions on the form?

Since you have to cover some large number of cells, you might do best
by calculating the results. For an example, paste the following code in
a new form, under the Designer generated code (section).

HTH
LFS

Public Image As Bitmap
Private Rows(1) As Array

Const SX As Integer = 30 ' Red cell sizes
Const SY As Integer = 50

Const RATIO As Single = SX / SY

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Image = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
' Row map indicates which cells have angles
Rows(0) = New Integer() {-1, 0, 0, -2, 1, 1, -1}
Rows(1) = New Integer() {-2, 0, 0, -1, 1, 1, -2}
DrawHex()
End Sub

Private Sub HexCell(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
Dim r, x, y, hx, hy As Integer
Dim a As Integer()

' Get red grid cell x and y
x = e.X \ SX
y = e.Y \ SY

' Preliminary HexX and HexY
hx = x \ 3
hy = y \ 2

' Get row map value (r)
a = CType(Rows(y And 1), Integer())
r = a(x Mod 6)

' Adjust for angled cells
If r = -1 Then
If (e.X - (x * SX)) < ((SY - (e.Y - (y * SY))) * RATIO) Then
hx -= 1
End If
'Debug.WriteLine((e.X - (x * SX)).ToString & " X " & (SY - (e.Y - (y * SY))).ToString & " -Y " & ((SY - (e.Y - (y *
SY))) * RATIO).ToString)
ElseIf r = -2 Then
If (e.X - (x * SX)) < ((e.Y - (y * SY)) * RATIO) Then
hx -= 1
End If
'Debug.WriteLine((e.X - (x * SX)).ToString & " X " & (e.Y - (y * SY)).ToString & " -Y " & ((e.Y - (y * SY)) *
RATIO).ToString)
End If

' Adjust for y offset in odd hex columns
If (hx And 1) = 1 AndAlso (y And 1) = 0 Then hy -= 1

' Show values
Dim msg As String = "X=" & hx.ToString & " Y=" & hy.ToString
If Me.Text <> msg Then Me.Text = msg

End Sub

Private Sub DrawHex()
' This just draws the cells on the screen
Dim grx As Graphics = Graphics.FromImage(Image)
Dim r, hx, hy, x, y As Integer
Dim a As Integer()

For y = 0 To 12
For x = 0 To 17
grx.DrawRectangle(Pens.Red, New Rectangle(x * SX, y * SY, SX, SY))
a = CType(Rows(y And 1), Integer())
r = a(x Mod 6)
hx = x * SX
hy = y * SY
If r = 0 Then
If (y And 1) = 0 Then
grx.DrawLine(Pens.Black, hx, hy, hx + SX, hy)
Else
grx.DrawLine(Pens.Black, hx, hy + SY, hx + SX, hy + SY)
End If
ElseIf r = 1 Then
If (y And 1) = 1 Then
grx.DrawLine(Pens.Black, hx, hy, hx + SX, hy)
Else
grx.DrawLine(Pens.Black, hx, hy + SY, hx + SX, hy + SY)
End If
ElseIf r = -1 Then
grx.DrawLine(Pens.Black, hx, hy + SY, hx + SX, hy)
ElseIf r = -2 Then
grx.DrawLine(Pens.Black, hx, hy, hx + SX, hy + SY)
End If
Next
Next

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
Dim grx As Graphics = Me.CreateGraphics
grx.DrawImage(Image, 0, 0)
grx.Dispose()
End Sub

Nov 21 '05 #4
Thanks for this code Larry it's *yet* another was that I can draw a hexmap...

Is there any chance you could be so kind and explain what the complicated
mathematical sections do (and how they do it?) I've been trying to figure
out how the 1st section works:
Rows(0) = New Integer() {-1, 0, 0, -2, 1, 1, -1}
Rows(1) = New Integer() {-2, 0, 0, -1, 1, 1, -2}
it doesn't make any sense to me as I thought the {} was used for formatting.
If you can't tell, I'm also a bit of a newbie in this VB lark :)

I'm also drawing the hexcells in a panel, not a form and although I've
successfully managed to do this within my program using your code, the
graphics are only drawn within the initial visible part of the panel, as soon
as I use the scrollbars I get one of two things hapening. If the drawimage
is in the "paint" sub then it re-draws all over the screen eventually drawing
a nice big red block on the panel screen. how can I make your hexmap draw a
50hex by 50hex board and then maintain the image so that the scrollbars on
the panel display the image correctly. I'll be overlaying the Hexes that
have information with small .bmp graphical images such as trees or towns, the
idea being that the end user can click on a hex containing a town image and
get the information for the town.

Niels

"Larry Serflaten" wrote:

"Niels Jensen" <ni***@surf-spot.co.uk> wrote

Thanks for the help so far but I do have one further question - how do
you do it for multiple regions?

I've managed to apply the example you gave me to my program but I now
have another problem... there could be hundreds of Hexregions on the
form at any time - the problem is it's an unknown number of regions as
the person running the server can make a map of any size.

How can I take this to the next step and get the mousemove event to
cover an unknown number of regions on the form?

Since you have to cover some large number of cells, you might do best
by calculating the results. For an example, paste the following code in
a new form, under the Designer generated code (section).

HTH
LFS

Public Image As Bitmap
Private Rows(1) As Array

Const SX As Integer = 30 ' Red cell sizes
Const SY As Integer = 50

Const RATIO As Single = SX / SY

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Image = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
' Row map indicates which cells have angles
Rows(0) = New Integer() {-1, 0, 0, -2, 1, 1, -1}
Rows(1) = New Integer() {-2, 0, 0, -1, 1, 1, -2}
DrawHex()
End Sub

Private Sub HexCell(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
Dim r, x, y, hx, hy As Integer
Dim a As Integer()

' Get red grid cell x and y
x = e.X \ SX
y = e.Y \ SY

' Preliminary HexX and HexY
hx = x \ 3
hy = y \ 2

' Get row map value (r)
a = CType(Rows(y And 1), Integer())
r = a(x Mod 6)

' Adjust for angled cells
If r = -1 Then
If (e.X - (x * SX)) < ((SY - (e.Y - (y * SY))) * RATIO) Then
hx -= 1
End If
'Debug.WriteLine((e.X - (x * SX)).ToString & " X " & (SY - (e.Y - (y * SY))).ToString & " -Y " & ((SY - (e.Y - (y *
SY))) * RATIO).ToString)
ElseIf r = -2 Then
If (e.X - (x * SX)) < ((e.Y - (y * SY)) * RATIO) Then
hx -= 1
End If
'Debug.WriteLine((e.X - (x * SX)).ToString & " X " & (e.Y - (y * SY)).ToString & " -Y " & ((e.Y - (y * SY)) *
RATIO).ToString)
End If

' Adjust for y offset in odd hex columns
If (hx And 1) = 1 AndAlso (y And 1) = 0 Then hy -= 1

' Show values
Dim msg As String = "X=" & hx.ToString & " Y=" & hy.ToString
If Me.Text <> msg Then Me.Text = msg

End Sub

Private Sub DrawHex()
' This just draws the cells on the screen
Dim grx As Graphics = Graphics.FromImage(Image)
Dim r, hx, hy, x, y As Integer
Dim a As Integer()

For y = 0 To 12
For x = 0 To 17
grx.DrawRectangle(Pens.Red, New Rectangle(x * SX, y * SY, SX, SY))
a = CType(Rows(y And 1), Integer())
r = a(x Mod 6)
hx = x * SX
hy = y * SY
If r = 0 Then
If (y And 1) = 0 Then
grx.DrawLine(Pens.Black, hx, hy, hx + SX, hy)
Else
grx.DrawLine(Pens.Black, hx, hy + SY, hx + SX, hy + SY)
End If
ElseIf r = 1 Then
If (y And 1) = 1 Then
grx.DrawLine(Pens.Black, hx, hy, hx + SX, hy)
Else
grx.DrawLine(Pens.Black, hx, hy + SY, hx + SX, hy + SY)
End If
ElseIf r = -1 Then
grx.DrawLine(Pens.Black, hx, hy + SY, hx + SX, hy)
ElseIf r = -2 Then
grx.DrawLine(Pens.Black, hx, hy, hx + SX, hy + SY)
End If
Next
Next

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
Dim grx As Graphics = Me.CreateGraphics
grx.DrawImage(Image, 0, 0)
grx.Dispose()
End Sub

Nov 21 '05 #5

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote
Thanks for this code Larry it's *yet* another was that I can draw a hexmap...

Is there any chance you could be so kind and explain what the complicated
mathematical sections do (and how they do it?)
It is very easy to get X and Y coordinates when the cells are rectangles:
' Get red grid cell x and y
x = e.X \ SX
y = e.Y \ SY


SX and SY are the size values of the red cells, so that, dividing the
current X or Y mouse position by the size of the cell give the cell's
X or Y values.

It is not so easy when there are angled lines or other such polygons.
In your case, I first set out to identify where the angled lines are, you
can see by the displayed grid they do follow a repeating pattern and
that pattern is represented in the Rows array. Second, the angle the
slopes are at is constant so one formula (based on the ratio of X to Y)
can be used to tell when the mouse crosses the angled line. When it
does, the horizontal position has to be adjusted. There is one formula
for the forward slash, and another for the backward slash. With the
correct X position, there is one other thing to address and that is that
alternating hex columns are offset by one cell difference and that is
found and altered as the last part of the process.

I've been trying to figure
out how the 1st section works:
Rows(0) = New Integer() {-1, 0, 0, -2, 1, 1, -1}
Rows(1) = New Integer() {-2, 0, 0, -1, 1, 1, -2}

It is an array of arrays.

These statements assign arrays of Integers to the elements of the Rows
array. "New Integer()" tells VB you're creating a new array and the values
inside the brackets initialize that array with those values. In this case, a -1
represents the forward slash (angle cell) and -2 represents the backward
slash (angle cell). 0 and 1 were only used during the draw process to help
determine if the horizontal line of the hex cell should be at the top or
bottom of that group of cells.
I'm also drawing the hexcells in a panel, not a form and although I've
successfully managed to do this within my program using your code, the
graphics are only drawn within the initial visible part of the panel, as soon
as I use the scrollbars I get one of two things hapening. If the drawimage
is in the "paint" sub then it re-draws all over the screen eventually drawing
a nice big red block on the panel screen. how can I make your hexmap draw a
50hex by 50hex board and then maintain the image so that the scrollbars on
the panel display the image correctly. I'll be overlaying the Hexes that
have information with small .bmp graphical images such as trees or towns, the
idea being that the end user can click on a hex containing a town image and
get the information for the town.


You will probably want to back up that panel with a memory bitmap such that
you draw your 50X50 board to the bitmap, and then copy it over to the panel
(in its Paint event) depending on the scroll position.

While doing your drawing in the paint event is a low impact method, it gets a
bit useless when you have several items to draw and are erasing the screen to
reposition them all. In that case it is better to draw to memory and then copy
the finished image in one go.

Take a look at what I did, I gave the form a public Image property that was
my memory bitmap. It is such a common methodology that I did it by habit!
In the form's Paint event I simply copied over the image in one go. Doing it
that way (and even that can be improved) allows for automatic repainting when
the form is restored from being minimized, or when some other window covers
and then exposes that form.

Where I have 0, 0 you'd add in values from your scroll control....

HTH
LFS


Nov 21 '05 #6
Hi,

Try something like this.

Dim arShapes As New ArrayList

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

For x As Integer = 0 To 4

Dim pth As New System.Drawing.Drawing2D.GraphicsPath

Dim rgnCircle As Region

pth.AddEllipse(100, 10 + x * 50, 50, 50)

rgnCircle = New Region(pth)

arShapes.Add(rgnCircle)

Next x

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

For Each rgnCircle As Region In arShapes

e.Graphics.FillRegion(Brushes.Blue, rgnCircle)

Next

End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove

Dim strOut As String = "Not over circle"

For x As Integer = 0 To arShapes.Count - 1

If DirectCast(arShapes.Item(x), Region).IsVisible(e.X, e.Y) Then

strOut = String.Format("Over Circle {0}", x)

End If

Next

Me.Text = strOut

End Sub

Ken

----------------------

"Niels Jensen" <ni***@surf-spot.co.uk> wrote in message
news:6Z********************@pipex.net...
Hi,

Thanks for the help so far but I do have one further question - how do
you do it for multiple regions?

I've managed to apply the example you gave me to my program but I now
have another problem... there could be hundreds of Hexregions on the
form at any time - the problem is it's an unknown number of regions as
the person running the server can make a map of any size.

How can I take this to the next step and get the mousemove event to
cover an unknown number of regions on the form?

Niels

Ken Tucker [MVP] wrote:
Hi,
Create a region for each cell. Use the region isvisble to see if
the cursor is in the cell.

Dim rgnCircle As Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Dim pth As New System.Drawing.Drawing2D.GraphicsPath

pth.AddEllipse(100, 100, 50, 50)

rgnCircle = New Region(pth)

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

e.Graphics.FillRegion(Brushes.Blue, rgnCircle)

End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove

Me.Text = String.Format("In Circle {0}", rgnCircle.IsVisible(New
Point(e.X,
e.Y)))

End Sub

Ken

-------------------------------------

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote in message
news:9E**********************************@microsof t.com...
I have been developing a little project which draw's a hexgrid on a panel
within a form similar to this - it:s used as a client from a e-mail based
strategy game:
____ ____
/ \ / \
/ (0,0) \____/ (2,0) \____/
\ / \ / \
\____/(1,1) \____/ (3,1) \_
/ \ / \
/ (0,1) \____/ (2,1) \____/
\ / \ / \
\____/(1,2) \____/ (3,2) \_
/ \ / \
/ (0,2) \____/ (2,2) \____/
\ / \ / \
\____/(1,3) \____/ (3,3) \_

The number of hexes can vary depending on the mapsize. now the problem I
currently have is trying to get a label.text to display which hex coord
the
mouse is currently in.

Using the mouse move function I can get it to automatically change when it
passes over the lines in the (1,y) columns by using the following formula:

(for these purposes HexHeight = 44 pixels, HexWidth = 50 pixels)

MouseYpos = LocalMousePosition.Y / HexHeight
Label1.text = "Coords: " & MouseXpos & "," & MouseYpos

however, because the colums are staggered any column starting with an even
number get's the new coords changed halfway through it.

So I'm now leaning towards trying mark the centre point of each hex, and
then establishing which one the mousepointer is nearest to. However I'm
having difficulty in figuring out how to do this.

Can anyone help?

Nov 21 '05 #7
I'd just like to thank averyone who helped me out on this - I'm getting
there..... slowly and you've all been a great help holding my hand as I go

Thanks guys
Niels

"Larry Serflaten" wrote:

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote
Thanks for this code Larry it's *yet* another was that I can draw a hexmap...

Is there any chance you could be so kind and explain what the complicated
mathematical sections do (and how they do it?)


It is very easy to get X and Y coordinates when the cells are rectangles:
' Get red grid cell x and y
x = e.X \ SX
y = e.Y \ SY


SX and SY are the size values of the red cells, so that, dividing the
current X or Y mouse position by the size of the cell give the cell's
X or Y values.

It is not so easy when there are angled lines or other such polygons.
In your case, I first set out to identify where the angled lines are, you
can see by the displayed grid they do follow a repeating pattern and
that pattern is represented in the Rows array. Second, the angle the
slopes are at is constant so one formula (based on the ratio of X to Y)
can be used to tell when the mouse crosses the angled line. When it
does, the horizontal position has to be adjusted. There is one formula
for the forward slash, and another for the backward slash. With the
correct X position, there is one other thing to address and that is that
alternating hex columns are offset by one cell difference and that is
found and altered as the last part of the process.

I've been trying to figure
out how the 1st section works:
Rows(0) = New Integer() {-1, 0, 0, -2, 1, 1, -1}
Rows(1) = New Integer() {-2, 0, 0, -1, 1, 1, -2}


It is an array of arrays.

These statements assign arrays of Integers to the elements of the Rows
array. "New Integer()" tells VB you're creating a new array and the values
inside the brackets initialize that array with those values. In this case, a -1
represents the forward slash (angle cell) and -2 represents the backward
slash (angle cell). 0 and 1 were only used during the draw process to help
determine if the horizontal line of the hex cell should be at the top or
bottom of that group of cells.
I'm also drawing the hexcells in a panel, not a form and although I've
successfully managed to do this within my program using your code, the
graphics are only drawn within the initial visible part of the panel, as soon
as I use the scrollbars I get one of two things hapening. If the drawimage
is in the "paint" sub then it re-draws all over the screen eventually drawing
a nice big red block on the panel screen. how can I make your hexmap draw a
50hex by 50hex board and then maintain the image so that the scrollbars on
the panel display the image correctly. I'll be overlaying the Hexes that
have information with small .bmp graphical images such as trees or towns, the
idea being that the end user can click on a hex containing a town image and
get the information for the town.


You will probably want to back up that panel with a memory bitmap such that
you draw your 50X50 board to the bitmap, and then copy it over to the panel
(in its Paint event) depending on the scroll position.

While doing your drawing in the paint event is a low impact method, it gets a
bit useless when you have several items to draw and are erasing the screen to
reposition them all. In that case it is better to draw to memory and then copy
the finished image in one go.

Take a look at what I did, I gave the form a public Image property that was
my memory bitmap. It is such a common methodology that I did it by habit!
In the form's Paint event I simply copied over the image in one go. Doing it
that way (and even that can be improved) allows for automatic repainting when
the form is restored from being minimized, or when some other window covers
and then exposes that form.

Where I have 0, 0 you'd add in values from your scroll control....

HTH
LFS


Nov 21 '05 #8
Hi Ken,

I've almost got this sorted now - I have the regions all being drawn out in
a panel (around 100 for test purposes) and it looks good. however when I
scroll the panel using autoscroll

The regions vanish as I scroll down, I also noticed that no-matter where in
the panel I scroll to the regions are always in the same position on the
panel, i.e hex 1 is in the top left of the panel even though it should be hex
three due to scrolling approx three hexes down.

Is there any way for the regions to scroll around the panel properly and
also to make the correct regions be in the correct locations?

Cheers
Niels

"Ken Tucker [MVP]" wrote:
Hi,

Try something like this.

Dim arShapes As New ArrayList

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

For x As Integer = 0 To 4

Dim pth As New System.Drawing.Drawing2D.GraphicsPath

Dim rgnCircle As Region

pth.AddEllipse(100, 10 + x * 50, 50, 50)

rgnCircle = New Region(pth)

arShapes.Add(rgnCircle)

Next x

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

For Each rgnCircle As Region In arShapes

e.Graphics.FillRegion(Brushes.Blue, rgnCircle)

Next

End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove

Dim strOut As String = "Not over circle"

For x As Integer = 0 To arShapes.Count - 1

If DirectCast(arShapes.Item(x), Region).IsVisible(e.X, e.Y) Then

strOut = String.Format("Over Circle {0}", x)

End If

Next

Me.Text = strOut

End Sub

Ken

----------------------

"Niels Jensen" <ni***@surf-spot.co.uk> wrote in message
news:6Z********************@pipex.net...
Hi,

Thanks for the help so far but I do have one further question - how do
you do it for multiple regions?

I've managed to apply the example you gave me to my program but I now
have another problem... there could be hundreds of Hexregions on the
form at any time - the problem is it's an unknown number of regions as
the person running the server can make a map of any size.

How can I take this to the next step and get the mousemove event to
cover an unknown number of regions on the form?

Niels

Ken Tucker [MVP] wrote:
Hi,
Create a region for each cell. Use the region isvisble to see if
the cursor is in the cell.

Dim rgnCircle As Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Dim pth As New System.Drawing.Drawing2D.GraphicsPath

pth.AddEllipse(100, 100, 50, 50)

rgnCircle = New Region(pth)

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

e.Graphics.FillRegion(Brushes.Blue, rgnCircle)

End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove

Me.Text = String.Format("In Circle {0}", rgnCircle.IsVisible(New
Point(e.X,
e.Y)))

End Sub

Ken

-------------------------------------

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote in message
news:9E**********************************@microsof t.com...
I have been developing a little project which draw's a hexgrid on a panel
within a form similar to this - it:s used as a client from a e-mail based
strategy game:
____ ____
/ \ / \
/ (0,0) \____/ (2,0) \____/
\ / \ / \
\____/(1,1) \____/ (3,1) \_
/ \ / \
/ (0,1) \____/ (2,1) \____/
\ / \ / \
\____/(1,2) \____/ (3,2) \_
/ \ / \
/ (0,2) \____/ (2,2) \____/
\ / \ / \
\____/(1,3) \____/ (3,3) \_

The number of hexes can vary depending on the mapsize. now the problem I
currently have is trying to get a label.text to display which hex coord
the
mouse is currently in.

Using the mouse move function I can get it to automatically change when it
passes over the lines in the (1,y) columns by using the following formula:

(for these purposes HexHeight = 44 pixels, HexWidth = 50 pixels)

MouseYpos = LocalMousePosition.Y / HexHeight
Label1.text = "Coords: " & MouseXpos & "," & MouseYpos

however, because the colums are staggered any column starting with an even
number get's the new coords changed halfway through it.

So I'm now leaning towards trying mark the centre point of each hex, and
then establishing which one the mousepointer is nearest to. However I'm
having difficulty in figuring out how to do this.

Can anyone help?


Nov 21 '05 #9
Hi Larry,

I've been tinkering with the code you gave me as it needed expanding a little:
What I have is a panel which is 300x200 in size. The heximage that is drawn
is 50 by 50 hexes making it a lot larger than the panel so using a HScrollBar
& VScrollBar I calculate the position of those and move the image in the
panel to represent the display (see the code at the bottom of the form). Now
I have two issues whch I can't get my head round:

I have modified your original:

x = e.X \ SX
y = e.Y \ SY

to:

x = (e.X + HScrollBar1.Value) \ SX + (HScrollBar1.Value \ SX)
y = (e.Y + VScrollBar1.Value) \ SY + (VScrollBar1.Value \ SY)

this now gives a partially correct hex reading in even cells (0, 2, 3 etc)
but when I scroll down to reveal more hexes, as long as the top half of the
hex (the hex is divided by the two red rectangular cells) is at the top of
the panel, it's fine. As soon as the bottom half of the hex is displayed then
the hex number change occoured mid way through the next hex.does this make
sense?

It also doesn't seem to work on the angles, although I have a feeling that's
because I need to change the following somehow:

' Adjust for angled cells
If r = -1 Then
If (e.X - (x * SX)) < ((SY - (e.Y - (y * SY))) * RATIO) Then
hx -= 1
End If
'Debug.WriteLine((e.X - (x * SX)).ToString & " X " & (SY - (e.Y
- (y * SY))).ToString & " -Y " & ((SY - (e.Y - (y *
SY))) * RATIO).ToString)
ElseIf r = -2 Then
If (e.X - (x * SX)) < ((e.Y - (y * SY)) * RATIO) Then
hx -= 1
End If
'Debug.WriteLine((e.X - (x * SX)).ToString & " X " & (e.Y - (y *
SY)).ToString & " -Y " & ((e.Y - (y * SY)) *
RATIO).ToString)
End If

I need to get my head round some basic geomotry again - last time I did any
was around 12 years ago in high school (and I thought I was being clever
telling my teacher that I'd never need to know geometry in real life LOL)

Any advice you have would be great

Niels

"Larry Serflaten" wrote:

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote
Thanks for this code Larry it's *yet* another was that I can draw a hexmap...

Is there any chance you could be so kind and explain what the complicated
mathematical sections do (and how they do it?)


It is very easy to get X and Y coordinates when the cells are rectangles:
' Get red grid cell x and y
x = e.X \ SX
y = e.Y \ SY


SX and SY are the size values of the red cells, so that, dividing the
current X or Y mouse position by the size of the cell give the cell's
X or Y values.

It is not so easy when there are angled lines or other such polygons.
In your case, I first set out to identify where the angled lines are, you
can see by the displayed grid they do follow a repeating pattern and
that pattern is represented in the Rows array. Second, the angle the
slopes are at is constant so one formula (based on the ratio of X to Y)
can be used to tell when the mouse crosses the angled line. When it
does, the horizontal position has to be adjusted. There is one formula
for the forward slash, and another for the backward slash. With the
correct X position, there is one other thing to address and that is that
alternating hex columns are offset by one cell difference and that is
found and altered as the last part of the process.

I've been trying to figure
out how the 1st section works:
Rows(0) = New Integer() {-1, 0, 0, -2, 1, 1, -1}
Rows(1) = New Integer() {-2, 0, 0, -1, 1, 1, -2}


It is an array of arrays.

These statements assign arrays of Integers to the elements of the Rows
array. "New Integer()" tells VB you're creating a new array and the values
inside the brackets initialize that array with those values. In this case, a -1
represents the forward slash (angle cell) and -2 represents the backward
slash (angle cell). 0 and 1 were only used during the draw process to help
determine if the horizontal line of the hex cell should be at the top or
bottom of that group of cells.
I'm also drawing the hexcells in a panel, not a form and although I've
successfully managed to do this within my program using your code, the
graphics are only drawn within the initial visible part of the panel, as soon
as I use the scrollbars I get one of two things hapening. If the drawimage
is in the "paint" sub then it re-draws all over the screen eventually drawing
a nice big red block on the panel screen. how can I make your hexmap draw a
50hex by 50hex board and then maintain the image so that the scrollbars on
the panel display the image correctly. I'll be overlaying the Hexes that
have information with small .bmp graphical images such as trees or towns, the
idea being that the end user can click on a hex containing a town image and
get the information for the town.


You will probably want to back up that panel with a memory bitmap such that
you draw your 50X50 board to the bitmap, and then copy it over to the panel
(in its Paint event) depending on the scroll position.

While doing your drawing in the paint event is a low impact method, it gets a
bit useless when you have several items to draw and are erasing the screen to
reposition them all. In that case it is better to draw to memory and then copy
the finished image in one go.

Take a look at what I did, I gave the form a public Image property that was
my memory bitmap. It is such a common methodology that I did it by habit!
In the form's Paint event I simply copied over the image in one go. Doing it
that way (and even that can be improved) allows for automatic repainting when
the form is restored from being minimized, or when some other window covers
and then exposes that form.

Where I have 0, 0 you'd add in values from your scroll control....

HTH
LFS


Nov 21 '05 #10

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote

I have modified your original:

x = e.X \ SX
y = e.Y \ SY

to:

x = (e.X + HScrollBar1.Value) \ SX + (HScrollBar1.Value \ SX)
y = (e.Y + VScrollBar1.Value) \ SY + (VScrollBar1.Value \ SY) ..... It also doesn't seem to work on the angles, although I have a feeling that's
because I need to change the following somehow: ..... Any advice you have would be great

I haven't tested anything using a scrollbar, but as you saw, it works out
when the proper X and Y values are used. I am not sure why you used
the new formula but I would suggest you alter the whole routine to first
get the composite values of e.X and e.Y and use those in place of e.X and
e.Y.

First I am assuming that with a Vscroll value of 0, then clicking on 0,0, will
give you the correct 0,0 result, and when the Vscroll value is 10, then clicking
on 0,0 should actually be 0,10. (opposed to using any negative values) Likewise
when the VScroll value is 20 and you click on 0,0 you actually need it to be 0,20
(because the hex grid has been drawn 20 pixels higher than its original position)

Do you see the pattern?

So the first thing to do is to get the X and Y values back to their needed values,
then let the rest of the routine work, something like:

Dim eX, eY as Integer

eX = e.X - HScrollBar1.Value
eY = e.Y - VScrollBar1.Value

After that, replace every occurance of e.X with eX and every occurance of
e.Y with eY:

x = eX \ SX
y = eY \ SY

And do the same with the later formulas then see if things start to turn out
right again.

HTH
LFS
Nov 21 '05 #11
OMG!

Larry your a genius and a star! Thanks it worked a treat and just goes to
show simplicity is the key. I had a friend a I trying out some weird
mathamatical formulas trying to do the simple thing you explained :p

Ahh well - Thanks again!

Niels

"Larry Serflaten" wrote:

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote

I have modified your original:

x = e.X \ SX
y = e.Y \ SY

to:

x = (e.X + HScrollBar1.Value) \ SX + (HScrollBar1.Value \ SX)
y = (e.Y + VScrollBar1.Value) \ SY + (VScrollBar1.Value \ SY)

.....
It also doesn't seem to work on the angles, although I have a feeling that's
because I need to change the following somehow:

.....
Any advice you have would be great

I haven't tested anything using a scrollbar, but as you saw, it works out
when the proper X and Y values are used. I am not sure why you used
the new formula but I would suggest you alter the whole routine to first
get the composite values of e.X and e.Y and use those in place of e.X and
e.Y.

First I am assuming that with a Vscroll value of 0, then clicking on 0,0, will
give you the correct 0,0 result, and when the Vscroll value is 10, then clicking
on 0,0 should actually be 0,10. (opposed to using any negative values) Likewise
when the VScroll value is 20 and you click on 0,0 you actually need it to be 0,20
(because the hex grid has been drawn 20 pixels higher than its original position)

Do you see the pattern?

So the first thing to do is to get the X and Y values back to their needed values,
then let the rest of the routine work, something like:

Dim eX, eY as Integer

eX = e.X - HScrollBar1.Value
eY = e.Y - VScrollBar1.Value

After that, replace every occurance of e.X with eX and every occurance of
e.Y with eY:

x = eX \ SX
y = eY \ SY

And do the same with the later formulas then see if things start to turn out
right again.

HTH
LFS

Nov 21 '05 #12
Ghaaa! Larry Please save me again!

I just realised that the hex cells run down in even and odd numbers
depending on the column.

i.e if X = 0, 2, 4... then all Y's cell Values will be even 0,2,4...
if X = 1, 3, 5... then all X's cell values will be odd

I'm looking at the code, and I just cant work out what needs to be done to
make the X/Y valuse read right.

have you got any pointers?

Cheers
Niels

"Niels Jensen" wrote:
OMG!

Larry your a genius and a star! Thanks it worked a treat and just goes to
show simplicity is the key. I had a friend a I trying out some weird
mathamatical formulas trying to do the simple thing you explained :p

Ahh well - Thanks again!

Niels

"Larry Serflaten" wrote:

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote

I have modified your original:

x = e.X \ SX
y = e.Y \ SY

to:

x = (e.X + HScrollBar1.Value) \ SX + (HScrollBar1.Value \ SX)
y = (e.Y + VScrollBar1.Value) \ SY + (VScrollBar1.Value \ SY)

.....
It also doesn't seem to work on the angles, although I have a feeling that's
because I need to change the following somehow:

.....
Any advice you have would be great

I haven't tested anything using a scrollbar, but as you saw, it works out
when the proper X and Y values are used. I am not sure why you used
the new formula but I would suggest you alter the whole routine to first
get the composite values of e.X and e.Y and use those in place of e.X and
e.Y.

First I am assuming that with a Vscroll value of 0, then clicking on 0,0, will
give you the correct 0,0 result, and when the Vscroll value is 10, then clicking
on 0,0 should actually be 0,10. (opposed to using any negative values) Likewise
when the VScroll value is 20 and you click on 0,0 you actually need it to be 0,20
(because the hex grid has been drawn 20 pixels higher than its original position)

Do you see the pattern?

So the first thing to do is to get the X and Y values back to their needed values,
then let the rest of the routine work, something like:

Dim eX, eY as Integer

eX = e.X - HScrollBar1.Value
eY = e.Y - VScrollBar1.Value

After that, replace every occurance of e.X with eX and every occurance of
e.Y with eY:

x = eX \ SX
y = eY \ SY

And do the same with the later formulas then see if things start to turn out
right again.

HTH
LFS

Nov 21 '05 #13

"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote
I just realised that the hex cells run down in even and odd numbers
depending on the column.

i.e if X = 0, 2, 4... then all Y's cell Values will be even 0,2,4...
if X = 1, 3, 5... then all X's cell values will be odd

I'm looking at the code, and I just cant work out what needs to be done to
make the X/Y valuse read right.

have you got any pointers?

I don't understand the problem, can you explain it be little better?

LFS
Nov 21 '05 #14
Sure,

At the moment if you go into the top left hex cell it'll read X = 0 Y =
0. If you go down to the next it'll read X = 0, Y = 1, the next will be
X = 0 Y = 2 etc.

What I should have realized is that it should be X= 0, y = 0 x = 0, y
= 2 x = 0, y = 4 etc

and on the odd X values i.e x = 1 it should be x = 1, y = 1. X = 1 Y = 3
etc.

I can't believe how helpful you've been so far, I really would be at a
loss without you help and for that I'm very grateful. Thanks

Niels
Larry Serflaten wrote:
"Niels Jensen" <Ni*********@discussions.microsoft.com> wrote

I just realised that the hex cells run down in even and odd numbers
depending on the column.

i.e if X = 0, 2, 4... then all Y's cell Values will be even 0,2,4...
if X = 1, 3, 5... then all X's cell values will be odd

I'm looking at the code, and I just cant work out what needs to be done to
make the X/Y valuse read right.

have you got any pointers?


I don't understand the problem, can you explain it be little better?

LFS

Nov 21 '05 #15

"Niels Jensen" <ni***@surf-spot.co.uk> wrote
I can't believe how helpful you've been so far, I really would be at a
loss without you help and for that I'm very grateful. Thanks


Just to be clear, see if the list below is correct

OldX OldY NewX NewY
0 0 0 0
0 1 0 2
0 2 0 4
0 3 0 6
0 4 0 8
1 0 1 1
1 1 1 3
1 2 1 5
1 3 1 7
1 4 1 9
If that is it, there is definately a pattern there:

NewX = OldX
NewY = (OldY * 2) + (OldX And 1)

Since the routine correctly outputs the X and Y,
just tack on the formula to adjust Y as the last line
of the routine....
LFS
Nov 21 '05 #16
Yup - worked a treat... Once again :)

Thanks for your help Larry, I'll make sure you're credited in my app :)

Niels

"Larry Serflaten" wrote:

"Niels Jensen" <ni***@surf-spot.co.uk> wrote
I can't believe how helpful you've been so far, I really would be at a
loss without you help and for that I'm very grateful. Thanks


Just to be clear, see if the list below is correct

OldX OldY NewX NewY
0 0 0 0
0 1 0 2
0 2 0 4
0 3 0 6
0 4 0 8
1 0 1 1
1 1 1 3
1 2 1 5
1 3 1 7
1 4 1 9
If that is it, there is definately a pattern there:

NewX = OldX
NewY = (OldY * 2) + (OldX And 1)

Since the routine correctly outputs the X and Y,
just tack on the formula to adjust Y as the last line
of the routine....
LFS

Nov 21 '05 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Csaba2000 | last post by:
I have set onmousedown to change the cursor, but this setting is ignored (IE 5.5; NN 6.1 on Win 2K Pro) until the mouse is either moved or the mouse button is released. On Opera 7.01, the setting...
2
by: KarenP | last post by:
In my Windows Forms application, while executing a process that takes some time, I am changing the cursor to the hourglass by setting Cursor.Current = Cursors.WaitCursor. This is working just...
1
by: objectref | last post by:
Hi to all, we have the MousePosition property that we can get the Point of the position of the mouse cursor on the screen, but is it there a way to get the respective Point of a cursor in a...
9
by: DotNetShadow | last post by:
Hi Guys, I have been having this problem recently where I have a form with a textbox and button, if in the button event I have the following: Private Sub Button1_Click(ByVal sender As...
6
by: Martin Heuckeroth | last post by:
Hi, We are looking for a way to determine the x and y points of the cursor in a richtext box. We made an VB.NET application with a couple of listboxes and one of them is a richtextlistbox....
3
by: Klaus Brune | last post by:
Hello all, When one tabs through a form (specifically, in Firefox), all the text in a field is automatically selected. What I'm looking for is a way to put a function (in onFocus perhaps)...
4
by: mike | last post by:
I have the opportunity to rescue a project that uses a mouse to sense the relative position of a machine. The hardware is built...just needs to be programmed. Stop snickering!!! I didn't do it...I...
2
by: Mohit | last post by:
Hi all, I am working on a windows application with a list view on a form. Now I wanted to show hand cursor when mouse is over list view item and default(arrow) cursor at other places. List...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.