PlanetSquires Forums

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: WinFBE, plot on a form  (Read 111 times)

Johan Klassen

  • FireFly3 Registered User
  • Junior Member
  • *
  • Posts: 73
  • FF3 User
WinFBE, plot on a form
« on: November 12, 2018, 04:15:46 PM »

hello Paul :-)
found the following code at https://www.freebasic.net/forum/viewtopic.php?p=138367#p138367
made a new project with one button and placed the code in the Form1_Button1_Click function.
everything seems to work OK but I would like your opinion, is the code kosher?
are there any memory leaks?
is there a better way?

[I changed hWndForm to Form1.hWindow]
Code: [Select]
Function Form1_Button1_Click( ByRef sender As wfxButton, ByRef e As EventArgs ) As LRESULT
 'by BasicScience

 Dim As Integer xleft, ytop, wd, ht
 xleft = 50
 ytop = 50
 wd = 400
 ht = 200
 Dim hDC As HDC
' Dim hPen As hpen
                           
   hDC = GetDC( Form1.hWindow )
   
   
   Rectangle hDC, xleft, ytop, xleft+wd, ytop+ht
   Dim As HPEN greenPen=CreatePen(PS_solid, 3, &h0000ff00)
   Dim As HPEN BluePen=CreatePen(PS_solid, 3, &h00ff0000)
   SelectObject (hDC, greenPen)
   
   MoveToEx hDC, xleft, ytop+ht/2, Null
   For i As Integer = 0 To wd-1
   
        If i = wd/2 Then   SelectObject (hDC, BluePen)
         LineTo hDC, xleft+i, ytop + (ht/2)*(1+ Sin(6.28*i/20)*Exp(-i/70))

   Next i
   
   ReleaseDC Form1.hWindow, hDC     

  DeleteObject(GreenPen)
  DeleteObject(BluePen)
   Function = 0
End Function
« Last Edit: November 12, 2018, 04:19:31 PM by Johan Klassen »
Logged

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8632
  • Windows 10
    • PlanetSquires Software
Re: WinFBE, plot on a form
« Reply #1 on: November 12, 2018, 05:41:44 PM »

Hi Johan,

I would do it a little different. :)

You should put all of the drawing in WM_PAINT because you never know when a portion of the form will need to repainted. I am doing all of the form background painting in WM_PAINT (the form background and the graphic itself). I am also suppressing WM_ERASEBKGND so there isn't double painting of the background causing flicker.

I am also SaveDC and RestoreDC in order to preserve the DC stack preventing deleting GDI objects while they are still selected in the DC.

Take a look at this:
Code: [Select]

dim shared gShowGraphic as Boolean = false

''
''
Function Form1_AllEvents( ByRef sender As wfxForm, ByRef e As EventArgs ) As LRESULT

   select case e.Message
      case WM_PAINT
         Dim hDC As HDC
         dim as RECT rc
         Dim As HPEN greenPen, BluePen
         Dim As long xleft, ytop, wd, ht, stateDC
         
         xleft = 50
         ytop = 50
         wd = 400
         ht = 200
         
         hDC = GetDC( Form1.hWindow )
         stateDC = SaveDC(hDC)
         
         ' Paint the Form background
         dim as HBRUSH hBackBrush = CreateSolidBrush(Form1.BackColor)
         GetClientRect( Form1.hWindow, @rc)
         FillRect( hDC, @rc, hBackBrush)
         
         ' Paint the graphic
         if gShowGraphic then
            Rectangle hDC, xleft, ytop, xleft+wd, ytop+ht
            greenPen = CreatePen(PS_solid, 3, &h0000ff00)
            BluePen = CreatePen(PS_solid, 3, &h00ff0000)
            SelectObject (hDC, greenPen)
               
            MoveToEx hDC, xleft, ytop+ht/2, Null
            For i As Integer = 0 To wd-1
               If i = wd/2 Then   SelectObject (hDC, BluePen)
              LineTo hDC, xleft+i, ytop + (ht/2)*(1+ Sin(6.28*i/20)*Exp(-i/70))
            Next i
         end if
         
         RestoreDC(hDC, stateDC)
         ReleaseDC Form1.hWindow, hDC     

         DeleteObject(GreenPen)
         DeleteObject(BluePen)
         DeleteObject(hBackBrush)
   
      case WM_ERASEBKGND
         ' We will handle all of the form background painting in WM_PAINT
         ' This will help avoid flicker.
         e.Handled = true
     
   end select
   
   Function = 0
End Function

''
''
Function Form1_Button1_Click( ByRef sender As wfxButton, ByRef e As EventArgs ) As LRESULT
   ' Toggle displaying the graphic
   gShowGraphic = not gShowGraphic
   Form1.Refresh
   Function = 0
End Function

''
''  Remove the following Application.Run code if it used elsewhere in your application.
Application.Run(Form1)

Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8632
  • Windows 10
    • PlanetSquires Software
Re: WinFBE, plot on a form
« Reply #2 on: November 12, 2018, 05:49:48 PM »

You could also use the BeginPaint and EndPaint api functions to get the hDC and release it when finished in WM_PAINT. In my code, I used GetDC and ReleaseDC. I don't think that it really makes any difference other than that BeginPaint will automatically send an WM_ERASEBKGND message so you could redraw the client area in that message before drawing your graphic. In my code, I decided to do it all in the WM_PAINT handler.
Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8632
  • Windows 10
    • PlanetSquires Software
Re: WinFBE, plot on a form
« Reply #3 on: November 12, 2018, 05:54:05 PM »

Also, before I forget, this code you used is dangerous because INTEGER is 32 bits on Win32 and 64 bits on Win64 thereby causing problems when compiling 64 bit EXE's. The Windows API expects 32 bit values for just about everything. I always use LONG rather than INTEGER.

Dim As Integer xleft, ytop, wd, ht
Rectangle hDC, xleft, ytop, xleft+wd, ytop+ht
Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Johan Klassen

  • FireFly3 Registered User
  • Junior Member
  • *
  • Posts: 73
  • FF3 User
Re: WinFBE, plot on a form
« Reply #4 on: November 12, 2018, 06:04:45 PM »

thanks a million, Paul :-)
your advice and code are very much appreciated.
« Last Edit: November 12, 2018, 06:06:57 PM by Johan Klassen »
Logged