DirectX + Alt + Tab

Just starting out? Need help? Post your questions and find answers here.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

DirectX + Alt + Tab

Post by blueznl »

After searching through these forums, and browsing the game section, and reading the FAQ, I still do not have a fail safe solution...

I want to be able to Alt+Tab from a full screen PureBasic application back to the desktop, and then back to my application, without the application crashing... How do I o that?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Re: DirectX + Alt + Tab

Post by Kaeru Gaman »

should work flawlessly... pse state an example that doesn't...
oh... and have a nice day.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: DirectX + Alt + Tab

Post by blueznl »

I am not sitting behind my machine right now, but I will do so tonight, yesterday every attempt at Alt+Tab crashed the application. Perhaps I screwed up? (I do sometimes, you know, that's how I ended up married :-))
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Re: DirectX + Alt + Tab

Post by Kaeru Gaman »

I'm not sure if there was a problem with calling FlipBuffers or ScreenOutput when the screen is inactive, whether we have to if it out or not...
but when you put everything concerning the screen after an If IsScreenActive and only a Delay after the Else, it should become rocksolid.
oh... and have a nice day.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: DirectX + Alt + Tab

Post by blueznl »

Well, it's an answer, but somewhat, euh... vague :-)

Could you modify the code below to show me what you mean? I'm clueless...

Code: Select all

InitKeyboard()
InitSprite()
InitSprite3D()
;
OpenScreen(1024,768,32,"Test",#PB_Screen_SmartSynchronization)
;
CreateImage(1,100,100,32)
StartDrawing(ImageOutput(1))
  DrawingMode(#PB_2DDrawing_AlphaChannel)
  Box(0,0,100,100,0)
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  BackColor(RGBA(0,0,0,0))
  FrontColor(RGBA(255,255,255,255))
  LineXY(4,95,49,5)
  LineXY(5,95,50,5)
  LineXY(50,5,95,95)
  LineXY(51,5,96,95)
  LineXY(95,95,50,85)
  LineXY(95,96,50,86)
  LineXY(50,85,5,95)
  LineXY(50,86,5,96)
  FillArea(45,20,-1,RGBA(255,0,0,96))
  LineXY(50,6,50,84,RGBA(128,128,128,96))
  FillArea(55,20,-1,RGBA(128,128,128,255))
StopDrawing()
;
CreateSprite(1,100,100,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(1))
  DrawImage(ImageID(1),0,0)
StopDrawing()
CreateSprite3D(1,1)
;
s = 5
a = 0
Repeat
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Escape)
    event = #PB_Event_CloseWindow
  EndIf
  If event = 0
    ClearScreen(0)
    For y = 0 To 1
      For xx = 0 To 1
        For x = 0 To 7
          RotateSprite3D(1,angle,#PB_Absolute)
          Start3D()
            Sprite3DBlendingMode(s,xx*8+x)
            DisplaySprite3D(1+a,30+x*125,10+xx*170+y*410)
            DisplaySprite3D(1+a,50+x*125,30+xx*170+y*410)
          Stop3D()
          StartDrawing(ScreenOutput())
            DrawingMode(#PB_2DDrawing_Transparent)
            DrawText(60+x*125,150+xx*170+y*410,Str(s)+" , "+Str(xx*8+x),RGB(255,255,255)*(1-y))
          StopDrawing()
        Next x
      Next xx
    Next y
    angle = (angle+1) % 360
    FlipBuffers()
  EndIf
Until event = #PB_Event_CloseWindow
;
CloseScreen()
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
STARGÅTE
Addict
Addict
Posts: 2236
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: DirectX + Alt + Tab

Post by STARGÅTE »

PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Re: DirectX + Alt + Tab

Post by Kaeru Gaman »

I'll read that code tomorrow, watching The Closer atm and Black Cristmas afterwards.
gnight
oh... and have a nice day.
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: DirectX + Alt + Tab

Post by Demivec »

STARGÅTE wrote:same problem as here:
http://www.purebasic.fr/english/viewtop ... =4&t=35669
I noticed all the same symptoms that were posted in that thread when applying the needed corrections to blueznl's code sample above. The needed corrections were prevented from functioning. :(

The most notable problem was that Flipbuffers() can't be called if the screen isn't active and that IsScreenActive() won't indicate the screen is active again without calling Flipbuffers() to update the status of the screen. :shock:

This observation may apply to the bug-thread dealing with threaded apps also.


@Edit: I incorrectly combined separate symptoms, from each of the solutions I was trying, into the observation I stated above. The problem didn't relate directly to FlipBuffers(). FlipBuffers() appeared to work fine (no faults). The problem was that the screen does not become active again when the program is selected again. When this happens IsScreenActive() always returns '0' and none of the screen functions appear to work. I think this is something the developers will have to remedy.
Last edited by Demivec on Sat Dec 19, 2009 11:14 pm, edited 1 time in total.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: DirectX + Alt + Tab

Post by blueznl »

I found some code in a (french) tutorial from 'B-games'. That code works with DirectX7 but NOT with DirectX9.

Makes me wonder if DirectX9 in PureBasic is yet mature enoug to be used as default...

There's also good news: DirectX7 synchronisation has become much better since previous versions...
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: DirectX + Alt + Tab

Post by djes »

This is a code I've done some months ago showing (among other things) how to do. See and adapt check_lostfocus() procedure.

Code: Select all

;******************************************************************************************************
;* Rasterline and VBL Sync
;* By djes (djes@free.fr) 03/24/2009
;* Thanx to Stefan Moebius for VBL sync examples
;* Note : I do not check functions return codes : I know it's bad!
;* PB 4.3
;* 12/21/09 : PB 4.40
;******************************************************************************************************

#STARS_NB = 50
#D3D_OK = 0

;******************************************************************************************************

Structure D3DRASTER_STATUS
  InVBlank.l
  ScanLine.l
EndStructure

Structure pos
  x.l
  y.l
  speed.l
EndStructure

;******************************************************************************************************

Define.D3DRASTER_STATUS raster
Define.IDirect3DDevice9 D3Ddevice_interface

Dim stars.pos(#STARS_NB)

;******************************************************************************************************
;-                                            PROCEDURES
;******************************************************************************************************
;wait for the vblank to start
;attend le début de la synchro vbl
Procedure vblank_wait()
	Shared D3Ddevice_interface, raster, exit
  Repeat
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Escape) 
      exit=#True
    EndIf
    D3Ddevice_interface\GetRasterStatus(0, @raster)
  Until raster\InVBlank=#True Or exit 
EndProcedure

;******************************************************************************************************
;wait for the vblank to finish
;attend la fin de la synchro vbl
Procedure vblank_end_wait()
	Shared D3Ddevice_interface, raster, exit
  Repeat
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Escape) 
      exit=#True
    EndIf
    D3Ddevice_interface\GetRasterStatus(0, @raster)
  Until raster\InVBlank=#False Or exit
EndProcedure

;******************************************************************************************************
;récupère la position du raster et y affiche une ligne de la couleur indiquée
Procedure rasterline(color.l)
  Shared raster, D3Ddevice_interface
  StartDrawing(ScreenOutput())
  D3Ddevice_interface\GetRasterStatus(0, @raster)
  LineXY(0, raster\ScanLine, 1023, raster\ScanLine, color)
  StopDrawing()
EndProcedure

;******************************************************************************************************
Procedure create_sprites()
	CreateSprite(0, 64, 64)
	StartDrawing(SpriteOutput(0))
	Circle(32, 32, 31, RGB($FF, $FF, $FF))
	StopDrawing()
EndProcedure

;******************************************************************************************************
;Open screen and get the device - Ouvre l'écran et récupère le device
Procedure init_display()
	Shared *SwapChain_interface, D3Ddevice_interface
	OpenScreen(1024, 768, 32, "", #PB_Screen_NoSynchronization)
	!extrn _PB_Screen_Direct3DDevice
	!MOV dword EAX, [_PB_Screen_Direct3DDevice]
	!MOV dword [v_D3Ddevice_interface],EAX
EndProcedure

;******************************************************************************************************
;Check if the user has switched (and that we have lost focus) (ALT-TAB)
;Vérifie si l'utilisateur n'a pas changé d'appli (en nous faisant donc perdre le focus) (ALT-TAB)
Procedure check_lostfocus()
  
  If IsScreenActive() = 0

		ReleaseMouse(1)

		;we're lowering our priority - on baisse notre priorité
		SetPriorityClass_(  GetCurrentProcess_(), #NORMAL_PRIORITY_CLASS)
		SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_NORMAL) 
	  
		;Wait til our window is coming back to foreground - Attend que notre fenêtre repasse au premier plan
	  Repeat
	  	;now our events are to be processed with WaitWindowEvent, else IsScreenActive() will never say that our window has the focus again
	  	;it should be written in the doc!
	  	;maintenant les événements sont à gérer avec WaitWindowEvent, sinon IsScreenActive() ne dit jamais que notre fenêtre a à nouveau le focus
	  	;il faudrait mettre ça dans la doc!!!!
	  	WaitWindowEvent()	
	  Until IsScreenActive() <> 0

		ReleaseMouse(0)
		;Better recreate the screen - il vaut mieux recréer l'écran
		CloseScreen()
		init_display()
		;and the sprites too (have to!) - et les sprites aussi (indispensable)
		create_sprites()
		;give to the system some time to rest - laisse un peu le temps au système de récupérer
		Delay(2000)


		;We're waiting for the synchro a new time - On réattend la synchro
		vblank_wait()
		SetPriorityClass_(  GetCurrentProcess_(), #HIGH_PRIORITY_CLASS)
		SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_ABOVE_NORMAL)     ;warning : keyboard lock

  EndIf

EndProcedure

;******************************************************************************************************
;-                                             INIT
;******************************************************************************************************

InitSprite()
InitKeyboard()
InitMouse()

init_display()
create_sprites()

For i=0 To #STARS_NB-1
  stars(i)\x = Random(1023)
  stars(i)\y = Random(767)
  stars(i)\speed = Random(16) + 1
Next i

exit=#False

;we're giving priority boost to our process - on donne une priorité maximale à notre processus
SetPriorityClass_(  GetCurrentProcess_(), #REALTIME_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_TIME_CRITICAL)     ;warning : keyboard lock

;******************************************************************************************************
;-                                        MAIN LOOP    
;******************************************************************************************************

Repeat

	;wait for the sync - attends la synchro
	vblank_wait()

	;flip the buffers without the PB's sync - flippe le buffer sans utiliser la synchro PB
  FlipBuffers()

	;during VBL, lower a bit our priority to give time to OS (especially to handle the keyboard)
	;pendant la VBL, baisse un peu notre priorité pour donner un peu de temps au système (pour gérer le clavier surtout)
	SetPriorityClass_(  GetCurrentProcess_(), #HIGH_PRIORITY_CLASS)
	SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_NORMAL)

  ExamineKeyboard()
  ExamineMouse()

  If KeyboardPushed(#PB_Key_Escape) 
    exit=#True
  EndIf

	check_lostfocus()
  ClearScreen(0)
	;we're waiting for the VBL end (could be better!!!)
	;on attend la fin de la VBL (à améliorer) pour être sûr de ne pas sauter une frame
	vblank_end_wait()

	;we're giving priority boost to our process - on donne une priorité maximale à notre processus
	SetPriorityClass_(  GetCurrentProcess_(), #REALTIME_PRIORITY_CLASS)
	SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_TIME_CRITICAL)     ;warning : keyboard lock



  rasterline($FF0000)


	;-TEST CODE

	;compute our effect
  For i = 0 To #STARS_NB-1
    stars(i)\x + stars(i)\speed
    If stars(i)\x > 1023
      stars(i)\x - 1024 - 64
    EndIf
  Next i

	;draw it
  For i = 0 To #STARS_NB-1
    DisplayTranslucentSprite(0, stars(i)\x, stars(i)\y, stars(i)\speed<<4)
  Next i

	;-END TEST CODE

	;draw a rasterline to see (visually) how much time our fx is taking
	;affiche une rasterline pour visualiser combien de temps prend notre effet
  rasterline($FF00)

Until exit 

CloseScreen()

End

;******************************************************************************************************
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: DirectX + Alt + Tab

Post by blueznl »

Thx... but this can't be for real, I mean, the idea behind basic is that it's a basic language hiding some complexity from the user... I hope the PBDevs can cook up something that makes this kind of thing easy on the mind of the (beginning) programmer...
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: DirectX + Alt + Tab

Post by djes »

Forget most of the code, just use this :

Code: Select all

;******************************************************************************************************
;Check if the user has switched (and that we have lost focus) (ALT-TAB)
;Vérifie si l'utilisateur n'a pas changé d'appli (en nous faisant donc perdre le focus) (ALT-TAB)
Procedure check_lostfocus()
 
  If IsScreenActive() = 0

      ReleaseMouse(1)
  
      ;Wait til our window is coming back to foreground - Attend que notre fenêtre repasse au premier plan
     Repeat
        ;now our events are to be processed with WaitWindowEvent, else IsScreenActive() will never say that our window has the focus again
        ;it should be written in the doc!
        ;maintenant les événements sont à gérer avec WaitWindowEvent, sinon IsScreenActive() ne dit jamais que notre fenêtre a à nouveau le focus
        ;il faudrait mettre ça dans la doc!!!!
        WaitWindowEvent()   
     Until IsScreenActive() <> 0

      ReleaseMouse(0)
     ;--- Optional
      ;Better recreate the screen - il vaut mieux recréer l'écran
      CloseScreen()
      init_display()
      ;and the sprites too (have to!) - et les sprites aussi (indispensable)
      create_sprites()
      ;give to the system some time to rest - laisse un peu le temps au système de récupérer
      Delay(2000)
     ;---

  EndIf

EndProcedure
It's not that hard...
Post Reply