Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Drawing Custom Buttons

Status
Not open for further replies.

splaisance

Programmer
Jul 2, 2001
67
US
I am having a problem drawing custom button shapes at specified locations in my application. The app has a grid of 24 concentric circles. Then a set of rectangles (or button shapes) are to be drawn onto this grid but they need to be drawn at an angle. Here is the code I am using in the paint event:


oG.TranslateTransform(pnlGrid.Width / 2, pnlGrid.Height / 2)

*For Each wABtn In clsBtn
'Move the origin to the bottom right corner of button
oG.TranslateTransform(wABtn.gSize.Width, wABtn.gSize.Height)

'Rotate the graphics by mydegrees
oG.RotateTransform(45)

'Get a fresh array of original corner points of button
* pts = wABtn.gPts

'Transform array to match transformation done on graphics object
* oG.TransformPoints(CoordinateSpace.Page, CoordinateSpace.World, pts)

'Update bounds of button w/newly transformed corner(points)
* wABtn.gBounds = New GraphicsPath(pts,mRectanglePathPoints)

'Close the bounding rectangle
* wABtn.gBounds.CloseAllFigures()

'Use ControlPaint to render 3D button image w/ state
*ControlPaint.DrawButton(oG, myRect.X, myRect.Y, hldWidth, hldHeight, wABtn.State)
*Next

'Reset transformation so drawing resumes on normal coordinate space
*oG.ResetTransform()

'Draw bounds of each button
* For i As Integer = 0 To (clsBtn.Count - 1)
* oG.DrawPath(Pens.Aqua, clsBtn.Item(i).gBounds)
* Next

Definitions at top of form are:
Private mRectanglePathPoints As Byte() = New Byte() {PathPointType.Start, PathPointType.Line, PathPointType.Line, PathPointType.Line}

Dim clsBtn As ArrayList
Private oG As Graphics
Dim wABtn As myButton

Where myButton is a class which determines each item's location, size, button pressed state, bounds (which is defined as a GraphicsPath), and other data.

When I only have the statements which are starred (*) run then I get the correct button outline, but the buttons are drawn 'regular' as in to say not on an angle or anything. Yet when I use all of the above code, neither the outlines nor the buttons are in the correct places.

Can anyone help me figure out what is going wrong?

 
There are both - multiple jobs per ring and multiple buttons spread out on grid which represent different jobs
 
Pretend my drawings are round:
Each dashed line represents a ring
Which Drawing is closest to what you are trying to do?
Or draw your own "ring"

Each drawing gets it's own ring. No other "things" to do.
-------------------
Job1 - 1hr
-------------------
Job2 - 2hrs
-------------------
Job2 - 2hrs
-------------------
Job3 - 30 mins
-------------------
Job4 - 30 mins

Each drawing gets it's own ring, have "other" things to do with the job
---------------------------------
Job1 - 1hr| Do Stuff1 | Do Stuff2
---------------------------------
Job2 - 2hrs| Do Stuff1 | Do Stuff2
---------------------------------
Job2 - 2hrs| Do Stuff1 | Do Stuff2
---------------------------------
Job3 - 30 mins| Do Stuff1 | Do Stuff2
---------------------------------
Job4 - 30 mins| Do Stuff1 | Do Stuff2

Each "hour" gets its own ring, and multiple jobs may fill the ring, or a job may span multiple rings. No other "stuff" to do
---------------------------------
Job1 - 1hr
---------------------------------
Job2 - 2hrs
---------------------------------
Job2 - 2hrs
---------------------------------
Job3 - 30 mins| Job4 - 30 mins

Each hour gets its own ring. Jobs have other stuff to do
---------------------------------
Job1 - 1hr| Do Stuff1 | Do Stuff2
---------------------------------
Job2 - 2hrs| Do Stuff1 | Do Stuff2
---------------------------------
Job2 - 2hrs| Do Stuff1 | Do Stuff2
---------------------------------
Job3 - 30 mins| Do Stuff1 | Do Stuff2| Job4 - 30 mins| Do Stuff1 | Do Stuff2



-The answer to your problem may not be the answer to your question.
 
The "jobs" or buttons represent a job or activity that is planned to happen - they aren't going to actually cause the job to happen tho. This is kinda a planning tool.
Using your example then it would be more like this:

---------
Hour 1 :(no job perhaps)
----------
Hour 2: job 1 starts (1 hr long)
-----------
Hour 3: job 2 starts (3 hr long), in another "degree" of circle job 3 starts (2 hr long)
-----------
Hour 4: still shows job2 and job 3, in a 3rd "degree" of circle job 4 starts (4 hr long)
------------
Hour 5: still shows job2, and job 4
------------
Hour 6: still shows job 4
--------------
Hour 7: still shows job 4


