Plotting a one red dot

Started by George Peite, October 18, 2005, 09:02:29 AM

Previous topic - Next topic

George Peite

could someone please post a one simple and complete example on how to draw a one red color dot or a one red color pixle on the center of a Frame control using the API calls.
this is will enable the newbie users to build on this simple example, and draw lines, circles and so on.
there is no graphics examples in the Firefly visual desktop folder.

thanks
George

TechSupport

You can easily do graphics that display on the Form or the Controls via the WM_PAINT message. For example:

Function FRMMAIN_FRAME1_WM_PAINT ( _
                                ControlIndex  As Long,  _  ' index in Control Array
                                hWndForm      As Dword, _  ' handle of Form
                                hWndControl   As Dword  _  ' handle of Control
                                ) As Long

   Local hDC      As Dword
   Local nSavedDC As Dword
   Local hPen     As Dword
   Local hBrush   As Dword
   Local rc       As Rect
   
   ' Retrieve the device context of the frame control
   hDC = GetDC( hWndControl )
   
   ' place a red pixel at the center of the Frame control
   GetClientRect hWndControl, rc  
   SetPixelV hDC,  (rc.nRight - rc.nLeft) / 2, (rc.nBottom - rc.nTop) / 2, %Red                    
   
   ' Display a line
   MoveToEx hDC, 10, 10, ByVal %Null
   LineTo hDC, 10, 50
   
   ' Display a blue circle by changing the pen and brush
   hPen   = CreatePen( %PS_SOLID, 1, %Blue)
   hBrush = CreateSolidBrush( %Red )
   
   ' save the values currently in the device context so we can restore
   ' them all afterwards.
   nSavedDC = SaveDC( hDC )          
   
   ' use our new pen and background brush
   SelectObject hDC, hPen
   SelectObject hDC, hBrush              
   
   Ellipse hDC, 20, 20, 40, 40
   
   RestoreDC hDC, nSavedDC
   
   ' Destroy our pen and brush to avoid resource leaks
   DeleteObject hPen
   DeleteObject hBrush
   
   ' release the device context
   ReleaseDC hWndControl, hDC
   
   
End Function

George Peite

Thanks very much
this is the most clear ,concise, educational graphics code i have seen in the powerbasic forums
best regards
george

George Peite

Hi
i  have build on your code to draw the function y=x^2
below is the program
ok, but suppose i want the Frame1 to be empty at the onset of the program, and i want the painting on the Frame1 to be displayed after i click on a Button wich will supply the Function FORM1_FRAME1_WM_PAINT  with the value of some variables such as (maxx variable)  i mean the following pseudocode:

Function FORM1_COMMAND1_BN_CLICKED(..)
 Local buffer As String
 buffer=Space$(5)

 rem i may get the value of maxx variable from
 rem GetWindowText HWND_Form1_Text1,ByVal StrPtr(buffer),5
 rem maxx=val(buffer)

 Call the Function FORM1_FRAME1_WM_PAINT()

 rem so it will display the Frame1
 rem and it will consider the new maxx variable
End Function

i have tried for hours to call the FORM1_FRAME1_WM_PAINT  function without  success.
i hope this is possible.

Sub maxLoop()
Global maxx As Integer
maxx=20
End Sub
Function FORM1_FRAME1_WM_PAINT ( _
                              ControlIndex  As Long,  _  ' index in Control Array
                              hWndForm      As Dword, _  ' handle of Form
                              hWndControl   As Dword  _  ' handle of Control
                              ) As Long
   Local hDC      As Dword
   Local nSavedDC As Dword
   Local hPen     As Dword
   Local hBrush   As Dword
   Local rc       As Rect
   Local i As Integer
   Local x As Double
   Local y As Double
   Local rangeX As Double
   Local rangeY As Double
   Local x1 As Double    
   
   ' Retrieve the device context of the frame control
   hDC = GetDC( hWndControl )
   GetClientRect hWndControl, rc    
   
   rangeX=(rc.nRight - rc.nLeft)
   rangeY=(rc.nBottom - rc.nTop)
   x=0:y=0
   maxLoop()
   For i=0 To maxx
   x=x+1:x1=x
   y=x^2
   x1=x1/20*rangeX
   y=y/225*rangeY
       
   x1=rc.nLeft+x1
   y=rc.nBottom-y
   SetPixelV hDC, x1, y, %Red                    
   Next i    
   ' release the device context
   ReleaseDC hWndControl, hDC
   
End Function

TechSupport

