Requires: Direct2D.lg32
D2Circle draws a circle in the render target's drawing area, while D2PCircle draws a filled circle in the render target's drawing area.
D2Circle x!, y!, r![, w1%][, w2%][, Figure%] [,D2Brush]
D2PCircle x!, y!, r![, w1%][, w2%][, Figure%] [,D2Brush]
x!, y!, r! | : float expression |
w1%, w2%, Figure% | : integer expression |
D2Brush | : Object expression |
D2Circle draws the outline of a circle with position x,y and radius r in device-independent pixels. By default, the outline is drawn using a solid color brush created from the current foreground color D2ForeColor. If the application passes a D2Brush object, the stroke (line) is painted with that brush. Use D2DefLine to set the line style and width. By using the start (w1) and end (w2) angles, you can draw just an arc (default), a closed arc, or a pie, rather than the full circle - the angles w1 and w2 are given in whole degree steps with any arc being drawn in an anti-clockwise direction. Figure% can have the following values:
D2PCircle draws the interior of a circle with position x,y and radius r in device-independent pixels. By default, the interior is painted using the brush set with D2DefFill. If the application specified a brush object with the D2PCircle command, the interior is painted with that brush. The outline of the circle is painted using the current foreground color. To prevent the painting of the outline set line-width to zero using D2DefLine , 0. By using the start (w1) and end (w2) angles, you can draw just an arc (default) or a closed arc, rather than the full circle - the angles w1 and w2 are given in whole degree steps with any arc being drawn in an anti-clockwise direction. Figure% can have the following values:
'
' Samples\Direct2D\D2PCircles.g32 (dpi-aware)
' - Animation with circles
' - Uses high-resolution timer
'
$Library "direct2d"
$Library "gfawinx"
DpiAwareness()
OpenW 1, 0, 0, 600, 500, ~15 ' size as if on 96 dpi screen
FormScaleForDpi(Me)
' Direct2D stuff
Global RT1 As Object, RTWidth As Float, RTHeight As Float
Set RT1 = D2GetRT()
D2GetSizeRT RT1, RTWidth, RTHeight
' D2Bitmap a device dependent resource
Global bmpBulldog As Object, bmpW As Float, bmpH As Float
Set bmpBulldog = D2Bitmap(":Bulldog")
D2BitmapSize bmpBulldog, bmpW, bmpH
' Create a high-resolution timer with 10 msec interval
' (The minimal interval of an Ocx Timer is 15.625 ms => 64 fps)
Global Object tmrQ
Set tmrQ = TimerQ(Me, 1, 10) ' from gfawinx.lg32
' Show FPS each second
Global fps As Long, fpsShow As Long
Ocx Timer tmrfps
tmrfps.Interval = 1000 ' 1 sec
tmrfps.Enabled = True
Global Float ang, x, y, x2, y2, x3, y3, x4, y4
Do
Sleep
Until Me Is Nothing
Sub tmrfps_Timer ' after 1 sec
fpsShow = fps
fps = 0
EndSub
Sub Win_1_Message(hWnd%, Mess%, wParam%, lParam%)
Const frq As Float = 1.0!
Const frq2 As Float = 4.0!
Const frq3 As Float = 6.0!
Const outeroffset As Float = 13.0!
Const outerfrq As Float = 6.0!
If Mess% == WM_TIMER && wParam% == 1 ' 10 msec timer
fps++ ' increment frame per seconds
' Show some animation
x = 266 + (180 + outeroffset * Sin(outerfrq * ang)) * Cos(ang)
y = 266 + (180 + outeroffset * Sin(outerfrq * ang)) * Sin(ang)
x2 = x + 40 * Cos(ang * frq)
y2 = y + 40 * Sin(ang * frq)
x3 = x2 + 20 * Cos(ang * frq2)
y3 = y2 + 20 * Sin(ang * frq2)
x4 = x3 + 10 * Cos(ang * frq3)
y4 = y3 + 10 * Sin(ang * frq3)
ang = ang + 0.01
Win_1_Paint
EndIf
End Sub
Sub Win_1_Paint
D2BeginDraw RT1
D2Put 0, 0, bmpBulldog, RTWidth , RTHeight ' shrink to fit
D2DefFill ARGB(0, 0, 0, 0)
D2PCircle x, y , 40
D2DefFill ARGB(128, 255, 0, 0)
D2PCircle x2, y2 , 20
D2DefFill ARGB(128, 0, 0, 255)
D2PCircle x3, y3 , 10
D2DefFill ARGB(128, 255, 255, 255)
D2PCircle x4, y4, 4
D2Text 0, 0, "Fps: " + Dec(fpsShow)
D2EndDraw
EndSub
Sub Win_1_ReSize
D2ResizeRT RT1, _X, _Y
D2GetSizeRT RT1, RTWidth, RTHeight
Sub Win_1_MessageProc(hWnd%, Mess%, wParam%, lParam%, retval%, ValidRet?)
Local Int dpi
If Mess% == WM_DPICHANGED
If FormScaleForDpi(Me, wParam%, lParam%) ' scale (resize) form and it's Ocx-es
' Here: Update other Dpi dependent resources (toolbar, bitmaps, Direct2D)
dpi = LoWord(wParam%) ' new Dpi for form
D2SetDpiRT RT1, dpi ' update D2 rendertarget's dpi
EndIf
retval% = 0 : ValidRet? = True ' tell OS we handled it
EndIf
EndSub
Function FormScaleForDpi(ByVal frm As Form, Optional newdpi As Int, Optional lParam As Int) As Bool
Local i As Int, c As Control, rc As RECT, prevDpi As Int, newrc As Pointer To RECT, _
tb As Tab, w As Int, h As Int
With frm
' Set initial newdpi for the form and the scale factors for a LoadForm
If .WhatsThisHelpID == 0
If Exist(":{" + .Name) ' a Form-Editor form
.WhatsThisHelpID = WinDpi(0) ' initial dpi is system newdpi
.ScaleWidth = .ScaleWidth * 96 / .WhatsThisHelpID ' set initial scale factors
.ScaleHeight = .ScaleHeight * 96 / .WhatsThisHelpID
Else ' created by OpenW or Form command
.WhatsThisHelpID = 96 ' coord space is 96
EndIf
EndIf
prevDpi = .WhatsThisHelpID
newdpi = LoWord(newdpi)
If newdpi == 0 Then newdpi = WinDpi(.hWnd)
Exit Func If newdpi == prevDpi ' don't continue if equal
' Size the form, except if it is a child window
If !(GetWindowLong(.hWnd, GWL_STYLE) %& WS_CHILD)
If lParam ' size to the OS suggested size
Pointer newrc = lParam ' ptr to RECT in lParam
SizeW .hWnd, newrc.Right - newrc.Left, newrc.Bottom - newrc.Top
Else ' scale based on the current client size
GetClientSize .hWnd, w, h ' can't use _X _Y, they are for ME only
AdjustW .hWnd, Scale(w, newdpi, prevDpi), Scale(h, newdpi, prevDpi)
EndIf
EndIf
.FontSize = .FontSize * newdpi / prevDpi
.ScaleWidth = .ScaleWidth * prevDpi / newdpi
.ScaleHeight = .ScaleHeight * prevDpi / newdpi
' Scale position and size of the Ocx windowed controls
For Each c In frm.Controls
If !(TypeOf(c) Is ImageList || TypeOf(c) Is Timer || _
TypeOf(c) Is CommDlg || TypeOf(c) Is TrayIcon) ' not the windowless OCX-es
' First set fontsize, but not all OCX-es have a Font property
If !(TypeOf(c) Is ProgressBar || TypeOf(c) Is Slider || TypeOf(c) Is Image || TypeOf(c) Is RichEdit)
c.fontsize = c.fontsize * newdpi / prevDpi
ElseIf TypeOf(c) Is RichEdit ' Requires LoadRichEdit50W!
SendMessage c.hwnd, WM_DPICHANGED, MakeLong(newdpi, newdpi), 0
EndIf
' Set new position and size for OCX-controls
GetWinPos(c.hwnd, rc) ' relative to parent
~SetWindowPos(c.hwnd, 0, _
Scale(rc.Left, newdpi, prevDpi), Scale(rc.Top, newdpi, prevDpi), _
Scale(rc.Right - rc.Left, newdpi, prevDpi), _
Scale(rc.Bottom - rc.Top, newdpi, prevDpi), SWP_NOZORDER) ' new pos and size
If TypeOf(c) Is Form ' Scale OCX-es of a child Form Ocx
c.WhatsThisHelpID = prevDpi
~FormScaleForDpi(c, newdpi)
ElseIf TypeOf(c) Is TabStrip ' Scale TabStrip's attached forms
For Each tb In c.Tabs
If TypeOf(tb.Ocx) Is Form
tb.Ocx.WhatsThisHelpID = prevDpi
~FormScaleForDpi(tb.Ocx, newdpi)
EndIf
Next
EndIf
EndIf
Next
.WhatsThisHelpID = newdpi ' store new newdpi
EndWith
FormScaleForDpi = True
EndFunc
NOTE: The above example will not run as it relies on an embedded file which is not present in the syntax. The programme with full resources can be found in GFABASIC/Samples/Direct2D/D2PCircles.g32.
Requires an active render target, either set with D2BeginDraw or D2SetRT.
All drawing commands must be placed between D2BeginDraw and D2EndDraw.
D2Circle invokes the ID2D1RenderTarget::DrawEllipse method and D2PCircle invokes the ID2D1RenderTarget::FillEllipse method.
The arc and pie figures are implemented using a temporary path geometry. More info can be found in the D2Sink_AddArc topic.
D2PBox, D2Box, D2PRBox, D2RBox, D2Line, D2Ellipse, D2PEllipse, D2SetRT, D2DefFill, D2DefLine, D2Brush, D2BeginDraw, D2EndDraw, D2Sink_AddArc.
{Created by James Gaite; Last updated: 03/03/2022 by James Gaite}