Date: 02-16-2022
Return to Index
created by gbSnippets
'Most of us enjoy watching screensavers and have often wondered how to
'convert one of our graphics routines to a screensaver. This snippet
'show how it's done.
'In general, a screesaver is just an *.EXE program whose window takes
'up the entire computer screen, including covering the Taskbar at the
'bottom of the screen. The EXE file must be renamed as *.SCR and placed
'in the \Windows\System32 directory in order for it to be available to
'the Windows "Display Properties" application.
'Primary Code:
'For brevity, the primary code is presented only in the compilable example
'below. However, here is a list of the key code features:
'0. Fills entire screen/no border/covers task bar
'1. Settings dialog
'2. Always on top
'3. Respond to Mode commands from "Display Properties" application
' "/s" : Normal Mode
' "/p <hWnd>" : Preview Mode
' "/c <hWnd>" : Configuration Mode
'4. Remove cursor from screensaver, show cursor when screensaver closes
'5. Save Settings in INI file
'6. Capture ENTER or ESC in settings dialog'
'7. Capture any keyboard press
'8. Capture any mouse movement/click
'Limitations
'There are a few things this snippet does not handle.
'1. Passwords - no password entry, does not prevent use of Ctl-Alt-Del to bypass password
'2. Preview - does not display in the small preview window of the "Display Properties" app
'Notes:
'Graphics Canvas
'This snippet includes a dialog and a Graphic Control the same size
'as the dialog. All drawing takes place on the Graphic Control.
'ScreenSaver Sizing
'Screen dimensions are explicitly used to size the screensaver dialog.
'The %WS_Maximize dialog style could also have been used.
'Window Border/Windows Taskbar
'The WS_Popup style creates a borderless dialog and covers the Windows taskbar.
'Display Properties App
'This snippet responds to the mode commands /s, /p, and /c. It does not support
'the /a password setting mode. Mode commands are simply command switches used
'when the screensaver is started. To get to the Display Properties application,
'right-mouse click on the desktop and select Properties from the context menu.
'Multiple /s Commands
'Also, I've read, but have not seen it to be the case, that the /s mode
'command may be sent multiple times by Windows, so that the screensaver
'must recognize when it is already running. This snippet does not check
'to see if it is already running.
'Compilable Example: (Jose Includes)
'After compilation of this snippet to an EXE, you must manually change the
'extension to SCR and place the file in the \windows\system32 folder. It will
'then be visible from the Windows Display Properties application.
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
%Unicode=1
#Include "win32api.inc"
''========================================================================
''Change these as needed - specific to the screensaver
''========================================================================
Type mtxMatrixStruct
X As Long
Y As Long
CharsDistance As Long
BlackColorMix As Byte
PrintChar As String * 1
CurrentFlag As Long
End Type
Global mtxMatrix() As mtxMatrixStruct, mtxMatrixMax As Long
$Main_Title = "SCRNSAVE: Matrix:"
$Setting_Title = "Matrix Settings"
$INIFileName = "screensaver.ini"
''========================================================================
''End of change section
''========================================================================
Global hDlg As DWord, hGraphic as DWord, hSettings as DWord
Global w,h,TimerInterval, OldProc As Long
%ID_Graphic = 600 : %ID_Timer = 700
Function PBMain() As Long
Settings_INI "get"
Select Case Left$(LCase$(Command$(1)),2)
Case "/p" : DisplayInPreviewWindow 'preview window, then quit
Case "/a" : DisplayPassWordDialog 'password, then quit
Case "/c" : DisplaySettingsDialog 'settings, then quit
Case "/s" : DisplayScreenSaver 'start normally
Case Else : DisplayScreenSaver 'start normally
End Select
End Function
Sub DisplayScreenSaver
Desktop Get Size To w,h
Dialog New Pixels, 0, $Main_Title,0,0,w,h, %WS_Popup To hDlg
Control Add Graphic, hDlg, %ID_Graphic, "", 0,0,w,h,%WS_Visible
Control Handle hDlg, %ID_Graphic to hGraphic
Graphic Attach hDlg, %ID_Graphic, Redraw
Graphic Color %Green, %Black
Graphic Font "MS Serif", 28, 1
Graphic Clear
Dialog Show Modal hDlg Call DlgProc
End Sub
CallBack Function DlgProc() As Long
Select Case CB.Msg
Case %WM_InitDialog
SetWindowPos(hDlg, %HWND_TOPMOST, 0, 0, 0, 0, %SWP_NoMove Or %SWP_NoSize) 'on Top
InitializeGraphics
OldProc = SetWindowLong(hGraphic, %GWL_WndProc, CodePTR(NewGraphicProc)) 'subclass
ShowCursor(%False)
SetTimer(CB.Hndl, %ID_Timer, TimerInterval, ByVal %NULL) 'uses callback messages
Dialog Post CB.Hndl, %WM_Timer, %ID_TIMER, 0 ' optional - forces an initial %WM_TIMER "event"
Case %WM_SetCursor
Static iCount as Long
Incr iCount
If iCount > 5 Then Dialog End hDlg
Case %WM_Timer
DisplayGraphics
Case %WM_Destroy
SetWindowLong hGraphic, %GWL_WNDPROC, OldProc 'un-subclass
ShowCursor(%True)
KillTimer CB.Hndl, %ID_Timer
Settings_INI "save"
End Select
End Function
Function NewGraphicProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case Msg
Case %WM_Char
Dialog End hDlg
End Select
Function = CallWindowProc(OldProc, hWnd, Msg, wParam, lParam)
End Function
Sub DisplayInPreviewWindow
'not supported as this time. this Sub is a placeholder for when the
'Display Properties calls the screensaver with the /p preview mode command.
Dialog End hDlg 'not supported at this time
Exit Sub
' The following code does not work. I found this in some VB6 examples,
' but haven't gotten it to work in PowerBASIC so far. Basically, the
' code is supposed to set the screensaver dialog as a child of the
' Preview Window so that the screensaver will play in that smaller window.
' I included it here in case anyone feels the urge to play with it.
Local lngStyle As Long, dispHWND As Long, DispRec As RECT, temp$
temp$ = Command$(1)
Replace "/p" With "" in temp$
dispHWND = Val(Trim$(temp$))
GetClientRect dispHWND, DispRec
lngStyle = GetWindowLong(hDlg, %GWL_STYLE)
lngStyle = lngStyle Or %WS_CHILD 'Append "WS_CHILD"
SetWindowLong hDlg, %GWL_STYLE, lngStyle
SetParent hDlg, dispHWND
SetWindowLong hDlg, %GWL_HWNDPARENT, dispHWND
SetWindowPos hDlg, %HWND_TOP, 0&, 0&, _
DispRec.nRight, DispRec.nBottom, _
%SWP_NOZORDER Or %SWP_NOACTIVATE Or %SWP_SHOWWINDOW
End Sub
''================================================================================
''Change below this line as needed - specific to the screensaver
''================================================================================
Sub Settings_INI(Task$)
'This sub saves settings to an INI file wherever the SCR file is placed.
'Each setting corresponds to a Global variable
'To call, use one of these: Settings_INI("get") or Setting_INI("save")
'Examples of saving Numeric and String variable are shown
Local temp As Asciiz*%Max_Path, INIFileName As Asciiz*%Max_Path
'defines file name (any file name will work)
INIFileName = Exe.Path$ + $INIFileName
If Task$ = "get" Then
'get value for numeric variable
Getprivateprofilestring "Settings", "TimerInterval", "20", temp, %Max_Path, INIFileName
TimerInterval = Val(temp)
'get value for string variable
' Getprivateprofilestring "Settings", "UnusedString", "20", temp, %Max_Path, INIFileName
' UnsedString = temp
End If
If Task$ = "save" Then
'save numeric variable
temp = Str$(TimerInterval)
WritePrivateProfileString "Settings", "TimerInterval", temp, INIFileName
'save string variable
' temp = Str$(UnusedString)
' WritePrivateProfileString "Settings", "UnusedString", temp, INIFileName
End If
End Sub
Sub InitializeGraphics
ReDim mtxMatrix(100)
Local i As Long
Randomize
mtxMatrixMax = 100
For i = 0 To mtxMatrixMax
mtxMatrix(i).X = Rnd(1,w) 'graphic width
mtxMatrix(i).Y = Rnd(1,h) 'graphic height
mtxMatrix(i).CharsDistance = Rnd(5,15) 'Distance between chars
mtxMatrix(i).BlackColorMix = Rnd(0,255) 'Green to black color
mtxMatrix(i).PrintChar = Chr$(Rnd*1)
mtxMatrix(i).CurrentFlag = 0 'Display chars or black box
Next i
End Sub
Sub DisplayGraphics
Local i As Long, k As Long
k = 25
For i = 0 To mtxMatrixMax 'Draw one char at each designated position
mtxMatrix(i).Y = mtxMatrix(i).Y + mtxMatrix(i).CharsDistance
If mtxMatrix(i).Y > h Then
mtxMatrix(i).CurrentFlag = mtxMatrix(i).CurrentFlag XOR 1 'chars or black box
mtxMatrix(i).Y = -1
If mtxMatrix(i).CurrentFlag Then mtxMatrix(i).X = Rnd(0,w) 'new x location
mtxMatrix(i).BlackColorMix = Rnd(0,255) 'New random color for the chars
End If
mtxMatrix(i).PrintChar = Chr$(Rnd(0,255))
Graphic Set Pos (mtxMatrix(i).X, mtxMatrix(i).Y) 'Locate the cursor to print
'print greenish character or black box at new XY position
If mtxMatrix(i).CurrentFlag = 0 Then 'Display black block - to erase previously displayed chars
Graphic Box (mtxMatrix(i).X, mtxMatrix(i).Y)-((mtxMatrix(i).X + k), (mtxMatrix(i).Y) + k), %Black, %Black
Else 'Display characters
Graphic Color Rgb(25, mtxMatrix(i).BlackColorMix, 25), %Black
Graphic Print mtxMatrix(i).PrintChar
End If
Next i
Graphic Redraw
End Sub
Sub DisplayPasswordDialog()
'not supported
End Sub
Sub DisplaySettingsDialog()
Dialog New Pixels, hDlg, $Setting_Title, (w-200)/2,(h-200)/2,200,200, %WS_SysMenu Or %WS_Caption Or %WS_ClipChildren To hSettings
Dialog Set Icon hSettings, "aainfo"
Control Add Label, hSettings, 800, "Timer Interval (ms):", 50, 60, 100, 20
Control Add TextBox, hSettings, 900, "20", 50, 80, 100, 20
Control Set Text hSettings, 900, Str$(TimerInterval)
Dialog Show Modal hSettings Call SettingsProc
End Sub
CallBack Function SettingsProc() As Long
Local temp$
Select Case CB.Msg
Case %WM_Command
If CB.Ctl = %IDOK Then Dialog End hSettings
If CB.Ctl = %IDCANCEL Then Dialog End hSettings
Case %WM_Destroy
Control Get Text hSettings, 900 To temp$
TimerInterval = Val(temp$)
If TimerInterval <=0 Then TimerInterval = 1
Settings_INI "save"
End Select
End Function
'gbs_00466
http://www.garybeene.com/sw/gbsnippets.htm