The proper Windows way to initiate a control repaint is to invalidate the control and update the window.

For example:

InvalidateRect HWND_FORM1_FRAME1, %ByVal %Null, %TRUE
UpdateWindow HWND_FORM1_FRAME1


... or you could call the built-in FireFly Function: FF_Control_Redraw

In order to control whether your graphics will display, I would use a simple global variable as a flag. You set the flag to %TRUE when your button is clicked. Place the variable definition at the top of the Form (or in a Module).

Global gDrawFlag As Long


In the BN_CLICKED message of your button put:

gDrawFlag = %TRUE


In your WM_PAINT message for the Frame control place:

If gFlagPaint = %FALSE Then Exit Function


I would retrieve the Maxx value during the WM_PAINT rather than the BN_CLICKED because then you don't need to track that value via a global variable.


Function FORM1_FRAME1_WM_PAINT( ........
If gFlagPaint = %FALSE Then Exit Function

Local maxx As Long

' get the value of maxx variable
maxx = Val( FF_Control_GetText( HWND_FORM1_TEXT1 ))

......
End Function




Hope this helps.

George Peite

that code works fine for me.
i have my last problem and question on this topic:
my Form1 contains the Frame1, the Text1 box, and the Command1 button
and when i write 4 in the Text1 box then click the Button the Frame1 will show the graph of 4 points for the function y=x^2, and when i write 9 in the Text1 box then click the Button the Frame1 will show correctly 9 points, but when i write 4 again in the Text1 box then click the Button the Frame1 will continue to show the 9 points and not the 4 points, ie i could plot with higher numbers only ,i have written :

InvalidateRect HWND_FORM1_FRAME1, ByVal %Null, %TRUE
UpdateWindow HWND_FORM1_FRAME1

in the Command1 button, and in another try in the FORM1_FRAME1_WM_PAINT  function  but this does not repaint the Frame1 to show 4 points
also i have tried:

FF_Control_Redraw  HWND_FORM1_FRAME1

but does not repaint to the 4 points
how to correct the situation
thanks

George Peite

Hi
after one thousand try i have found the suitable code for the above program in wich the Form1 contains a Frame1 and one Button and one Text1 Box to enter the number of points you want to draw on the Frame1, click the button will plot the correct number of points
the problematic line was
FF_Control_Redraw  HWND_FORM1_Frame1
we should use
FF_Control_Redraw  HWND_FORM1

Thanks

Global gFlagPaint As Long  
'-----------------------------------------------------------------------------------------------------------------
Function FORM1_COMMAND1_BN_CLICKED ( _
                                  ControlIndex     As Long,  _  ' index in Control Array
                                  hWndForm         As Dword, _  ' handle of Form
                                  hWndControl      As Dword, _  ' handle of Control
                                  idButtonControl  As Long   _  ' identifier of button
                                  ) As Long

gFlagPaint = %True
FF_Control_Redraw  HWND_FORM1

End Function


Function FORM1_FRAME1_WM_PAINT ( _
                              ControlIndex  As Long,  _  ' index in Control Array
                              hWndForm      As Dword, _  ' handle of Form
                              hWndControl   As Dword  _  ' handle of Control
                              ) As Long

If gFlagPaint = %FALSE Then Exit Function
               
   Local hDC      As Dword
   Local nSavedDC As Dword
   Local hPen     As Dword
   Local hBrush   As Dword
   Local rc       As Rect
   Local i As Integer
   Local x As Double
   Local y As Double
   Local rangeX As Double
   Local rangeY As Double
   Local x1 As Double
   Local maxx As Long
   Local buffer As String
   buffer=Space$(5)
   GetWindowText HWND_Form1_Text1,ByVal StrPtr(buffer),5    
   maxx=Val(buffer)
   'Get the value Of maxx variable
   'maxx = Val( FF_Control_GetText( HWND_FORM1_TEXT1 ))
   ' Retrieve the device context of the frame control
   hDC = GetDC( hWndControl )
   GetClientRect hWndControl, rc    
   
   rangeX=(rc.nRight - rc.nLeft)
   rangeY=(rc.nBottom - rc.nTop)
   x=0:y=0
   
   For i=0 To maxx
   x=x+1:x1=x
   y=x^2
   x1=x1/20*rangeX
   y=y/225*rangeY
       
   x1=rc.nLeft+x1
   y=rc.nBottom-y
   SetPixelV hDC, x1, y, %Red                    
   Next i    
   ' release the device context
   ReleaseDC hWndControl, hDC                        
                   

End Function