This is assuming the same you did w/each dash being a circle outline. Does that at least explain what I'm going for better?


------------
 
yes. That was actually my initial take on the deal. are the rings supposed to expand to hold more jobs or do the rings get "segmented", with a segment for each job?

so is it like:
(segmented ring)
--------------
Job 1 | Job 2
--------------

or
(Thicker ring)
--------------
Job 1
Job 2
--------------

Back to the original question.

Are you having problems with the location or rotation of the button(s)? is it a problem with the first or second button for a ring?


Side note? Why aren't you just using MS Project?

-The answer to your problem may not be the answer to your question.
 
Well I finally got the buttons to draw on the grid in the proper locations initially but am now having a little trouble when one is moved. It is not always calculating the correct new hour location.

b/c the information will constantly vary depending on data in a database and user input. Plus there will be other information displayed and linked to this grid.

The rings are all the same width apart - if a ring has more than one job in it then it is shown at a different angle - ie: job 1 at angle 30 degrees, job 2 at angle 50 degrees, etc.
 
So is it not putting in:
the right hour ring?
or
the correct angle?

I am assuming you are using the mouseUp location, to store the X,Y position.

How are you calculating which ring to put the job in?
Are you using some form of center and radius length calculation to determine which ring to put it in? or are you using a mouseEnter on the ring itself to throw some kind of flag saying "drop it on me"

-The answer to your problem may not be the answer to your question.
 
It is not putting it in the correct hour ring. Since the circles are created by using drawellipse I am using a calculation. I find the distance from the centerpoint of the circle grid to my new location point clicked.

wrkX = cPt.X - button.Location.X
wrkY = cPt.Y - button.Location.Y
wrkPt2 = New Point(wrkX, wrkY)
wrkRadius = Sqrt((wrkPt2.X ^ 2) + (wrkPt2.Y ^ 2))

Where cPt.x and cPt.y is the center x,y. The button's location is continuously updated as you move it in the mousemove event. This part is in the mouseup event.

Once I have the distance out from the center point that I have moved the button to, I compare it to the saved circle radis and see if I find the right one:

For Each wCircle In clsCircles
With wCircle
cirRect = New Rectangle(.gcX, .gcY, .gcWidth, .gcHeight)
If (.gcRadiusB <= wrkRadius) Then
' yes the point is found in this rectangle/circle hour!
j = .gcHr
isCirFound = True
Exit For
End If
End With
Next

The circles are created from the largest hour/outermost circle first down to the smallest hour/innermost hour. This was so I could have every other circle shaded a different color.
 
I think you are going in the wrong direction(literally), with your comparision.

Each ring will have an inner and an outer radii distance.
You need to find the circle where the mouse radius falls between the inner and outer radii.
Think aboout creating a temp circle with the center at the center and the edge touching the mouse pointer

Try putting all your radii (inner and outer) sizes in a collection/array/(whatever)
and checking your distance, from center to mouse is between
Code:
Public Struct myRing
   Dim intRadiusInner, intRadiusOuter as Integer
   Dim intRingNum as Integer
End Struct

Function FindRing(intMouseRadius as Integer) As Integer
   For each oRing as myRing in oAllTheRings
      If intMouseRadius < oRing.intRadiusOuter And _
         intMouseRadius > oRing.intRadiusInner Then
         Return oRing.intRingNumber
      End If
   Next
End Function



-The answer to your problem may not be the answer to your question.
 
I am doing that although not in the exact way you are showing. When I create the circles initially I am holding the circle information in an arraylist which has the circle's radius. By comparing the circle's radius to the calculated radius of my new point from the outside circle down to the innermost circle it basically does the same thing as you are saying. Or that is how I am understanding what you said.

I believe it has something to do w/the fact that I am creating a custom button shape which is what the user is moving. Yet, the button is still a regular rectangle - just not all of it is seen - only the angled part I set the bounds to is seen. I think the top/left of the actual rectangle is probably hitting the wrong circle hour. The only problem is I haven't been able to figure out the correct offset between where the mouse is being clicked in the button and it's top/left location to adjust for this. Any suggestions on this?
 
When you click on a control you get the X,Y relative, to the TOP LEFT of the control.
You don't need the TOP LEFT per se, you need the center point.

Given button:
-------------------
| |
| |
-------------------

and a click:
-------------------
|X |
| |
-------------------

Then your x,y is 1,1
if the control is at 10, 10 on the form
and the form is at 100, 100 on the screen
then your mouse is/was at 111,111

Now you need to figure out which ring 111,111 falls into.

I will try messing with this tonight. I have some label moving code.

-The answer to your problem may not be the answer to your question.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top