Fullscreen window with OpenWindowScreen

Share your advanced PureBasic knowledge/code with the community.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Fullscreen window with OpenWindowScreen

Post by Rescator »

Code updated for 5.20+

Simple example.
Please note the macro used to make the second window a topmost,
this is to avoid the taskbar eating up part of the window
when you move the window near the bottom of the screen.
The main window is allready a topmost automatically.

Code: Select all

Macro MakeWindowTopmost(window)
 SetWindowPos_(WindowID(window),#HWND_TOPMOST,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_FRAMECHANGED)
EndMacro

InitSprite()
InitKeyboard()

#Flags=#PB_Window_Invisible|#PB_Window_Maximize|#PB_Window_BorderLess
OpenWindow(0,0,0,800,600,"our screen",#Flags)
HideWindow(0,#False)
SmartWindowRefresh(0,#True)

OpenWindowedScreen(WindowID(0),0,0,WindowWidth(0),WindowHeight(0),0,0,0,#PB_Screen_NoSynchronization)

#Flags2=#PB_Window_Invisible|#PB_Window_SystemMenu|#PB_Window_WindowCentered|#PB_Window_BorderLess
OpenWindow(1,0,0,200,200,"screen "+Str(WindowWidth(0))+"x"+Str(WindowHeight(0)),#Flags2,WindowID(0))
MakeWindowTopmost(1)

ButtonGadget(0,0,0,100,20,"Draw circle")
WebGadget(1,0,20,WindowWidth(1),WindowHeight(1)-20,"http://www.purebasic.com")
HideWindow(1,#False)
SmartWindowRefresh(1,#True)

Repeat
 Event=WaitWindowEvent(1)
 If Event=#PB_Event_Gadget
  If EventGadget()=0
   StartDrawing(ScreenOutput())
   Circle(Random(WindowWidth(0)-1),Random(WindowHeight(0)-1),50,Random($FFFFFF))
   StopDrawing()
   FlipBuffers()
  EndIf
 EndIf
Until Event=#PB_Event_CloseWindow
Advanced example, with a procedure to toggle the fullscreen,
make sure though that you close and re open the screen
as any resize will shut down the screen and fre it's buffer.
See PB manual about this under OpenWindowScreen()

Code: Select all

;Example: PB4 Beta 10

Procedure.l SetFullscreenMode(window.l,state.l)
 Static style.l,x.l,y.l,w.l,h.l,mode.l=#False,oldwindow.l
 Define.l hwnd
 If ((window=-1) And (state=-1)) : ProcedureReturn mode : EndIf
 If IsWindow(window)=#False : ProcedureReturn #False : EndIf
 hwnd=WindowID(window)
 If ((mode=#False) And (state=#True))
  style=GetWindowLong_(hwnd,#GWL_STYLE)
  oldwindow=window
  mode=#True
  x=WindowX(window)
  y=WindowX(window)
  w=WindowWidth(window)
  h=WindowHeight(window)
  SetWindowLong_(hwnd,#GWL_STYLE,#WS_POPUP)
  SetWindowPos_(hwnd,#HWND_TOP,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_NOZORDER|#SWP_FRAMECHANGED)
  ShowWindow_(hwnd,#SW_MAXIMIZE)
 Else
  If ((mode=#True) And (oldwindow=window))
   SetWindowLong_(hwnd,#GWL_STYLE,style)
   SetWindowPos_(hwnd,#HWND_NOTOPMOST,x,y,w,h,#SWP_FRAMECHANGED)
   ShowWindow_(hwnd,#SW_NORMAL)
   mode=#False
  Else
   ProcedureReturn #False
  EndIf
 EndIf
 ProcedureReturn #True
EndProcedure

Macro GetFullscreenMode() ;Returns #True if there currently is a fullscreen, #False if not. 
 SetFullscreenMode(-1,-1)
EndMacro

Macro MakeWindowTopmost(window)
 SetWindowPos_(WindowID(window),#HWND_TOPMOST,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_FRAMECHANGED)
EndMacro

InitSprite()
InitKeyboard()

#Flags=#PB_Window_Invisible|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered
OpenWindow(0,0,0,800,600,"our screen",#Flags)
HideWindow(0,#False)
SmartWindowRefresh(0,#True)

SetFullscreenMode(0,#True)
OpenWindowedScreen(WindowID(0),0,0,WindowWidth(0),WindowHeight(0),0,0,0,#PB_Screen_NoSynchronization)

#Flags2=#PB_Window_Invisible|#PB_Window_SystemMenu|#PB_Window_WindowCentered|#PB_Window_BorderLess|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered
OpenWindow(1,0,0,200,200,"screen "+Str(WindowWidth(0))+"x"+Str(WindowHeight(0)),#Flags2,WindowID(0))
MakeWindowTopmost(1)

ButtonGadget(0,0,0,100,20,"Draw circle")
WebGadget(1,0,20,WindowWidth(1),WindowHeight(1)-20,"http://www.purebasic.com")
HideWindow(1,#False)
SmartWindowRefresh(1,#True)

Repeat
 Event=WaitWindowEvent(1)
 If Event=#PB_Event_Gadget
  If EventGadget()=0
   StartDrawing(ScreenOutput())
   Circle(Random(WindowWidth(0)-1),Random(WindowHeight(0)-1),50,Random($FFFFFF))
   StopDrawing()
   FlipBuffers()
  EndIf
 EndIf
Until Event=#PB_Event_CloseWindow
Note!
If you minimize the second window or maximize it,
you will notice that it is still restricted by the workspace defaults.
Please see http://support.microsoft.com/default.as ... -us;179363
for more details on why this behaviour exist!
It is possible to override this but that is beyond the scope of these two examples!
Feel free to add improvements or variations of the examples to this thread if you have ideas or suggestions!
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Here is another example, a very simple one though!
But it shows the potential of a Windowed Screen and a skinned Game GUI.

This example also has a nifty little fade effect like you see in many games when you pause the game and bring up the game menu.
I made this routine since you can not use gamma fading in windowed screens.

Please note that there is both asm and PB code,
I only left the PB code so you can compare the two,
as for some reason I do not notice that much of a speed difference.
El Choni hinted to using MMX asm instructions, sadly my ASM skill's is far from good so I'm not gonna try that first.
Feel free anyone else to give it a shot though!

Code: Select all

Procedure SetWindowBackgroundBrush(window,image)
 Define.l brush
 brush=CreatePatternBrush_(ImageID(image))
 If brush
  SetClassLong_(WindowID(window),#GCL_HBRBACKGROUND,brush)
 EndIf
 ProcedureReturn brush
EndProcedure

Macro FreeWindowBackgroundBrush(brush)
 DeleteObject_(brush)
EndMacro

InitSprite()
InitKeyboard()

#Flags=#PB_Window_Invisible|#PB_Window_Maximize|#PB_Window_BorderLess
OpenWindow(0,0,0,800,600,"our screen",#Flags)
HideWindow(0,#False)
SmartWindowRefresh(0,#True) ;Keep this #True as the window is fully covered by the screen anyway!

OpenWindowedScreen(WindowID(0),0,0,WindowWidth(0),WindowHeight(0),0,0,0)

;#Flags2=#PB_Window_Invisible|#PB_Window_SystemMenu|#PB_Window_WindowCentered|#PB_Window_BorderLess
#Flags2=#PB_Window_Invisible|#PB_Window_WindowCentered|#PB_Window_BorderLess
OpenWindow(1,0,0,500,320,"screen "+Str(WindowWidth(0))+"x"+Str(WindowHeight(0)),#Flags2,WindowID(0))
CreateGadgetList(WindowID(1))

ButtonGadget(0,0,0,100,20,"Draw circle")
ButtonGadget(1,100,0,100,20,"Close")
ButtonGadget(2,200,0,100,20,"Fade/Unfade")
WebGadget(3,0,20,200,300,"http://www.purebasic.com")

UseJPEGImageDecoder()
UsePNGImageDecoder()
file$=OpenFileRequester("Choose Image","","Image|*.BMP;*.jpg;*.png",0)
If file$
 image=LoadImage(#PB_Any,file$)
 If image
  If ImageWidth(image)<>WindowWidth(1) Or ImageHeight(image)<>WindowHeight(1)
   ResizeImage(image,WindowWidth(1),WindowHeight(1))
  EndIf
  brush=SetWindowBackgroundBrush(1,image)
 EndIf
EndIf

HideWindow(1,#False)
SmartWindowRefresh(1,#False) ;has to be #False to avoid missing redraw of background!

paused=#False
*OldDrawingBuffer=#Null
Repeat
 Event=WaitWindowEvent(1)
 If Event=#PB_Event_Gadget
  If EventGadget()=0
   If paused=#False
    StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Default)
    Circle(Random(WindowWidth(0)-1),Random(WindowHeight(0)-1),50,Random($FFFFFF))
    StopDrawing()
    FlipBuffers(0)
   EndIf
  ElseIf EventGadget()=1
   Event=#PB_Event_CloseWindow
  ElseIf EventGadget()=2
   If paused=#False
    StartDrawing(ScreenOutput())
    *DrawingBuffer=DrawingBuffer()
    DrawingBufferPitch=DrawingBufferPitch()
    NumberOfLines=WindowHeight(0)
    DrawingBufferSize=DrawingBufferPitch*NumberOfLines
    *OldDrawingBuffer=AllocateMemory(DrawingBufferSize)
    *DrawingBufferEnd=*DrawingBuffer+DrawingBufferSize
    If *OldDrawingBuffer
     CopyMemory(*DrawingBuffer,*OldDrawingBuffer,DrawingBufferSize)

     !MOV dword ECX,dword [p_DrawingBuffer] ;move bufferpointer to ECX
     !MOV dword EDX,dword [p_DrawingBufferEnd] ;move bufferendpointer to EDX
     !drawloop: ;the start of our loop
     !MOV byte AL,byte [ECX] ;grab one byte from drawbuffer
     !SHR AL,1 ;Shift the bits of the byte 1 place to the right (same as divide by 2)
     !MOV byte [ECX],byte AL ;put the byte back into drawbuffer
     !INC ECX ;increase pointer by 1
     !CMP ECX,EDX ;is pointer the same as endpointer?
     !JB drawloop ;if not then continue looping

     ;Same as the asm loop but in PB code instead,
     ;the difference is not as large as one might think though! (i.e. PB is very fast)
     ;*pos.BYTE=*DrawingBuffer
     ;DrawingBufferPitch-1
     ;NumberOfLines-1
     ;For y=0 To NumberOfLines
     ; For x=0 To DrawingBufferPitch
     ;  *pos\b=(*pos\b&$FF)>>1
     ;  *pos+1
     ; Next
     ;Next
    EndIf
    StopDrawing()
    FlipBuffers(0)
    paused=#True
   Else
    If *OldDrawingBuffer
     StartDrawing(ScreenOutput())
     *DrawingBuffer=DrawingBuffer()
     CopyMemory(*OldDrawingBuffer,*DrawingBuffer,MemorySize(*OldDrawingBuffer))
     FreeMemory(*OldDrawingBuffer) : *OldDrawingBuffer=#Null
     StopDrawing()
     FlipBuffers(0)
    EndIf
    paused=#False
   EndIf
  EndIf
 EndIf
Until Event=#PB_Event_CloseWindow

If brush : FreeWindowBackgroundBrush(brush) : EndIf
Post Reply