Hexagon-shaped image or picture boxes?

I am attempting to create a tile-based strategy game and would like the be able to create map tiles in hexagon shapes rather than squares.  Is there any way to create a control array of hexagon shaped tiles all interlocked together on a form?  Each tile must have different values (visible if explored, description, etc.).  Can this be done with one big map picture and creating multiple hotspots, or do I still have to go with individual hexagon-shaped image boxes?  Be explicit with your info as I am a dummy...I will award more than 200 points if I get something that works well.  Thanks so much.  --Vingamel  
Who is Participating?
MirkwoodConnect With a Mentor Commented:
OKE, Here is the complete code.
What do you need to do.
1) Create a new user control
2) Add this code to this usercontrol
3) Create a form
4) Add instances usercontrol to the form

What does the code do
1) Create a control that has the shape of a hexagon
2) Control has property backcolor
3) Control shows msgbox with name when clicked upon

How does it work:
1) On resize the usercontrol is made a square
2) On resize is creates a new window shape using the polygon region functions.

Private Declare Function CreatePolygonRgn Lib "gdi32" (lpPoint As POINTAPI, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long
Private Type POINTAPI
        x As Long
        y As Long
End Type

Private Declare Function SetWindowRgn Lib "user32" _
        (ByVal hWnd As Long, ByVal hRgn As Long, _
        ByVal bRedraw As Boolean) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long

Dim hRegion As Long

Public Property Get BackColor() As OLE_COLOR
    BackColor = UserControl.BackColor
End Property

Public Property Let BackColor(ByVal newvalue As OLE_COLOR)
    UserControl.BackColor = newvalue
End Property

Private Sub UserControl_Click()
    'Display name
    MsgBox Ambient.DisplayName
End Sub

Private Sub UserControl_Resize()
        'Make square
        If (Width > Height) Then Width = Height
        If (Height > Width) Then Height = Width
        'Create polygon
        Dim points(5) As POINTAPI
        points(0).x = (ScaleWidth / 2 + ScaleLeft) / Screen.TwipsPerPixelX
        points(0).y = ScaleTop / Screen.TwipsPerPixelY
        'Right top
        points(1).x = (ScaleLeft + ScaleWidth) / Screen.TwipsPerPixelX
        points(1).y = (ScaleHeight / 3 + ScaleTop) / Screen.TwipsPerPixelY
        'right bottom
        points(2).x = points(1).x
        points(2).y = (2 * ScaleHeight / 3 + ScaleTop) / Screen.TwipsPerPixelY
        points(3).x = points(0).x
        points(3).y = (ScaleTop + ScaleHeight) / Screen.TwipsPerPixelY
        'Right top
        points(4).x = ScaleLeft / Screen.TwipsPerPixelX
        points(4).y = points(2).y
        'right bottom
        points(5).x = points(4).x
        points(5).y = points(1).y
        'Delete region
        If (hRegion <> 0) Then DeleteObject hRegion
'        hRegion = CreateEllipticRgn(ScaleLeft / Screen.TwipsPerPixelX, ScaleTop / Screen.TwipsPerPixelY, (ScaleLeft + ScaleWidth) / Screen.TwipsPerPixelX, (ScaleTop + ScaleHeight) / Screen.TwipsPerPixelY)
        'Change window size to a region
        hRegion = CreatePolygonRgn(points(0), 6, 2)
        'Make region active region
        SetWindowRgn hWnd, hRegion, True
End Sub

Private Sub UserControl_Terminate()
        'Destroy region
        If (hRegion <> 0) Then DeleteObject hRegion
        hRegion = 0
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    BackColor = PropBag.ReadProperty("BackColor", &H8080FF)
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    PropBag.WriteProperty "BackColor", BackColor, &H8080FF
End Sub

You'll probably have to go with individual imageboxes. I'll try to scrape togeather a solution for you. BTW, do you have a control for hexagon-shaped imageboxes or do you need that too?
This might help you. This shows how to change shape of a form. You can do similar things for a control.


Private Declare Function CreateEllipticRgn Lib "gdi32" _
        (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, _
        ByVal Y2 As Long) As Long

Private Declare Function SetWindowRgn Lib "user32" _
        (ByVal hWnd As Long, ByVal hRgn As Long, _
        ByVal bRedraw As Boolean) As Long

Private Sub Form_Load()
       Show 'The form!
       SetWindowRgn hWnd, CreateEllipticRgn(0, 0, 300, 200), True
End Sub
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

VingamelAuthor Commented:
To Skiprosebaugh: Kinda what I figured is that I will need individual image boxes...re: Hex-shaped image-boxes, I do need the code for that if you can provide that.

To Mirkwood: With your code above, do I just plop this into a module and it takes off?...like I said, I need explicit info on this stuff.  I will try this tonight and see how it goes.  Thanks.  Still dumb, but still learning.--Vingamel
VingamelAuthor Commented:
I increased the point value for this question because I want explicit instructions--not just code--on how to do this.  Assume I a beginner, because I am.  I have bumped in API stuff before, but I plop it into code boxes and hit run, and walla, nothin' happens.  See, I need to know the whole smorgasbord here.  Thanks a gob.  --Vingamel
BTW, the old example also worked, you should have tried harder. For example click on it or change the background color.
VingamelAuthor Commented:
Thanks, Mirkwood, for all your help.  I will work with this and see what I come up with.  I will take your word that it works and not make you wait until I test it out.  --Vingamel
I saw the question and I was looking for a simple answer.
There are many answers to your questions,and they vary from to a simple one to very complex.
I'm gonna show you a method (no API involved) .Please follow the indications step by step,VERY carefully:

1-You will need a bitmap with 100x100 pixels size by example with a black background and a white hexagon
Please be careful :Black (0,0,0) and white (255,255,255) .Save it like Hexagon.bmp

Next,you need an other bitmap,that you will use like texture.By example,clouds.bmp .
(I think there's a bitmap in the windows directory with that name)

1-Start VB ,New Project,Select ActiveX Control
 A UserControl form appear in the project.The UserControl it's a kind of form,that you can use for develop
visual controls.

2-Select UserControl properties (F4) and set:
MaskPicture=Here you must load the bitmap that you built (the hexagon one)
Picture=Here you must load the clouds.bmp o the bitmap what you want.

2-Select a control label and put on the form
Select Label's properties and set:
BackStyle=Transparent (this is VERY important,don't forget it)
Caption=Whatever you want
Try to put the label in the upper left corner of the UserControl form.
You don't have to worry about the position,we solve that later.

If everything goes right,you will see a single form with a bitmap that you select.You won't see the hexagon...yet

3-add this code.It will set the form size,and we'll add some events and properties
Drop this code in the usercontrol :
Option Explicit
Dim PicSelected$
Event Click() 'Activate the Click Event
Event DblClick() 'Activate de DblClick Event

Private Sub UserControl_Resize() 'Set Size constant (100 is the size of the bitmap mask)
   Size 100 * Screen.TwipsPerPixelX, 100 * Screen.TwipsPerPixelY
End Sub

Private Sub UserControl_Click() 'Enable Click
   RaiseEvent Click
End Sub

Private Sub usercontrol_dblclick() 'enable DblClick
   RaiseEvent DblClick
End Sub

'Establish a property to change the bitmap
Public Property Let PicturePath(ByVal P As String) 'Select Picture
On Error GoTo Perror
PicSelected = P 'Remember the picture selected
UserControl.Picture = LoadPicture(PicSelected) 'Load the picture
PropertyChanged "PicturePath" 'Alert for changes
Exit Property
MsgBox "Error " & Err.Number & " " & Err.Description 'Error if you give a wrong picture path
End Property

Public Property Get PicturePath() As String
End Property

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
 PropBag.WriteProperty "PicturePath", PicSelected, "" 
End Sub

4-Select File ,Add project and select Standard EXE, open it
In the project explorer,you will see two projects:Project1 with UserControl form and Project2 with
a standard Form1.
Open the Project Explorer
Select the UserControl form in the project explorer ,double click it,and close it(clicking in X) ,so we only see the Form1.

5-Select ToolBox
You will see a new control:It's like a Square 4-divided with a pencil.That is your control.
Go with the mouse and move it over  (don't select it) .it will display a UserControl1 tooltip.
(if the control is gray you cannot use it ; it's beacuse the UserControl Form window is open;you must close it and you will see
the control in color)

6-Select the UserControl1 control from the ToolBox  and drop it in the form.If everything goes ok,you will see the hexagon
and the label. You can drop many UserControl1 in the form.

You can select a different bitmap in every hexagon,with the PictureGraph property.

7-Go to the UserControl form and try to center the label into the hexagon.Yep it's a little difficult because you cannot see
the hexagon.

I think this is the simplest way that I know.It has many problems:
1-It would be desiderable that you can change the hexagon size ,in design time.In this example the hexagon size
depends on a bitmap,so you must change the MaskBitmap to accomplish it.(Baaaaad)
2-Note that this is a very single solution.
Better solution would include more properties (like hexagon size,rotation,more events,etc.) but you will need to know
about Classes,API calls ,and another things.

3- you can compile the example and generate a OCX.Select de UserControl and then File,Compile UserControl.OCX
(save it in Windows\System\)
Later,for use in other project,you have to include the OCX,using Project components and selecting de OCX

Maybe this example helps you

Good Luck
If you have problems or questions, tell me. Please also tell me if it works OK. That makes me feel good :-)
VingamelAuthor Commented:
To Mirkwood & Eklipse:
I already gave Mirkwood the 300 points, but I see that Eklipse has given me another option as well.  Eklipse...thanks so much for the second opinion, and I apologize that I was unable to get your resolution before shooting the points over to Mirkwood.  If your fix is better than Mirkwood's, I should like to compensate you some how for your time.  Thanks to both of you for your expert help!!!
Well ,I hope this things help you and let's you know what happened.

Happy christmas

VingamelAuthor Commented:
Eklipse: Your solution worked well...also gave me some other ideas for aspects of project I am working on.  Thanks very much, and Merry Christmas to you.  --Vingamel
VingamelAuthor Commented:
Mirkwood: Your solution gave me a hexagon (with unequal sides).  Curious if hexagon can contain various bitmaps so that each hex has its own unique terrain?  Anyway, you've helped me considerably and I thank you.  Merry Christmas.  --Vingamel
Yes, just set the picture property of the usercontrol and see what happens.
Now, make the picture property a property of your control.

VingamelAuthor Commented:
Mirkwood: Very cool...and I supposer there is a way to fix the shape of the hex so that the sides are equal, and then plop them down on a form (see the original question above).  Thank ya very much.  --Vingamel  

Eklipse: Although your solution gave me a hex, trying to interconnect several onto a form is strange because we actually dealing with squares with invisible corners...so a user could think he was clicking on hex one, but actually click on the invisible corner of the neighboring hex...or am I not seeing something here.  Thanks so much.  --Vingamel
Sure just change position of  points.
VingamelAuthor Commented:
Thanks so much...I should be able do okay now and not bother you any more.  Until my next 300 point question, see ya.  --Vingamel
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.