Xtreme Visual Basic Talk

Xtreme Visual Basic Talk (http://www.xtremevbtalk.com/)
-   Interface and Graphics (http://www.xtremevbtalk.com/interface-and-graphics/)
-   -   How to get a Perfect Square Shape (http://www.xtremevbtalk.com/interface-and-graphics/328566-perfect-square-shape.html)

abeginner 02-03-2017 11:26 PM

How to get a Perfect Square Shape
 
2 Attachment(s)
First of all ITS GOOD TO BE BACK.

I have a problem trying to draw a perfect square using the Shape control in VB6. I have been playing around with a program to draw various shapes. I need to draw a Perfect Square Shape so that I can then form an Equilateral Triangle using it, but the shape control seems to default to a rectangle instead of a perfect square.

Also what sort of picture box can be used to improve the picture quality (antialias lines)?

Lastly, once each picture is drawn what can be done to move it to a slightly different position (I played around with Robert Raymond's advanced graphics programs on PlanetVB, where a shape can be drawn, moved and rotated but could not understand the code (i think he used some sort of buffer?)). Sorry about all the questions, but I'd really like to learn about this graphics stuff.

Thanks in Advance. Eddie

Here is a screen shot and the code:

passel 02-06-2017 03:07 PM

Quote:

Originally Posted by abeginner (Post 1410655)
... I need to draw a Perfect Square Shape so that I can then form an Equilateral Triangle using it, but the shape control seems to default to a rectangle instead of a perfect square. ...

What do you base that on?
An equilateral triangle where the base is one side of a square, the corner opposite of the base will not touch the edge of the opposite side of the square.
The height of an equilateral triangle is equal to Sin(60) * the base.
Think about it.
Start with three lines that are three sides of a square so are equal length.
Now tilt the left and right sides toward the center, each rotating 60 degrees to meet in the center. The tops of those lines will meet about 86.6 percent of the way up from the center of the base.

Also, in your code you're not even using the corners of the square shape you created, but are using the X,Y mouse position that the user dragged to, so your equilateral triangle isn't using the square in any case.

p.s. I played around further with the code, and I think I see where you're coming from. One thing to note is you have the scalemode set to User so there is the chance the pixels are not square units, but the main issue is that setting "OutlineRectangle.Shape = 1" to make the shape a square doesn't make the rectangle square, it just draws the largest square that will fit, centered within the bounds of the rectangle defined.
It is the same idea if you selected a circle shape. It doesn't make the rectangle defining the bounds of the shape into a circle, it just draws the largest circle that will fit, centered, within those bounds.

So, you probably want to do the same thing, essentially, except you may want the top of the triangle to always touch the top of the rectangle, rather than be centered within the bounds of the rectangle.
An example would be to determine the shortest side of the rectangle and use that for your base. Your centerX calculation would stay the same, and the top Y.
You would use the shortest side as the length of your triangle sides, so set the left and right offsets from center to 1/2 that length.
Your bottom Y value would be the Top + .866 * that length.
Code:

  If OptionEquil.Value = True Then
 
  'OutlineRectangle.Shape = 1 ' A square  'doesn't help, so not needed
 
    If initialX <> 0 And initialY <> 0 Then
      Dim legLength As Single
      Dim leftSide As Single, rightSide As Single, centerX As Single, BottomY As Single

      With OutlineRectangle
        'Choose the shortest side of the rectangle for the triangle side length
        If .Width < .Height Then 
          legLength = .Width     
        Else
          legLength = .Height
        End If
       
        centerX = .Left + .Width / 2
        leftSide = centerX - legLength / 2
        rightSide = centerX + legLength / 2
        BottomY = .Top + legLength * 0.866
       
        Picture1DrawCanvas.Line (centerX, .Top)-(rightSide, BottomY) 'centerTop to bottom right
        Picture1DrawCanvas.Line -(leftSide, BottomY)                'continue to bottom left
        Picture1DrawCanvas.Line -(centerX, .Top)                    'continue back to centerTop
      End With
    End If
  End If

Quote:

Originally Posted by abeginner (Post 1410655)
Also what sort of picture box can be used to improve the picture quality (antialias lines)?

I don't know of a user control that has been built that has antialising built in, but there may be some out there that will probably cost you money.
You could use GDI+, but that is some additional work, and someone like mms would probably be the most familiar with it. I have no experience with it and VB6. I don't know if there is a GDI available API call that will do it (didn't look, so there may be).
Quote:

Originally Posted by abeginner (Post 1410655)
Lastly, once each picture is drawn what can be done to move it to a slightly different position

If you're going to want to move or modify the shapes you're drawing, then you will have to save the information used to draw the shapes.
Right now you just draw the shape on an AutoRedraw buffer and have no memory of how you drew it after it is drawn. Since you have no way to redraw the shape, you have no way to make any modifications to it.

You will need to create a type, or a class to hold information about a shape, and then an array or collection of some sort to maintain those objects.
Then there is the matter of determining which shape you want to modify, and how to designate what modifications you want to do. Can be even more challenging if you allow shapes to overlap.

mms 02-07-2017 01:13 PM

Antialiasing is easy with GDI+ (one line of code)

Following is complete code for sample project.
Copy/Paste into your project and add 1 PictureBox and 2 CommandButtons

Form Code
Code:

Option Explicit


Dim stat As Long
Dim gdiplusToken As Long


Private Sub Form_Load()

    Form1.Caption = "GDI+"
    Form1.width = Screen.TwipsPerPixelX * 600
    Form1.height = Screen.TwipsPerPixelY * 465
    Form1.ScaleMode = vbPixels

    Picture1.Appearance = 0
    Picture1.Left = 20
    Picture1.Top = 20
    Picture1.height = Form1.ScaleHeight - Command1.height - 40 - 20
    Picture1.width = Form1.ScaleWidth - 40
    Picture1.AutoRedraw = True

    Command1.width = Picture1.width / 2 - 10
    Command1.height = 25
    Command1.Left = Picture1.Left
    Command1.Top = Picture1.Top + Picture1.height + 20
    Command1.Caption = "Draw Square && Circle"
    Command1.ZOrder (0)
   
    Command2.width = Picture1.width / 2 - 10
    Command1.height = 25
    Command2.Left = (Picture1.Left + Picture1.width) / 2 + 20
    Command2.Top = Picture1.Top + Picture1.height + 20
    Command2.Caption = "Draw Square && Circle (Antialiased)"
    Command2.ZOrder (0)

    ' Initialize Windows GDI+
    Dim GdiplusStartupInput As GdiplusStartupInput
    GdiplusStartupInput.GdiplusVersion = 1
    GdiplusStartupInput.DebugEventCallback = 0
    GdiplusStartupInput.SuppressBackgroundThread = False
    GdiplusStartupInput.SuppressExternalCodecs = False

    stat = GdiplusStartup(gdiplusToken, GdiplusStartupInput, 0)
    If stat <> Ok Then
        MsgBox "Error loading GDI+!", vbCritical
        Call GdiplusShutdown(gdiplusToken)
    End If

End Sub


Private Sub Form_Unload(Cancel As Integer)
   
    ' Clean up resources used by Windows GDI+
    Call GdiplusShutdown(gdiplusToken)
   
End Sub


Private Sub Command1_Click()

    Picture1.Cls

    Dim graphics As Long
    stat = GdipCreateFromHDC(Picture1.hdc, graphics)


    Dim redPen As Long
    stat = GdipCreatePen1(&HFFFF0000, 1, UnitPixel, redPen)

    stat = GdipDrawRectangle(graphics, redPen, 20, 70, 50, 50)
    stat = GdipDrawEllipse(graphics, redPen, 90, 70, 50, 50)

    ' Cleanup
    stat = GdipDeletePen(redPen)
    stat = GdipDeleteGraphics(graphics)
   
    Picture1.Refresh
   
End Sub


Private Sub Command2_Click()

    Picture1.Cls

    Dim graphics As Long
    stat = GdipCreateFromHDC(Picture1.hdc, graphics)
    stat = GdipSetSmoothingMode(graphics, SmoothingModeHighQuality)

    Dim redPen As Long
    stat = GdipCreatePen1(&HFFFF0000, 1, UnitPixel, redPen)

    stat = GdipDrawRectangle(graphics, redPen, 220, 70, 50, 50)
    stat = GdipDrawEllipse(graphics, redPen, 290, 70, 50, 50)

    ' Cleanup
    stat = GdipDeletePen(redPen)
    stat = GdipDeleteGraphics(graphics)
   
    Picture1.Refresh
   
End Sub

Module Code
Code:

Option Explicit


'-----------------------------------------------
' GDI+ Structs/Types
'-----------------------------------------------

Public Type GdiplusStartupInput
    GdiplusVersion As Long
    DebugEventCallback As Long
    SuppressBackgroundThread As Long
    SuppressExternalCodecs As Long
End Type


'-----------------------------------------------
' GDI+ Enums
'-----------------------------------------------

Public Enum GpStatus
    Ok = 0
    GenericError = 1
    InvalidParameter = 2
    OutOfMemory = 3
    ObjectBusy = 4
    InsufficientBuffer = 5
    NotImplemented = 6
    Win32Error = 7
    WrongState = 8
    Aborted = 9
    FileNotFound = 10
    ValueOverflow = 11
    AccessDenied = 12
    UnknownImageFormat = 13
    FontFamilyNotFound = 14
    FontStyleNotFound = 15
    NotTrueTypeFont = 16
    UnsupportedGdiplusVersion = 17
    GdiplusNotInitialized = 18
    PropertyNotFound = 19
    PropertyNotSupported = 20
End Enum

Public Enum GpUnit
    UnitWorld
    UnitDisplay
    UnitPixel
    UnitPoint
    UnitInch
    UnitDocument
    UnitMillimeter
End Enum

Public Enum QualityMode
    QualityModeInvalid = -1
    QualityModeDefault = 0
    QualityModeLow = 1
    QualityModeHigh = 2
End Enum

Public Enum SmoothingMode
    SmoothingModeInvalid = QualityModeInvalid
    SmoothingModeDefault = QualityModeDefault
    SmoothingModeHighSpeed = QualityModeLow
    SmoothingModeHighQuality = QualityModeHigh
    SmoothingModeNone
    SmoothingModeAntiAlias
End Enum


'-----------------------------------------------
' APIs
'-----------------------------------------------

Public Declare Function GdiplusStartup Lib "gdiplus" _
    (token As Long, inputbuf As GdiplusStartupInput, _
    Optional ByVal outputbuf As Long = 0) As GpStatus
Public Declare Sub GdiplusShutdown Lib "gdiplus" (ByVal token As Long)

' Graphics Functions
Public Declare Function GdipCreateFromHDC Lib "gdiplus" _
    (ByVal hdc As Long, graphics As Long) As GpStatus
Public Declare Function GdipDeleteGraphics Lib "gdiplus" _
    (ByVal graphics As Long) As GpStatus
Public Declare Function GdipSetSmoothingMode Lib "gdiplus" _
    (ByVal graphics As Long, ByVal SmoothingMd As SmoothingMode) As GpStatus
Public Declare Function GdipDrawRectangle Lib "gdiplus" _
    (ByVal graphics As Long, ByVal pen As Long, _
    ByVal X As Single, ByVal Y As Single, _
    ByVal width As Single, ByVal height As Single) As GpStatus
Public Declare Function GdipDrawEllipse Lib "gdiplus" _
    (ByVal graphics As Long, _
    ByVal pen As Long, _
    ByVal X As Single, ByVal Y As Single, _
    ByVal width As Single, ByVal height As Single) As GpStatus

' Pen Functions
Public Declare Function GdipCreatePen1 Lib "gdiplus" _
    (ByVal color As Long, ByVal width As Single, ByVal unit As GpUnit, pen As Long) As GpStatus
Public Declare Function GdipDeletePen Lib "gdiplus" _
    (ByVal pen As Long) As GpStatus


abeginner 03-23-2017 06:02 AM

Thanks to Passel and mms for your help.
Sorry for not getting back earlier, as I had not realized that I had some replies. Many appologies.

I will try out the code and read over both your replies carefully. I play around with simple code and want to learn more, but I tend to get stumped and need some expert guidance. Your replies are very much appreciated.

abeginner 10-02-2017 08:35 AM

Here is what I ended up with to dynamically draw a square
 
2 Attachment(s)
Here is what I ended up with to dynamically draw a square


All times are GMT -6. The time now is 03:25 PM.

Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Search Engine Optimisation provided by DragonByte SEO v2.0.15 (Lite) - vBulletin Mods & Addons Copyright © 2017 DragonByte Technologies Ltd.
All site content is protected by the Digital Millenium Act of 1998. Copyright©2001-2011 MAS Media Inc. and Extreme Visual Basic Forum. All rights reserved.
You may not copy or reproduce any portion of this site without written consent.