Direct2D Include [Windows]

Share your advanced PureBasic knowledge/code with the community.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 616
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Direct2D Include [Windows]

Post by minimy »

Sound really nice!! Thanks for share! :D
If translation=Error: reply="Sorry, Im Spanish": Endif
Justin
Addict
Addict
Posts: 948
Joined: Sat Apr 26, 2003 2:49 pm

Re: Direct2D Include [Windows]

Post by Justin »

I did an animation test, i expected it to be a bit smoother on 4k resolution, i did not use a timer, maybe someone can improve it.
Simply save the code in the PBDirect2D folder an run it.
Image

Code: Select all

;DemoAnim.pb

IncludeFile "PBDirect2D.pb"

EnableExplicit

#ANIM_DOTS_COUNT = 3

Enumeration
	#MENU_ID_START_STOP
EndEnumeration

;- _ANIM
Structure _ANIM
	lastTime.q
	active.b
	counter.f
EndStructure

;- _APP
Structure _APP
	win.i
	menu.i
	oldProc.i
	
	anim._ANIM
	
	;Device independent resources
	d2dFactory.ID2D1Factory
	dWriteFactory.IDWriteFactory
	txtFormat.IDWriteTextFormat
	
	;Device dependent resources
	renderTarget.ID2D1HwndRenderTarget
	dotBrush.ID2D1SolidColorBrush
	rectBrush.ID2D1SolidColorBrush
EndStructure
Global._APP app

