Screensaver Hell! Help! [Long Post]

Everything else that doesn't fall into one of the other PB categories.
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Screensaver Hell! Help! [Long Post]

Post by Kale »

Im having trouble with this piece of code. Its basically a screen saver template, which i am trying to make as generic as possible for later re-use. The problem i have is that i can't seen to get the preview working as it should.

As you (may or may not) know screensavers just pass different command line parameters to the .exe to do different things '/s' for screensaver, '/c' for config and also '/p' for preview. Along with the '/p' there is also the handle to the preview window passed like this '/p:2165', i have no trouble parsing this and getting the handle, BUT when i try to display anything in this window i run into problems, i think its my inexperience with child windows. This is my code:

Code: Select all

;===========================================================================
;-GLOBAL FLAGS / VARIABLES / STRUCTURES / ARRAYS
;===========================================================================

Global screenWidth.l
Global screenHeight.l
Global previewFlag.l
Global parameter.s
Global prevWinHndlString.s
Global prevWinHndl.l
Global prevThreadID.l

screensaverName.s = "PureBasic ScreenSaver"
screenWidth.l = GetSystemMetrics_(#SM_CXSCREEN)
screenHeight.l = GetSystemMetrics_(#SM_CYSCREEN)

parameter = UCase(ProgramParameter())
If Len(parameter) > 2
    prevWinHndlString = RemoveString(parameter, Left(parameter, 3), 1)
    parameter = RemoveString(parameter, Left(parameter, 1), 1)
    parameter = Left(parameter, 1)
Else
    parameter = RemoveString(parameter, Left(parameter, 1), 1)
    prevWinHndlString = ProgramParameter()
    If FindString(prevWinHndlString, "-", 0) <> 0 : prevWinHndlString = RemoveString(prevWinHndlString, "-", 1) : EndIf
    If FindString(prevWinHndlString, "/", 0) <> 0 : prevWinHndlString = RemoveString(prevWinHndlString, "/", 1) : EndIf
EndIf
prevWinHndl = Val(prevWinHndlString)

;===========================================================================
;-PROCEDURES
;===========================================================================

;simple error checking
Procedure HandleError(result, text.s)
    If result = 0 : MessageRequester("Error", text, #PB_MessageRequester_Ok) : End : EndIf
EndProcedure

;start only one screensaver
Procedure OnlyOneSCRStart(screensaverName.s)
    *MutexName = @screensaverName
    Shared OnlyOneStartMutex.l
    OnlyOneStartMutex = CreateMutex_(0, 1, *MutexName)
    OnlyOneStartError.l = GetLastError_()
    If OnlyOneStartMutex <> 0 And OnlyOneStartError = 0
        ProcedureReturn 1
    Else
        CloseHandle_(OnlyOneStartMutex)
        End
    EndIf
EndProcedure

;close the screensaver
Procedure OnlyOneSCRStop()
    CloseHandle_(OnlyOneStartMutex)
EndProcedure

;execute the preview in the little mini monitor in 'Display Properties'
Procedure ExecutePreview()
    previewWindowSize.RECT
    GetClientRect_(prevWinHndl, @previewWindowSize)

    CatchImage(1, ?PreviewImage)
    HandleError(CreateGadgetList(prevWinHndl), "Gadget list in preview panel could not be created!")
    ImageGadget(1, 0, 0, previewWindowSize\right, previewWindowSize\bottom, UseImage(1))
    
    Repeat
        EventID.l = WaitWindowEvent()
    Until EventID = #PB_EventCloseWindow

EndProcedure

;run the fullscreen screensaver code
Procedure ExecuteScreenSaver()
    Shared screensaverName
    SystemParametersInfo_(#SPI_SCREENSAVERRUNNING, 1, @oldval, 0)
    ShowCursor_(0)
    
    HandleError(OpenScreen(screenWidth, screenHeight, 32, screensaverName), "A fullscreen screen could not be opened!")

CatchSprite(0, ?PBLogo, 0)
XMax = (GetSystemMetrics_(#SM_CXSCREEN)/2)-(SpriteWidth(0)/2)
YMax = (GetSystemMetrics_(#SM_CYSCREEN)/2)-(SpriteHeight(0)/2)
    
    Repeat

ClearScreen(0,0,0)
DisplaySprite(0, XMax+x, YMax+x)
DisplaySprite(0, XMax-x, YMax-x)
DisplaySprite(0, XMax+x, YMax-x)
DisplaySprite(0, XMax-x, YMax+x)
DisplaySprite(0, XMax+x, YMax)
DisplaySprite(0, XMax-x, YMax)
DisplaySprite(0, XMax, YMax+x)
DisplaySprite(0, XMax, YMax-x)
If x < XMax And Pos = 0 : x+1 : Pos = 0 : EndIf
If x = XMax And Pos = 0 : x-1 : Pos = 1 : EndIf
If x < XMax And Pos = 1 : x-1 : Pos = 1 : EndIf
If x = 0 And Pos = 1 : x+1 : Pos = 0 : EndIf
FlipBuffers()

        Delay(1)
        ExamineKeyboard()
        ExamineMouse()
    Until KeyboardPushed(#PB_Key_All) Or MouseDeltaX() <> 0 Or MouseDeltaY() <> 0 Or MouseWheel() <> 0 Or MouseButton(1) <> 0 Or MouseButton(2) <> 0
    ShowCursor_(1)
    SystemParametersInfo_(#SPI_SCREENSAVERRUNNING, 0, @oldval, 0)
    End
EndProcedure

;===========================================================================
;-CONFIG GEOMETRY
;===========================================================================

;configuration window
Procedure Config()
    Shared screensaverName
    If OpenWindow(0, 0, 0, 320, 240, #PB_Window_SystemMenu | #PB_Window_WindowCentered, screensaverName)
        Repeat
            EventID.l = WaitWindowEvent()
        Until EventID = #PB_EventCloseWindow
    EndIf
    End
EndProcedure

;===========================================================================
;-MAIN
;===========================================================================

OnlyOneSCRStart(screensaverName)

;deal with the parameters passed to this program
Select parameter
    Case "" ;double clicked
        Config()
    Case "A" ;check password
        End
    Case "C" ;'Settings' button clicked in the screensaver dialog
        Config()
    Case "P" ;when the preview is requested in the screensaver dialog by selecting this screensaver
        ExecutePreview()
    Case "S" ;launch the main screensaver after an interval or by pressing 'Preview' in the dialog
        HandleError(InitSprite(), "DirectX v7.0 or above can not be found or initialised!")
        HandleError(InitKeyboard(), "DirectX v7.0 or above can not be found or initialised!")
        HandleError(InitMouse(), "DirectX v7.0 or above can not be found or initialised!")
        ExecuteScreenSaver()
EndSelect

OnlyOneSCRStop()
End

;===========================================================================
;-BINARY INCLUDES
;===========================================================================

PBLogo:
    IncludeBinary "PureBasic.bmp"
    
PreviewImage:
    IncludeBinary "preview.bmp"
now when the preview.bmp is displayed it is fine, the only problem is i can't seem to get the .exe to quit when i want to do something else, i.e. bring up the config dialog or watch the screensaver fullscreen. When i quit the display properties dialog the .exe is still running in the background. Any Ideas? this has been driving me nuts for weeks.

I have tried an API approach using this as a guide:
viewtopic.php?t=2658

but that piece of code confuses the hell out of me and its not very generic. I'm trying to write a screensaver template to use a PB screen using OpenScreen() for nice graphics and to be reuseable for lots of savers, etc... I'm nearly there i just need this .bmp in the preview window sorting. :cry:
Big thanks to anyone who can help.
--Kale

Image
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

anybody any ideas? or examples? :cry:
--Kale

Image
Fred
Administrator
Administrator
Posts: 18351
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

Unfortunately not...
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

he he, ok i'll figure it out. :)
--Kale

Image
dontmailme
Enthusiast
Enthusiast
Posts: 537
Joined: Wed Oct 29, 2003 10:35 am

Post by dontmailme »

did you find out how to stop this happening ? It would be interesting to try this out.
Paid up PB User !
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

Yeah figured it out and learned a hell of alot since this old post :) I've been looking into the WinAPI in more depth since then. This is how i display a piccie in the small monitor window and behaving as a normal child should when the 'P' parameter has been passed to the saver.

Code: Select all

;preview window callback
Procedure PreviewCallback(hWnd, Message, wParam, lParam) 
    Select Message
        Case #WM_CLOSE
            UnregisterClass_("PreviewWindowClass", GetModuleHandle_(#NULL)) 
            Destroywindow_(hWnd)
            End 
    EndSelect
    Result = DefWindowProc_(hWnd, Message, wParam, lParam) 
    ProcedureReturn Result
EndProcedure

;execute the preview in the little mini monitor in 'Display Properties'
Procedure ExecutePreview()
    PreviewWindowSize.RECT
    GetClientRect_(PrevWinHndl, @PreviewWindowSize)
    PreviewWindowClass.WNDCLASS
    Classname.s = "PreviewWindowClass"
    PreviewWindowClass\style = #CS_HREDRAW | #CS_VREDRAW
    PreviewWindowClass\lpfnWndProc = @PreviewCallback()
    PreviewWindowClass\cbClsExtra = 0
    PreviewWindowClass\cbWndExtra = 0
    PreviewWindowClass\hInstance = GetModuleHandle_(#NULL)
    PreviewWindowClass\hIcon = 0
    PreviewWindowClass\hCursor = 0
    PreviewWindowClass\hbrBackground = 0
    PreviewWindowClass\lpszMenuName = 0
    PreviewWindowClass\lpszClassName = @Classname
    RegisterClass_(PreviewWindowClass)
    hWnd.l = CreateWindowEx_(0, "PreviewWindowClass", "", #WS_CHILD | #WS_VISIBLE, 0, 0, PreviewWindowSize\right, PreviewWindowSize\bottom, PrevWinHndl, 0, GetModuleHandle_(#NULL), 0) 
    If hWnd
        CatchImage(1, ?PreviewImage)
        HandleError(CreateGadgetList(hWnd), "Gadget list in preview window could not be created!")
        ImageGadget(1, 0, 0, PreviewWindowSize\right, PreviewWindowSize\bottom, UseImage(1))
        While Getmessage_(Message.MSG, 0, 0, 0)
            TranslateMessage_(Message)
            DispatchMessage_(Message)
        Wend
    EndIf
EndProcedure
--Kale

Image
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

screensaver preview code is perfect!

Post by netmaestro »

Thanks for this, it's just the ticket and works perfectly.
Last edited by netmaestro on Wed Feb 22, 2006 7:42 am, edited 2 times in total.
BERESHEIT
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

Heres the downloadable source of the above (working) screensaver.

http://www.garyw.uklinux.net/pb/Screens ... Source.zip
--Kale

Image
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

One thing I discovered you need to make your saver act like the pros is a GetFocus_() check in your status routine. If something else has focus, die. Otherwise, you could get up in the morning and find something's started in the night and your screensaver's running on the taskbar. No place for a professional saver at all.
Last edited by netmaestro on Wed Feb 22, 2006 7:41 am, edited 2 times in total.
BERESHEIT
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

Handy Tip! :)
--Kale

Image
Post Reply