B3D style scaling window

BlitzMax Forums/BlitzMax Programming/B3D style scaling window

Is there a way to create a window in BMax that behaves in the same way that a scaled one would in B3D using the following command,

Graphics 640,480,32,3

Ideally, I want something that automatically scales the content of the window when resized.

Thanks for any help,

Jason.

If you use MaxGUI you can do it pretty easily - as you resize the window the attached canvas resizes also and the graphics are automatically scaled. Without MaxGUI is somewhat more difficult.

I`ve tried with MaxGui but the canvas stays the same size when I adjust the window. Do I need to resize the canvas myself in code?

Please could you provide a simple example? Thanks.

Jason.

as you resize the window the attached canvas resizes also and the graphics are automatically scaled.

I wouldn't have thought so.

On the Size event, you need to reset the viewport to the new dimensions. But this won't scale anything for you. You would need to calculate the 1:1 scale of the original dimensions to whatever was current, and then maybe call SetScale. (although SetScale isn't a true scaling function).

I`ve tried with MaxGui but the canvas stays the same size when I adjust the window. Do I need to resize the canvas myself in code?



The canvas can be resized by MaxGui automatically -> SetGadgetLayout
Your graphics need to be scaled by you, check out the Redraw() function

SuperStrict


Global	Window1:TGadget
Global	Canvas1:TGadget

		Window1:TGadget = CreateWindow:TGadget("Window1",68,62,392,246,Null,WINDOW_TITLEBAR|WINDOW_RESIZABLE |WINDOW_STATUS |WINDOW_CLIENTCOORDS )
			Canvas1:TGadget = CreateCanvas:TGadget(0,0,392,246,Window1:TGadget,Null)
				SetGadgetLayout( Canvas1:TGadget,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED )


Function MyHook:Object(iId:Int,tData:Object,tContext:Object)
  Local Event:TEvent=TEvent(tData)

  If event=Null Return Null
  If (Event.ID = EVENT_WINDOWSIZE) Or (Event.ID = EVENT_WINDOWMOVE) Or (Event.ID = Event_AppResume) Then 
		Redraw()
  End If
  Return tData
End Function

AddHook EmitEventHook , MyHook




Repeat
	WaitEvent()
	Select EventID()
		Case EVENT_WINDOWCLOSE
			Select EventSource()
				Case Window1	Window1_WC( Window1:TGadget )
			End Select

		Case EVENT_GADGETPAINT
			Select EventSource()
				Case Canvas1	Canvas1_GP( Canvas1:TGadget )
			End Select

	End Select
Forever

Function Window1_WC( Window:TGadget )
	DebugLog "Window Window1 wants to be closed"

	End
End Function

Function Canvas1_GP( Canvas:TGadget )
	DebugLog "Canvas Canvas1 needs to be redrawn"
	SetGraphics CanvasGraphics ( Canvas )
	SetViewport 0,0,GadgetWidth( Canvas ),GadgetHeight( Canvas )
	Redraw()
End Function


Function Redraw()
	Local ScaleX:Float = GadgetWidth(Canvas1 )/400.0,ScaleY:Float=GadgetHeight(Canvas1 )/300.0
	SetScale( ScaleX,ScaleY)
	SetGraphics CanvasGraphics ( Canvas1 )
	SetViewport 0,0,GadgetWidth( Canvas1 ),GadgetHeight( Canvas1 )
	SetColor( 208,216,61 )
	SetClsColor( 118,131,184 )
	Cls
	SetColor 255,0,0
	DrawOval GadgetWidth(canvas1)/2-(50*ScaleX),GadgetHeight(Canvas1)/2-(50*ScaleY),100,100
	Flip
End Function




Edit: Removed the background window

Instead of using maxGui, you can also change
Local style = WS_VISIBLE | WS_CAPTION | WS_SYSMENU
to
Local style = WS_OVERLAPPEDWINDOW |WS_VISIBLE 
in "d3d7graphics.bmx".
Same window styles must be used in "bbGLGraphicsCreateGraphics" in glgraphics.win32.c

?Win32
Local style=GetWindowLongA(GetActiveWindow(),GWL_STYLE)
SetWindowLongA GetActiveWindow(),GWL_STYLE,style|WS_SIZEBOX
?

Just insert that after you call Graphics. After that, you will need to reset the projection matrix each frame in case the user resizes the window.

?Win32
Extern "win32"
	Function UpdateWindow(hwnd)
	Function RedrawWindow(hwnd,updaterect:Int Ptr,region,flags)
End Extern 
Const RDW_INVALIDATE=$1
Const RDW_UPDATENOW=$100
Const RDW_FRAME=$400

Global _graphicshwnd,_currgraphics:TGraphics
Global _useogl=True

Function Graphics:TGraphics(width,height,depth=0,hertz=60,flags=0)
	_currgraphics=brl.Graphics.Graphics(width,height,depth,hertz,flags)
	_graphicshwnd=GetActiveWindow()
	Local style=GetWindowLongA(_graphicshwnd,GWL_STYLE)
	SetWindowLongA _graphicshwnd,GWL_STYLE,style|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
	RedrawWindow _graphicshwnd,Null,Null,RDW_INVALIDATE|RDW_UPDATENOW|RDW_FRAME
	AddHook FlipHook,ScaleGraphics,Null
	Return _currgraphics
End Function

Function SetGraphicsDriver(driver:TGraphicsDriver,defaultFlags=GRAPHICS_BACKBUFFER)
	Select driver
	Case GLGraphicsDriver(),GLMax2DDriver()
		_useogl=True
	Default
		_useogl=False
	End Select
	brl.Graphics.SetGraphicsDriver driver,defaultFlags
End Function

Function ScaleGraphics:Object(id,data:Object,context:Object)
	Local rect[4]
	GetClientRect _graphicshwnd,rect
	Local gwidth,gheight,gdepth,ghertz,gflags
	_currgraphics.GetSettings gwidth,gheight,gdepth,ghertz,gflags
	If _useogl		
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,gwidth,gheight,0,-1,1
		glMatrixMode GL_MODELVIEW
		glViewport 0,0,rect[2]-rect[0],rect[3]-rect[1]
	Else
		Local viewport:D3DVIEWPORT7=New D3DVIEWPORT7
		viewport.dwX=0
		viewport.dwY=0
		viewport.dwWidth=rect[2]-rect[0]
		viewport.dwHeight=rect[3]-rect[1]
		viewport.dvMinZ=0.0
		viewport.dvMaxZ=1.0
		D3D7Max2DDriver().device.SetViewport(viewport)
		Local depth=2
		Local matrix#[]=[2.0/gwidth,0.0,0.0,0.0,0.0,-2.0/gheight,0.0,0.0,0.0,0.0,2.0/depth,0.0,-1-(1.0/gwidth),1+(1.0/gheight),1.0,1.0]
		D3D7Max2DDriver().device.SetTransform(D3DTS_PROJECTION,matrix)
	EndIf
	Return data
End Function
?

That will allow the OpenGL to emulate Blitz3D's scalable window. All you have to do is copy and paste it into the bottom of you source file. I attempted to get the D3D7 driver to work but couldn't.

Thanks everyone, problem solved.

Jason.