Procedure app_createDeviceIndependentResources()
	Protected.l hr
	Protected.D2D1_FACTORY_OPTIONS fOpts
	Protected.D2D1_STROKE_STYLE_PROPERTIES props
	
	fOpts\DebugLevel = #D2D1_DEBUG_LEVEL_NONE
	hr = D2D1CreateFactory_(#D2D1_FACTORY_TYPE_SINGLE_THREADED, ?IID_ID2D1Factory, @fOpts, @app\d2dFactory)
	
	hr = DWriteCreateFactory_(#DWRITE_FACTORY_TYPE_SHARED, ?IID_IDWriteFactory, @app\dWriteFactory)
	If hr = #S_OK
		;Text format
		hr = app\dWriteFactory\CreateTextFormat("Segoe UI", #Null, #DWRITE_FONT_WEIGHT_REGULAR, 
			#DWRITE_FONT_STYLE_NORMAL, #DWRITE_FONT_STRETCH_NORMAL, 18.0,
			"en-us", @app\txtFormat)
		
		If hr = #S_OK
			app\txtFormat\SetTextAlignment(#DWRITE_TEXT_ALIGNMENT_LEADING)
		EndIf 
	EndIf
	
	ProcedureReturn hr
EndProcedure

Procedure app_discardDeviceIndependentResources()
	If app\d2dFactory
		app\d2dFactory\Release() : app\d2dFactory = 0 
	EndIf
	
	If app\dWriteFactory
		app\dWriteFactory\Release() : app\dWriteFactory = 0 
	EndIf
	
	If app\txtFormat
		app\txtFormat\Release() : app\txtFormat = 0 
	EndIf
EndProcedure

Procedure app_createDeviceResources()
	Protected.l hr
	Protected.RECT rc
	Protected.i hwnd
	Protected.D2D1_SIZE_U sz
	Protected.D2D1_RENDER_TARGET_PROPERTIES rtProps
	Protected.D2D1_HWND_RENDER_TARGET_PROPERTIES  hwndProps
	Protected.D2D1_COLOR_F color
	Protected.D2D1_BRUSH_PROPERTIES bProp
	
	hr = #S_OK
	
	If app\renderTarget = 0
		hwnd = WindowID(app\win)
		GetClientRect_(hwnd, @rc)
		sz\width = rc\right - rc\left
		sz\height = rc\bottom - rc\top
		
		;Create a Direct2D render target.
		rtProps\type = #D2D1_RENDER_TARGET_TYPE_DEFAULT
		rtProps\pixelFormat\format = #DXGI_FORMAT_UNKNOWN
		rtProps\pixelFormat\alphaMode = #D2D1_ALPHA_MODE_UNKNOWN
		rtProps\dpiX = 0.0
		rtProps\dpiY = 0.0
		rtProps\usage = #D2D1_RENDER_TARGET_USAGE_NONE
		rtProps\minLevel = #D2D1_FEATURE_LEVEL_DEFAULT
		
		hwndProps\hwnd = hwnd
		hwndProps\pixelSize\height = sz\height
		hwndProps\pixelSize\width = sz\width
		hwndProps\presentOptions = #D2D1_PRESENT_OPTIONS_NONE
		
		hr = app\d2dFactory\CreateHwndRenderTarget(@rtProps, @hwndProps, @app\renderTarget)
		If hr = #S_OK		
			;Brushes
			bProp\opacity = 1.0
			
			color\r = 0 : color\g = 162/255 : color\b = 232/255 : color\a = 1.0
			app\renderTarget\CreateSolidColorBrush(@color, @bProp, @app\rectBrush)
			
			color\r = 0.0 : color\g = 1.0 : color\b = 0.0 : color\a = 1.0
			app\renderTarget\CreateSolidColorBrush(@color, @bProp, @app\dotBrush)
		EndIf
	EndIf 
	
	ProcedureReturn hr
EndProcedure

Procedure app_discardDeviceResources()	
	If app\renderTarget
		app\renderTarget\Release() : app\renderTarget = 0
	EndIf
	
	If app\dotBrush
		app\dotBrush\Release() : app\dotBrush = 0
	EndIf
	
	If app\rectBrush
		app\rectBrush\Release() : app\rectBrush = 0
	EndIf
EndProcedure

Procedure app_init()
	InitializeStructure(@app, _APP)
EndProcedure

Procedure app_release()
	app_discardDeviceResources()
	app_discardDeviceIndependentResources()
EndProcedure

Procedure app_onSize(width.w, height.w)
	Protected.D2D1_SIZE_U sz
		
	If app\renderTarget
		sz\width = width
		sz\height = height
		
		app\renderTarget\Resize(@sz)
	EndIf
EndProcedure

Procedure app_onRender()
	Protected.l hr, i
	Protected.q tag1, tag2
	Protected.D2D1_COLOR_F color
	Protected.D2D1_ROUNDED_RECT dotsRect
	Protected.D2D1_RECT_F rtRect
	Protected.D2D1_SIZE_F rtSize
	Protected.D2D1_ELLIPSE  dot
	Protected.f dotRectSize, t, vel
	Protected.q currentTime, deltaTime, timeDelay, t2
	Protected.s text
	
	hr = #S_OK
	
	hr = app_createDeviceResources()
	If hr = #S_OK	
		app\renderTarget\BeginDraw()
		currentTime = ElapsedMilliseconds()
		deltaTime = currentTime - app\anim\lastTime
		app\anim\lastTime = currentTime
		
		timeDelay = 16 - deltaTime
		
		color\r = 1.0 : color\g = 1.0 : color\b = 1.0 : color\a = 1.0
		app\renderTarget\Clear(@color)
		app\renderTarget\GetSize(@rtSize)
		rtRect\right = rtSize\width
		rtRect\bottom = rtSize\height
		
		;Round Rectangle
		dotRectSize = 200.0
		dotsRect\rect\left = (rtSize\width / 2) - dotRectSize / 2
		dotsRect\rect\top = (rtSize\height / 2) - dotRectSize / 2
		dotsRect\rect\right = (rtSize\width / 2) + dotRectSize / 2
		dotsRect\rect\bottom = dotsRect\rect\top + dotRectSize ;(rtSize\height / 2) + dotRectSize / 2
		dotsRect\radiusX = 20.0
		dotsRect\radiusY = 20.0
		app\renderTarget\FillRoundedRectangle(@dotsRect, app\rectBrush)
		
		t = app\anim\counter
		dot\point\x = (rtSize\width / 2) - 40
		dot\point\y = (rtSize\height / 2)
		dot\radiusX = 10.0
		dot\radiusY = 10.0
		For i = 0 To #ANIM_DOTS_COUNT - 1
			If app\anim\active
				dot\point\y = (rtSize\height / 2) + (Sin(t) * ((dotRectSize / 2) - 40 )) 
			EndIf 
			
			app\renderTarget\FillEllipse(@dot, app\dotBrush)
			dot\point\x + 40
			t - 0.5
		Next 
		
		;Text
		text = "Press F1 to Start / Stop"
		app\renderTarget\DrawText(text, Len(text), app\txtFormat, @rtRect, app\rectBrush, #D2D1_DRAW_TEXT_OPTIONS_NONE, #DWRITE_MEASURING_MODE_NATURAL)

		hr = app\renderTarget\EndDraw(@tag1, @tag2)
		
		app\anim\counter + 0.090
	EndIf
	
	If (hr = #D2DERR_RECREATE_TARGET)
		hr = #S_OK
		app_discardDeviceResources()
	EndIf 
	
	If timeDelay > 0
		Delay(timeDelay)
	EndIf 
EndProcedure

Procedure.i win_proc(hwnd.i, msg.l, wparam.i, lparam.i)	
	Select msg
		Case #WM_SIZE
			app_onSize(PeekW(@lparam), PeekW(@lparam + SizeOf(Word)))
				
		Case #WM_DISPLAYCHANGE
			InvalidateRect_(hwnd, #Null, #False)
 			
		Case #WM_ERASEBKGND
			Protected.RECT rc
			
			If Not app\anim\active
				GetClientRect_(hwnd, @rc)
				app_onSize(rc\right, rc\bottom)
				app_onRender()
				ProcedureReturn 1
			EndIf
			
		Case #WM_PAINT		
			If Not app\anim\active
				app_onRender()
				ValidateRect_(hwnd, #Null)
				ProcedureReturn 0
			EndIf 
	EndSelect
	
	ProcedureReturn CallWindowProc_(app\oldProc, hwnd, msg, wparam, lparam)
EndProcedure

Procedure app_processEvent(ev.l)
	Select ev
		Case #PB_Event_Menu
			Select EventMenu()
				Case #MENU_ID_START_STOP
					app\anim\active = Bool(Not app\anim\active)
					If Not app\anim\active
						app\anim\counter = 0
					EndIf
					
					InvalidateRect_(WindowID(app\win), 0, #False)
					
			EndSelect
	EndSelect
EndProcedure

Procedure main()
	Protected.l ev
	
	app_init()
	
	If app_createDeviceIndependentResources() <> #S_OK
		MessageRequester("Error" , "Failed to initialize Direct2D")
		End
	EndIf
	
	app\anim\active = #True
	
	app\win = OpenWindow(#PB_Any, 10, 10, 600, 400, "DemoAnim", #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget)
	app\menu = CreateMenu(#PB_Any, WindowID(app\win))
	AddKeyboardShortcut(app\win, #PB_Shortcut_F1, #MENU_ID_START_STOP)
	app\oldProc = SetWindowLongPtr_(WindowID(app\win), #GWLP_WNDPROC, @win_proc())

	Repeat
		If app\anim\active
			ev = WindowEvent()
			If ev = 0
				app_onRender()
				
			Else
				app_processEvent(ev)
			EndIf 
			
		Else
			ev = WaitWindowEvent()
			app_processEvent(ev)
		EndIf 
		
	Until ev = #PB_Event_CloseWindow
EndProcedure

main()
pjay
Enthusiast
Enthusiast
Posts: 252
Joined: Thu Mar 30, 2006 11:14 am

Re: Direct2D Include [Windows]

Post by pjay »

I'm running an Intel iGPU here and it takes < 1ms rendering (at 2560x1440 though, not 4k), so it's nice and fast here Justin (it should be to be fair, for such a simple scene).

I did disable vSync (hwndProps\presentOptions = #D2D1_PRESENT_OPTIONS_IMMEDIATELY), removed the Delay() & adjusted animation speed to tie-in with elapsed milliseconds to get the measurements.

Cool project & very powerful for 2d rendering, thanks for sharing. 8)
Justin
Addict
Addict
Posts: 948
Joined: Sat Apr 26, 2003 2:49 pm

Re: Direct2D Include [Windows]

Post by Justin »

Added Windows Animation Manager component:
https://learn.microsoft.com/en-us/windo ... ain-portal
It handles animations and transitions, it runs better.
Example in DemoWAM.pb in the repo.

Hi pjay,

the #D2D1_PRESENT_OPTIONS_IMMEDIATELY flag makes a big difference thanks for the tip, but the cpu usage is also high, about 10-15% could you reduce it?

Anyways, using the WAM runs pretty smooth, enough for UI animations.

Now i think the code is ready to attemp a DirectX animated canvas gadget, i will try it in a few days.
Justin
Addict
Addict
Posts: 948
Joined: Sat Apr 26, 2003 2:49 pm

Re: Direct2D Include [Windows]

Post by Justin »

Just noticed that with the current settings the alpha channel was not supported, you have to use a pixelformat with #DXGI_FORMAT_B8G8R8A8_UNORM and #D2D1_ALPHA_MODE_PREMULTIPLIED flags.

Updated and opacity animation test in DemoWAM.pb.
Image
Prod
User
User
Posts: 14
Joined: Thu Mar 31, 2005 3:47 pm
Location: Denmark

Re: Direct2D Include [Windows]

Post by Prod »

This is most excellent.
Could you provide an example of how to use CreateBitmap and DrawBitmap?
User avatar
IceSoft
Addict
Addict
Posts: 1694
Joined: Thu Jun 24, 2004 8:51 am
Location: Germany

Re: Direct2D Include [Windows]

Post by IceSoft »

link no longer existing:
Justin wrote: Thu Aug 29, 2024 12:31 pm The files are at github:
https://github.com/omegakode/PBDirect2D
Belive! C++ version of Puzzle of Mystralia
Bug Planet
<Wrapper>4PB, PB<game>, =QONK=, PetriDish, Movie2Image, PictureManager,...
PeDe
Enthusiast
Enthusiast
Posts: 284
Joined: Sun Nov 26, 2017 3:13 pm

Re: Direct2D Include [Windows]

Post by PeDe »

IceSoft wrote: Mon Nov 25, 2024 1:52 pm link no longer existing:
Justin wrote: Thu Aug 29, 2024 12:31 pm The files are at github:
https://github.com/omegakode/PBDirect2D
I have downloaded the files as a ZIP archive (149 KiB):
https://www.dreisiebner.at/temp/PBDirec ... -09-12.zip

Peter
Justin
Addict
Addict
Posts: 948
Joined: Sat Apr 26, 2003 2:49 pm

Re: Direct2D Include [Windows]

Post by Justin »

Hi,

the files are up again, i needed to make it private for some time, now is public again.

This code creates a bitmap in memory, draws it to the window and you can save it as a jpg using File->Save.

For loading and drawing an image from a file is in DemoApp.pb.

Code: Select all

IncludeFile "PBDirect2D.pb"

;https://www.codeproject.com/Articles/5269188/Direct2D-Tutorial-Part-1-RenderTarget#bitmap

EnableExplicit

;- Enum MENU_ID
Enumeration
	#MENU_ID_SAVE
EndEnumeration

;- _APP
Structure _APP
	win.i
	menu.i
	d2dFactory.ID2D1Factory
	imgFactory.IWICImagingFactory
	renderTarget.ID2D1HwndRenderTarget
	brush1.ID2D1SolidColorBrush
	d2dBmp.ID2D1Bitmap
	wicBmp.IWICBitmap 
	oldProc.i
EndStructure
Global._APP app

Procedure app_discardDeviceDependentResources()	
	If app\renderTarget
		app\renderTarget\Release() : app\renderTarget = 0
	EndIf
	
	If app\brush1
		app\brush1\Release() : app\brush1 = 0
	EndIf
	
	If app\d2dBmp
		app\d2dBmp\Release() : app\d2dBmp = 0
	EndIf
EndProcedure

Procedure app_release()
	If app\d2dFactory
		app\d2dFactory\Release() : app\d2dFactory = 0
	EndIf
	
	If app\imgFactory
		app\imgFactory\Release() : app\imgFactory = 0
	EndIf 
	
	app_discardDeviceDependentResources()
EndProcedure	

;Creates a WIC Bitmap
Procedure.i app_createImage(imgFactory.IWICImagingFactory)
	Protected.IWICBitmap wicBmp
	Protected.D2D1_BRUSH_PROPERTIES bProp
	Protected.D2D1_RENDER_TARGET_PROPERTIES rtProps
	Protected.ID2D1SolidColorBrush brush1
	Protected.D2D1_COLOR_F color
	Protected.ID2D1RenderTarget bmpRt
	Protected.D2D1_ROUNDED_RECT rc
	Protected.q tag1, tag2
	
	imgFactory\CreateBitmap(200, 200, ?GUID_WICPixelFormat32bppPBGRA, #WICBitmapCacheOnLoad, @wicBmp)
	
	;Create bitmap render target
	rtProps\type = #D2D1_RENDER_TARGET_TYPE_DEFAULT
	;Enable alpha channel
	rtProps\pixelFormat\format = #DXGI_FORMAT_B8G8R8A8_UNORM
	rtProps\pixelFormat\alphaMode = #D2D1_ALPHA_MODE_PREMULTIPLIED
	rtProps\dpiX = 0.0
	rtProps\dpiY = 0.0
	rtProps\usage = #D2D1_RENDER_TARGET_USAGE_NONE
	rtProps\minLevel = #D2D1_FEATURE_LEVEL_DEFAULT

	app\d2dFactory\CreateWicBitmapRenderTarget(wicBmp, @rtProps, @bmpRt)
	
	;Brush
	bProp\opacity = 1.0
	color\r = 0 : color\g = 162/255 : color\b = 232/255 : color\a = 1.0
	bmpRt\CreateSolidColorBrush(@color, @bProp, @brush1)
	
	;Draw bitmap
	bmpRt\BeginDraw()
		color\r = 1 : color\g = 0 : color\b = 0 : color\a = 1
		bmpRt\Clear(@color)
		rc\rect\left = 10
		rc\rect\top = 10
		rc\rect\right = 100
		rc\rect\bottom = 100
		rc\radiusX = 20
		rc\radiusY = 20
		bmpRt\FillRoundedRectangle(@rc, brush1)
	bmpRt\EndDraw(@tag1, @tag2)
	
	bmpRt\Release()
	
	ProcedureReturn wicBmp
EndProcedure

Procedure app_saveImage()
	Protected.IStream stm
	Protected.IWICBitmapEncoder encoder
	Protected.IWICBitmapFrameEncode frame
	Protected.IPropertyBag2 props
	Protected.D2D1_SIZE_F bmpSize
	Protected.l bmpWidth, bmpHeight, hr
	Protected.GUID pixelFormat
	Protected.s file
	
	file = SaveFileRequester("Save", "test.jpg", "JPG file|*.jpg|All files|*.*", 0)
	If file = "" : ProcedureReturn : EndIf
	
	hr = SHCreateStreamOnFileEx_(file, #STGM_CREATE | #STGM_WRITE | #STGM_SHARE_EXCLUSIVE,
		#FILE_ATTRIBUTE_NORMAL, #True, #Null, @stm)
	If hr <> #S_OK : ProcedureReturn : EndIf
	
	hr = app\imgFactory\CreateEncoder(?GUID_ContainerFormatJpeg, #Null, @encoder)
	If hr <> #S_OK : ProcedureReturn : EndIf

	encoder\Initialize(stm, #WICBitmapEncoderNoCache)
	encoder\CreateNewFrame(@frame, @props)
	frame\Initialize(props)
	
	app\wicBmp\GetSize(@bmpWidth, @bmpHeight)
	app\wicBmp\GetPixelFormat(@pixelFormat)
	
	frame\SetPixelFormat(@pixelFormat)
	frame\WriteSource(app\wicBmp, #Null)
	
	frame\Commit()
	encoder\Commit()
	
	frame\Release()
	encoder\Release()
	
	stm\Release()
EndProcedure

Procedure app_createDeviceIndependentResources()
	Protected.D2D1_FACTORY_OPTIONS fOpts
	Protected.l hr

	;Create D2D1Factory
	fOpts\DebugLevel = #D2D1_DEBUG_LEVEL_NONE
	hr = D2D1CreateFactory_(#D2D1_FACTORY_TYPE_SINGLE_THREADED, ?IID_ID2D1Factory, @fOpts, @app\d2dFactory)
		
	;Create WICImagingFactory
	hr = CoCreateInstance_(?CLSID_WICImagingFactory, #Null, #CLSCTX_INPROC_SERVER, ?IID_IWICImagingFactory, @app\imgFactory)
		
	app\wicBmp = app_createImage(app\imgFactory)
	
	ProcedureReturn hr
EndProcedure

Procedure app_createDeviceDependentResources()
	Protected.RECT rc
	Protected.l hr
	Protected.i hwnd
	Protected.D2D1_SIZE_U sz
	Protected.D2D1_RENDER_TARGET_PROPERTIES props
	Protected.D2D1_HWND_RENDER_TARGET_PROPERTIES  hwndProps

	hr = #S_OK
	
	If app\renderTarget = 0
		hwnd = WindowID(app\win)
		GetClientRect_(hwnd, @rc)
		sz\width = rc\right - rc\left
		sz\height = rc\bottom - rc\top
		
		;Create a Direct2D render target.
		props\type = #D2D1_RENDER_TARGET_TYPE_DEFAULT
		
		;Enable alpha channel
		props\pixelFormat\format = #DXGI_FORMAT_B8G8R8A8_UNORM
		props\pixelFormat\alphaMode = #D2D1_ALPHA_MODE_PREMULTIPLIED
		
		props\dpiX = 0.0
		props\dpiY = 0.0
		props\usage = #D2D1_RENDER_TARGET_USAGE_NONE
		props\minLevel = #D2D1_FEATURE_LEVEL_DEFAULT
		
		hwndProps\hwnd = hwnd
		hwndProps\pixelSize\height = sz\height
		hwndProps\pixelSize\width = sz\width
		hwndProps\presentOptions = #D2D1_PRESENT_OPTIONS_NONE
		
		hr = app\d2dFactory\CreateHwndRenderTarget(@props, @hwndProps, @app\renderTarget)
		If hr = #S_OK
			;Create D2DBitmap from WICBitmap
			app\renderTarget\CreateBitmapFromWicBitmap(app\wicBmp, #Null, @app\d2dBmp)
		EndIf
	EndIf
	
	ProcedureReturn hr
EndProcedure

Procedure app_onSize(width.w, height.w)
	Protected.D2D1_SIZE_U sz
		
	If app\renderTarget
		sz\width = width
		sz\height = height
		
		app\renderTarget\Resize(@sz)
	EndIf
EndProcedure

Procedure app_onRender()
	Protected.l hr, x, y, width, height, txtOpts
	Protected.D2D1_COLOR_F color
	Protected.q tag1, tag2
	Protected.D2D1_SIZE_F rectSize, rtSize, bmpSize, scaledBmpSize
	Protected.D2D1_RECT_F rcF2, rcBmpDest, rcBmpSrc
	Protected.D2D1_POINT_2F bmpPos, pt
	Protected.s txt
	
	hr = #S_OK
	
	hr = app_createDeviceDependentResources()
	If hr = #S_OK	
		rectSize\width = 200.0
		rectSize\height = 200.0
				
		app\renderTarget\BeginDraw()

		color\r = 1.0 : color\g = 1.0 : color\b = 1.0 : color\a = 1.0
		app\renderTarget\Clear(@color)
		app\renderTarget\GetSize(@rtSize)
		
		app\d2dBmp\GetSize(@bmpSize)
		rcBmpSrc\left = 0
		rcBmpSrc\top = 0
		rcBmpSrc\right = bmpSize\width
		rcBmpSrc\bottom = bmpSize\height
		
		rcBmpDest\left = 10
		rcBmpDest\top = 10
		rcBmpDest\right = rcBmpDest\left + bmpSize\width
		rcBmpDest\bottom = rcBmpDest\top + bmpSize\height

		app\renderTarget\DrawBitmap(app\d2dBmp, @rcBmpDest, 1, #D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, @rcBmpSrc)
    
		hr = app\renderTarget\EndDraw(@tag1, @tag2)
	EndIf
	
	If (hr = #D2DERR_RECREATE_TARGET)
		hr = #S_OK
		app_discardDeviceDependentResources()
	EndIf 
	
	ProcedureReturn hr
EndProcedure

Procedure win_proc(hwnd.i, msg.l, wparam.i, lparam.i)	
	Select msg
		Case #WM_SIZE
			app_onSize(PeekW(@lparam), PeekW(@lparam + SizeOf(Word)))
			
		Case #WM_DISPLAYCHANGE
			InvalidateRect_(hwnd, #Null, #False)
 			
		Case #WM_ERASEBKGND
			Protected.RECT rc
			
			GetClientRect_(hwnd, @rc)
			app_onSize(rc\right, rc\bottom)
			app_onRender()
			ProcedureReturn 1
			
		Case #WM_PAINT
			app_onRender()
			ValidateRect_(hwnd, #Null)
			ProcedureReturn 0
	EndSelect
	
	ProcedureReturn CallWindowProc_(app\oldProc, hwnd, msg, wparam, lparam)
EndProcedure

Procedure main()
	Protected.l ev
	
	If app_createDeviceIndependentResources() <> #S_OK
		MessageRequester("Error" , "Failed to initialize Direct2D")
		End
	EndIf
		
	app\win = OpenWindow(#PB_Any, 10, 10, 600, 400, "Demo Bitmap", #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | 
		#PB_Window_SizeGadget)
	app\oldProc = SetWindowLongPtr_(WindowID(app\win), #GWLP_WNDPROC, @win_proc())
	
	app\menu = CreateMenu(#PB_Any, WindowID(app\win))
	MenuTitle("File")
	MenuItem(#MENU_ID_SAVE, "Save")
	BindMenuEvent(app\menu, #MENU_ID_SAVE, @app_saveImage())
	
	Repeat
		ev = WaitWindowEvent()
		
	Until ev = #PB_Event_CloseWindow
	
	app_release()
EndProcedure

main()
Post Reply