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
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
Thanks very much
this is the most clear ,concise, educational graphics code i have seen in the powerbasic forums
best regards
george
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
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.
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
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