PowerBASIC Peer Support Forums
 

Go Back   PowerBASIC Peer Support Forums > User to user Discussions > Source Code

Notices

Source Code PowerBASIC and related source code. Please do not post questions or discussions, just source code.

Reply
 
Thread Tools Display Modes
  #1  
Old Dec 30th, 2009, 02:37 PM
Shannon David Larratt Shannon David Larratt is offline
Member
 
Join Date: Nov 2009
Location: Toronto, Canada
Posts: 50
Ghost in the Machine Clock

This is a piece of clock software that takes over your mouse and "writes" the time onto your screen like a ghost. It includes a character editor as well. It can also write with transparent mouse trails, which is done by taking a screen capture, pasting it into a borderless window, making it transparent, and drawing to that. I had lots of fun writing this.

More documentation on my blog here: http://www.zentastic.com/blog/2009/1...-beta-version/

Program source code:

Code:
#COMPILE EXE
#DIM ALL

'Compress via: \work\upx304w\upx.exe -9 \work\scrollclock\gitm-clock.exe


#INCLUDE ONCE "WIN32API.INC"
#INCLUDE ONCE "COMMCTRL.INC"
#INCLUDE ONCE "PBForms.INC"

#RESOURCE "gitm-clock.pbr"          'Icon and Default Charset

TYPE CustomColors
   c(15) AS LONG
END TYPE

'Globals
GLOBAL hMainDialog AS DWORD         'The handle of the main/settings dialog window
GLOBAL hCreatorDialog  AS DWORD     'The handle of the creator dialog window
GLOBAL graphicX AS LONG             'The X-location of the character editor graphic control
GLOBAL graphicY AS LONG             'The Y-location of the character editor graphic control
GLOBAL graphicW AS LONG             'The width of the character editor graphic control
GLOBAL graphicH AS LONG             'The height of the character editor graphic control
GLOBAL isRecording AS LONG          'Are we currently recording a character path?
GLOBAL recordingWhat AS LONG        'What character is currently being recorded?
GLOBAL pointList$()                 'This is a list of 12 (0-9, :, AM, PM) lists of points for all the characters
GLOBAL lastDrawing AS LONG          'What was the last drawing that we rendered (since if it's the same, it's drawn with the mouse animation)
GLOBAL mouseRunning AS LONG         'Is the mouse currently moving under program control?
GLOBAL unsavedChars AS LONG         'Do we have unsaved characters that we've created in the creator module?
GLOBAL ClockStyle$                  'How to render the clock; valid options are "HH:MM AM (12hr)", "HH:MM (12hr)", "HHMM AM (12hr)", "HHMM (12hr)", "HH:MM (24hr)", "HHMM (24hr)"
GLOBAL ShortcutKeyModifier$         'Shortcut key, shift part; valid options are "Ctrl", "Alt", "Ctrl+Alt", "Ctrl+Shift", "Alt+Shift", "Ctrl+Alt+Shift"
GLOBAL ShortcutKey$                 'Shortcut key, actual key; valid shortcut keys are 0-9,A-Z,F1-F12
GLOBAL CharacterSet$                'Filename of the character set to use; "Default.set" is stored internally, others are loaded from disk
GLOBAL MaxPixelHeight AS LONG       'Default is 323, with a width of 230, and it scales from there
GLOBAL LeaveMouseTrails AS LONG     '(T/F) Are we drawing mouse trails on the screen, or just moving the cursor
GLOBAL SlowdownFactor AS LONG       '(1 - 200); the number of milliseconds pause between points
GLOBAL AccelerationFactor AS LONG   '(1 - 10); where 1 = Normal, 2 = Play every 2nd point, 3 = Play every 3rd point, etc.
GLOBAL theCanvasX AS LONG           'Canvas X of top-left while in use
GLOBAL theCanvasY AS LONG           'Canvas Y of top-left while in use
GLOBAL CustomColorList AS CustomColors  'Stores 16 user-defined colors
GLOBAL trailsColor AS LONG          'This is the color of the trails


'List of Dialog Constants
%IDD_CREATOR_DIALOG   =  101            'This is the character creator dialog
%IDC_GRAPHIC          = 1001
%IDC_RECORD_0         = 1500
%IDC_RECORD_1         = 1501
%IDC_RECORD_2         = 1502
%IDC_RECORD_3         = 1503
%IDC_RECORD_4         = 1504
%IDC_RECORD_5         = 1505
%IDC_RECORD_6         = 1506
%IDC_RECORD_7         = 1507
%IDC_RECORD_8         = 1508
%IDC_RECORD_9         = 1509
%IDC_RECORD_COLON     = 1510
%IDC_RECORD_AM        = 1511
%IDC_RECORD_PM        = 1512
%IDC_SHOW_0           = 1600
%IDC_SHOW_1           = 1601
%IDC_SHOW_2           = 1602
%IDC_SHOW_3           = 1603
%IDC_SHOW_4           = 1604
%IDC_SHOW_5           = 1605
%IDC_SHOW_6           = 1606
%IDC_SHOW_7           = 1607
%IDC_SHOW_8           = 1608
%IDC_SHOW_9           = 1609
%IDC_SHOW_COLON       = 1610
%IDC_SHOW_AM          = 1611
%IDC_SHOW_PM          = 1612
%IDC_BUTTON_STOP      = 1023
%IDC_BUTTON_QUIT      = 1033
%IDC_BUTTON_LOAD      = 1030
%IDC_BUTTON_NEW       = 1031
%IDC_BUTTON_SAVE      = 1032
%IDC_MANUAL           = 1034

%IDD_MAINDIALOG                    =  201       'The 2-series is the main/settings dialog
%IDC_LABEL_CLOCKSTYLE              = 2001
%IDC_COMBOBOX_CLOCKSTYLE           = 2002
%IDC_COMBOBOX_SHORTCUTKEY_MODIFIER = 2003
%IDC_LABEL_SHORTCUTKEY             = 2004
%IDC_COMBOBOX_SHORTCUT_KEY         = 2005
%IDC_LABEL_CHARACTERSET            = 2008
%IDC_TEXTBOX_CHARACTERSET          = 2010
%IDC_BUTTON_BROWSE_CS              = 2011
%IDC_BUTTON_EDIT_CS                = 2013
%IDC_TEXTBOX_PIXELHEIGHT           = 2015
%IDC_LABEL_PIXELHEIGHT             = 2016
%IDC_TEXTBOX_SLOWDOWN              = 2017
%IDC_LABEL_SLOWDOWN                = 2018
%IDC_TEXTBOX_ACCELERATION          = 2019
%IDC_LABEL_ACCELERATION            = 2020
%IDC_CHECKBOX_LEAVE_MOUSE_TRAILS   = 2021
%IDC_BUTTON_SHOW_NOW               = 2022
%IDC_LABEL_CURRENTLYLOOKSLIKE      = 2023
%IDC_LABEL_CLOCKSAMPLE             = 2024
%IDC_BUTTON_APPLY_SETTINGS         = 2025
%IDC_BUTTON_RESTORE_DEFAULTS       = 2026
%IDC_BUTTON_QUIT_PROGRAM           = 2027
%IDC_LINE                          = 2028
%IDC_SAMPLECLOCK                   = 2029
%IDC_HOTKEY                        = 2030
%IDC_COLORPICKER                   = 2031

%IDD_FAKEBACKGROUND                = 301
%IDC_GRAPHIC_FAKE                  = 3001


'Declarations
DECLARE FUNCTION DrawDigit(whatDigit AS LONG, whereX AS LONG, whereY AS LONG, lineIt AS LONG, OPTIONAL ratio AS DOUBLE) AS LONG        'Using the mouse, draw a digit
DECLARE CALLBACK FUNCTION ShowCREATOR_DIALOGProc()
DECLARE FUNCTION ShowCREATOR_DIALOG(BYVAL hParent AS DWORD) AS LONG
DECLARE SUB WriteManual()       'Write/reset the manual text to %IDC_MANUAL
DECLARE CALLBACK FUNCTION ShowMAINDIALOGProc()
DECLARE FUNCTION ShowMAINDIALOG(BYVAL hParent AS DWORD) AS LONG
DECLARE SUB WriteSettings()         'Write the INI file to disk
DECLARE SUB LoadSettings()          'Load the INI file
DECLARE SUB WriteSettingsToScreen() 'Write all the settings to the dialog
DECLARE SUB SetProgramDefaults()    'Set default of program
DECLARE FUNCTION LoadPoints(pointFilename$, pointsLoaded AS LONG) AS LONG      'Load a point set, return the number of characers and points loaded
DECLARE SUB UpdateShowButtons()     'Update the show buttons with bold/non-bold on the creator form to represent if they have data
DECLARE FUNCTION GetCurrentTime$()          'Return the current time, in the current clock style
DECLARE SUB wrapRegisterHotkey()                'Register the hotkey for the program
DECLARE SUB wrapUnregisterHotkey()                                      'Free the hotkey
DECLARE SUB CalculateWorkspace(Digits AS LONG, canvasX AS LONG, canvasY AS LONG, canvasW AS LONG, canvasH AS LONG, charW AS LONG, charH AS LONG, ration AS DOUBLE)    'Calculate the size of characters and canvas


FUNCTION PBMAIN()                       'Main function
    PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR %ICC_INTERNET_CLASSES)

    DIM PointList$(0 TO 12)         'This stores the current character set
    recordingWhat = -1              'What character is currently being recorded (nothing is -1, since 0 is a valid option)
    lastDrawing = -1                'What's the last drawing that we viewed in the creator graphic

    ShowMAINDIALOG %HWND_DESKTOP    'Start with the main/settings dialog
END FUNCTION



CALLBACK FUNCTION ShowCREATOR_DIALOGProc()
    LOCAL dummyThread???, res AS LONG, dummy AS DWORD, charsLoaded AS LONG, pointsLoaded AS LONG
    LOCAL hFont1 AS DWORD, drawingWhat AS LONG, ctr AS LONG, pointCount AS LONG
    LOCAL thisX AS LONG, thisY AS LONG, lastDrawX AS LONG, lastDrawY AS LONG, drawX AS LONG, drawY AS LONG
    LOCAL mousePt AS POINT, ff AS LONG, thisCheck AS LONG, sFileSpec$, TempFilename$

    SELECT CASE AS LONG CB.MSG
        CASE %WM_INITDIALOG
            'Initialization handler

        CASE %WM_NCACTIVATE
            STATIC hWndSaveFocus AS DWORD
            IF ISFALSE CB.WPARAM THEN
                hWndSaveFocus = GetFocus()  'Save control focus
            ELSEIF hWndSaveFocus THEN
                SetFocus(hWndSaveFocus)     'Restore control focus
                hWndSaveFocus = 0
            END IF

        CASE %WM_COMMAND
            SELECT CASE AS LONG CB.CTL
                CASE %IDC_GRAPHIC
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        isRecording = %FALSE            'If they click on the graphic window, then stop recording
                    END IF

                CASE %IDC_RECORD_0 TO %IDC_RECORD_PM            'Clicked a record button
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        IF recordingWhat = -1 THEN      'Make sure we're not recording anything
                            isRecording = %TRUE         'Set that we are currently recording
                            recordingWhat = CB.CTL - %IDC_RECORD_0  'Mark what we're recording, based on the control ID
                            hFont1 = PBFormsMakeFont("MS Sans Serif", 10, 700, %FALSE, %FALSE, %FALSE, %ANSI_CHARSET)   'Create a slightly bigger, bold font
                            CONTROL SEND hCreatorDialog, %IDC_RECORD_0 + recordingWhat, %WM_SETFONT, hFont1, 0          'Set the font of the button we clicked
                            CONTROL REDRAW hCreatorDialog, %IDC_RECORD_0 + recordingWhat                                'And redraw it
                            THREAD CREATE doRecord(dummy) TO dummyThread???                                             'Start the recording thread
                            THREAD CLOSE dummyThread??? TO res                                                          'And kill the handle since we don't need it
                        END IF
                    END IF

                CASE %IDC_SHOW_0 TO %IDC_SHOW_PM                'Clicked a show button
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        GRAPHIC ATTACH hCreatorDialog, %IDC_GRAPHIC, REDRAW         'Attach to the graphic window
                        GRAPHIC CLEAR %RGB_WHITE                                    'Clear the window with a white background
                        drawingWhat = CB.CTL - %IDC_SHOW_0                          'Set which character is being drawn
                        pointCount = PARSECOUNT(pointList$(drawingWhat))            'How many points are on our list?
                        IF pointCount > 4 THEN                                      'Are there more than four? (actually, more than 2)
                            thisX = VAL(PARSE$(pointList$(drawingWhat), 1))         'Get the first point X...
                            thisY = VAL(PARSE$(pointList$(drawingWhat), 2))         '             ...and Y
                            DIALOG PIXELS hCreatorDialog, thisX, thisY TO UNITS lastDrawX, lastDrawY    'Convert this to units for the dialog
                            FOR ctr = 3 TO pointCount STEP 2                        'Go through all the points
                                thisX = VAL(PARSE$(pointList$(drawingWhat), ctr))       'Grab this point's X...
                                thisY = VAL(PARSE$(pointList$(drawingWhat), ctr + 1))   '           ...and Y values
                                DIALOG PIXELS hCreatorDialog, thisX, thisY TO UNITS drawX, drawY    'Convert it to units as well
                                GRAPHIC LINE (lastDrawX, lastDrawY) - (drawX, drawY), %RGB_BLUE     'And draw a line connecting it to the previous point
                                lastDrawX = drawX                                   'Set the previous point...
                                lastDrawY = drawY                                   '       ...to the value of the current point
                                IF lastDrawing = drawingWhat THEN                   'Is this drawing the second time we've done it?
                                    DIALOG DOEVENTS 1                               'Pause for a moment to keep the dialog from freezing
                                    SLEEP 10                                        'And sleep for a moment to keep it from being instant
                                    GRAPHIC REDRAW                                  'Redraw the graphic window
                                    'Now move mouse to match
                                    DIALOG UNITS hCreatorDialog, drawX + 5, drawY + 5 TO PIXELS thisX, thisY    'Figure out the pixel location of this point
                                    mousePt.x = thisX                               'And set it inside a...
                                    mousePt.y = thisY                               '       ...windows style point
                                    ClientToScreen hCreatorDialog, mousePt          'Convert this client-relative pixel to a screen-relative pixel
                                    SetCursorPos mousePt.X, mousePt.Y               'And move the cursor to this location
                                END IF
                            NEXT
                        END IF
                        lastDrawing = drawingWhat                                   'Set what we just drew
                        GRAPHIC REDRAW                                              'Redraw the graphic
                        GRAPHIC DETACH                                              'And detatch from it since we're done
                    END IF

                CASE %IDC_BUTTON_STOP
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        isRecording = %FALSE                                        'Stop recording
                    END IF

                CASE %IDC_BUTTON_QUIT
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        DIALOG END CBHNDL                                           'Quit this dialog
                    END IF

                CASE %IDC_BUTTON_LOAD
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        IF unsavedChars <> %FALSE THEN                              'If we have unsaved characters, warn them
                            thisCheck = MSGBOX("You have unsaved characters. Would you like to load anyway and lose this work?", %MB_SYSTEMMODAL OR %MB_YESNO, "Warning")
                            IF thisCheck <> %IDYES THEN                             'Abort if they said no
                                EXIT SELECT
                            END IF
                        END IF
                        sFileSpec$ = ""                         'No default filename, next line executes the windows load dialog
                        DISPLAY OPENFILE hCreatorDialog, , , "Please select a file to load from", EXE.PATH$, _
                            "All mouse movement sets (*.set)" & CHR$(0) & "*.set" & CHR$(0), sFileSpec$, "set", _
                            %OFN_FILEMUSTEXIST OR %OFN_PATHMUSTEXIST OR %OFN_ENABLESIZING OR %OFN_OVERWRITEPROMPT OR %OFN_CREATEPROMPT TO TempFilename$
                        TempFilename$ = TRIM$(TempFilename$)        'Clean up
                        IF DIR$(TempFilename$) <> "" THEN           'Valid file, we can open it
                            charsLoaded = LoadPoints(tempFilename$, pointsLoaded)       'Try and load the points from disk
                            UpdateShowButtons()                                         'Update the "show" buttons to show which characters are done
                            MSGBOX "Number of data sets of mouse motion digits loaded is " & FORMAT$(charsLoaded) + " with " & FORMAT$(pointsLoaded) & " individual coordinates", %MB_ICONINFORMATION, "Loaded Successfully"    'Tell them
                            unsavedChars = %FALSE                                       'We don't have unsaved characters on a fresh load
                            CONTROL SET TEXT hMainDialog, %IDC_TEXTBOX_CHARACTERSET, TempFilename$      'Update the filename on the main dialog
                            WriteSettings()                                             'And save it as our current default
                        END IF
                    END IF

                CASE %IDC_BUTTON_NEW                                        'NEW character set (clear basically)
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        IF unsavedChars <> %FALSE THEN                                  'If we have unsaved characters, warn them before clearing
                            thisCheck = MSGBOX("You have unsaved characters. Would you like to start over and lose this work?", %MB_SYSTEMMODAL OR %MB_YESNO, "Warning")
                            IF thisCheck <> %IDYES THEN                             'If they said No, abort
                                EXIT SELECT
                            END IF
                        END IF
                        hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 400, %FALSE, %FALSE, %FALSE, %ANSI_CHARSET)    'This is the normal font
                        FOR ctr = 0 TO 12                   'Set fonts of buttons to indicate whether they exist or not
                            pointList$(ctr) = ""            'Clear the data on this character
                            CONTROL SEND hCreatorDialog, %IDC_SHOW_0 + ctr, %WM_SETFONT, hFont1, 0      'And clear the show button to match
                            CONTROL REDRAW hCreatorDialog, %IDC_SHOW_0 + ctr                            'Redraw the button
                        NEXT
                        unsavedChars = %FALSE               'We have no unsaved buttons on a cleared list
                    END IF

                CASE %IDC_BUTTON_SAVE                                   'SAVE the current character set
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        sFileSpec$ = ""             'No default filename. Next line executes the windows save dialog
                        DISPLAY SAVEFILE hCreatorDialog, , , "Please select a file to save to", EXE.PATH$, _
                            "All mouse movement sets (*.set)" & CHR$(0) & "*.set" & CHR$(0), sFileSpec$, "set", _
                            %OFN_PATHMUSTEXIST OR %OFN_ENABLESIZING OR %OFN_OVERWRITEPROMPT OR %OFN_CREATEPROMPT TO TempFilename$
                        TempFilename$ = TRIM$(TempFilename$)        'Clean up the filename (not sure if this is ever needed)

                        IF TempFilename$ <> "" THEN         'Did they enter a filename? (If not they cancelled)
                            ff = FREEFILE                           'Get the next free handle
                            OPEN TempFilename$ FOR OUTPUT AS #ff    'Open it
                            FOR ctr = 0 TO 12                       'Go through all the point sets in order
                                PRINT #ff, pointList$(ctr)          'And write them, one per line
                            NEXT
                            CLOSE #ff                               'And we're done, so (next) tell the user
                            MSGBOX "Your data set of mouse motion digits has been saved to " & TempFilename$, %MB_ICONINFORMATION, "Saved Successfully"
                            unsavedChars = %FALSE                   'We have nothing unsaved now
                            CharacterSet$ = TempFilename$           'Set our current character set to the one we just saved
                            CONTROL SET TEXT hMainDialog, %IDC_TEXTBOX_CHARACTERSET, TempFilename$  'Update the main dialog
                            WriteSettings()                         'And update the settings file
                        END IF

                    END IF

            END SELECT
    END SELECT
END FUNCTION



FUNCTION ShowCREATOR_DIALOG(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt AS LONG, hInstance AS DOUBLE
    LOCAL hAccel AS DWORD, AccelTable() AS ACCELAPI
    DIM AccelTable(0 TO 14) AS ACCELAPI

    DIALOG NEW hParent, "Mouse Motion Capture Character Creator", 199, 112, _
        380, 211, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_CAPTION OR _
        %WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR _
        %DS_CENTER OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
        %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
        %WS_EX_RIGHTSCROLLBAR, TO hCreatorDialog                            'Create the creator window

    CONTROL ADD GRAPHIC, hCreatorDialog, %IDC_GRAPHIC, "", 5, 5, 155, 200, %WS_BORDER OR %SS_NOTIFY     'Drawing area

    DIALOG UNITS hCreatorDialog, 5, 5 TO PIXELS graphicX, graphicY          'Figure out the pixel size of the drawing area
    DIALOG UNITS hCreatorDialog, 155, 200 TO PIXELS graphicW, graphicH

    'Add all the record buttons
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_0, "0", 170, 5, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_1, "1", 170, 20, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_2, "2", 170, 35, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_3, "3", 170, 50, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_4, "4", 170, 65, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_5, "5", 170, 80, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_6, "6", 170, 95, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_7, "7", 170, 110, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_8, "8", 170, 125, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_9, "9", 170, 140, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_COLON, ":", 170, 160, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_AM, "AM", 170, 175, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_RECORD_PM, "PM", 170, 190, 25, 15

    'Add all the view/show buttons
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_0, "0", 205, 5, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_1, "1", 205, 20, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_2, "2", 205, 35, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_3, "3", 205, 50, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_4, "4", 205, 65, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_5, "5", 205, 80, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_6, "6", 205, 95, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_7, "7", 205, 110, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_8, "8", 205, 125, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_9, "9", 205, 140, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_COLON, ":", 205, 160, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_AM, "AM", 205, 175, 25, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_SHOW_PM, "PM", 205, 190, 25, 15

    'Add the manual/help text
    CONTROL ADD LABEL,  hCreatorDialog, %IDC_MANUAL, "", 240, 5, 135, 140
    writeManual()       'Write the manual to this window (separated into a function in case I later want to multi-purpose this area)

    'Add control buttons
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_BUTTON_STOP, "Stop Recording", 240, 150, 65, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_BUTTON_QUIT, "Quit Editor", 240, 190, 65, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_BUTTON_LOAD, "Load Set", 310, 150, 65, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_BUTTON_NEW, "New Set", 310, 170, 65, 15
    CONTROL ADD BUTTON, hCreatorDialog, %IDC_BUTTON_SAVE, "Save Set", 310, 190, 65, 15

    'Set up accelerator keys for all the record buttons
    AccelTable(0).fvirt = %FVIRTKEY :    AccelTable(0).key = %VK_0  :    AccelTable(0).cmd = %IDC_RECORD_0
    AccelTable(1).fvirt = %FVIRTKEY :    AccelTable(1).key = %VK_1  :    AccelTable(1).cmd = %IDC_RECORD_1
    AccelTable(2).fvirt = %FVIRTKEY :    AccelTable(2).key = %VK_2  :    AccelTable(2).cmd = %IDC_RECORD_2
    AccelTable(3).fvirt = %FVIRTKEY :    AccelTable(3).key = %VK_3  :    AccelTable(3).cmd = %IDC_RECORD_3
    AccelTable(4).fvirt = %FVIRTKEY :    AccelTable(4).key = %VK_4  :    AccelTable(4).cmd = %IDC_RECORD_4
    AccelTable(5).fvirt = %FVIRTKEY :    AccelTable(5).key = %VK_5  :    AccelTable(5).cmd = %IDC_RECORD_5
    AccelTable(6).fvirt = %FVIRTKEY :    AccelTable(6).key = %VK_6  :    AccelTable(6).cmd = %IDC_RECORD_6
    AccelTable(7).fvirt = %FVIRTKEY :    AccelTable(7).key = %VK_7  :    AccelTable(7).cmd = %IDC_RECORD_7
    AccelTable(8).fvirt = %FVIRTKEY :    AccelTable(8).key = %VK_8  :    AccelTable(8).cmd = %IDC_RECORD_8
    AccelTable(9).fvirt = %FVIRTKEY :    AccelTable(9).key = %VK_9  :    AccelTable(9).cmd = %IDC_RECORD_9
    AccelTable(10).fvirt = %FVIRTKEY:    AccelTable(10).key = %VK_OEM_1: AccelTable(10).cmd = %IDC_RECORD_COLON     'Should be ";" or ":" on US keyboards
    AccelTable(11).fvirt = %FVIRTKEY:    AccelTable(11).key = %VK_OEM_MINUS: AccelTable(11).cmd = %IDC_RECORD_COLON 'Should be "-" on all keyboards
    AccelTable(12).fvirt = %FVIRTKEY:    AccelTable(12).key = %VK_A :    AccelTable(12).cmd = %IDC_RECORD_AM
    AccelTable(13).fvirt = %FVIRTKEY:    AccelTable(13).key = %VK_P :    AccelTable(13).cmd = %IDC_RECORD_PM
    AccelTable(14).fvirt = %FVIRTKEY:    AccelTable(14).key = %VK_SPACE: AccelTable(14).cmd = %IDC_BUTTON_STOP
    ACCEL ATTACH hCreatorDialog, AccelTable() TO hAccel

    'Make sure that the show buttons visually match any preloaded data
    UpdateShowButtons()

    'Add the program icon
    hInstance = GetModuleHandle("")
    DIALOG SEND hCreatorDialog, %WM_SETICON, %ICON_BIG, LoadIcon(hInstance, "0L")

    'Make the dialog visible
    DIALOG SHOW MODAL hCreatorDialog, CALL ShowCREATOR_DIALOGProc TO lRslt

    FUNCTION = lRslt
END FUNCTION


SUB WriteManual()       'Write/reset the manual text to %IDC_MANUAL
    CONTROL SET TEXT hCreatorDialog, %IDC_MANUAL, "Instead of pushing the left column " + _
        "of buttons, press ""0"" through ""9"" as well as "":"", ""A"", and " + _
        """P"" to begin recording a character (it will actually start the " + _
        "instant you move the mouse), and then the space bar to stop " + _
        "recording (or click the mouse button to stop). Note that all pauses and drawing speed will be recorded " + _
        "as well as just the motion. Afterwards, pressing the buttons in the " + _
        "right column let you view them (click a second time to view with animation). " + _
        "The new, save, and load buttons let you create new sets, " + _
        "save the current set, or load an older one."
END SUB


FUNCTION doRecord(BYVAL dummy AS DWORD) AS DWORD        'Record a sequence of mouse movements
    LOCAL mousePt AS POINT
    LOCAL startX AS LONG, startY AS LONG
    LOCAL thisX AS LONG, thisY AS LONG
    LOCAL drawX AS LONG, drawY AS LONG
    LOCAL lastDrawX AS LONG, lastDrawY AS LONG
    LOCAL temp$
    LOCAL hFont1 AS DWORD

    GRAPHIC ATTACH hCreatorDialog, %IDC_GRAPHIC, REDRAW     'Attach to the graphic window for drawing
    GRAPHIC CLEAR %RGB_WHITE                                'Clear it with a white background

    GetCursorPos mousePt                                    'Get the current mouse location
    ScreenToClient hCreatorDialog, mousePt                  'And convert it to being relative to this dialog

    startX = mousePt.x - graphicX                           'Now convert it to being relative to the graphic control
    startY = mousePt.y - graphicY                           'And mark that as the start point

    'Wait for first mouse movement
    DO UNTIL isRecording = %FALSE                           'Start loop and wait for first move
        GetCursorPos mousePt                                'Get current pouse point
        ScreenToClient hCreatorDialog, mousePt              'Convert to being relative to the dialog
        thisX = mousePt.x - graphicX                        'And convert to being relative to the control
        thisY = mousePt.y - graphicY
        IF startX <> thisX OR startY <> thisY THEN          'Has the mouse moved?
            pointList$(recordingWhat) = FORMAT$(thisX, "0") & "," & FORMAT$(thisY, "0") 'Add the starting point to the point set
            EXIT DO                                         'And continue on to the main recording loop
        END IF
    LOOP

    DIALOG PIXELS hCreatorDialog, thisX, thisY TO UNITS lastDrawX, lastDrawY    'Convert our start point to a unit value for drawing

    DO UNTIL isRecording = %FALSE                           'Record all mouse movement until something kills the thread
        SLEEP 10                                            'Pause for just a moment: 1/100 of a second
        GetCursorPos mousePt                                'Get the current mouse location
        ScreenToClient hCreatorDialog, mousePt              'Convert to dialog relative
        thisX = mousePt.x - graphicX                        'Convert to control relative
        thisY = mousePt.y - graphicY

        IF (thisX > 0 AND thisX < graphicW) AND (thisY > 0 AND thisY < graphicH) THEN       'Are we inside the drawing space?
            pointList$(recordingWhat) = pointList$(recordingWhat) & ", " & FORMAT$(thisX, "0") & "," & FORMAT$(thisY, "0")  'Add this motion to the point set

            DIALOG PIXELS hCreatorDialog, thisX, thisY TO UNITS drawX, drawY        'Convert pixel recording to dialog units for drawing

            'graphic set pixel (drawX, drawY), %RGB_RED
            GRAPHIC LINE (lastDrawX, lastDrawY) - (drawX, drawY), %RGB_RED          'Draw line, in red
            lastDrawX = drawX                                                       'And set last point to the current point
            lastDrawY = drawY

            GRAPHIC REDRAW                                                          'Redraw the graphic window
        END IF
    LOOP

    'Mark as done on view button
    hFont1 = PBFormsMakeFont("MS Sans Serif", 10, 700, %FALSE, %FALSE, %FALSE, %ANSI_CHARSET)    'Create a bold font
    CONTROL SEND hCreatorDialog, %IDC_SHOW_0 + recordingWhat, %WM_SETFONT, hFont1, 0        'Turn font to bold
    CONTROL REDRAW hCreatorDialog, %IDC_SHOW_0 + recordingWhat                              'On recording button

    'Write stats to graphic window
    hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 400, %FALSE, %FALSE, %FALSE, %ANSI_CHARSET)    'Create a normal font
    GRAPHIC SET FONT hFont1                                                                     'Make this our active font
    GRAPHIC SET POS (5, 5)                                                                      'Start writing at top left
    GRAPHIC COLOR %RGB_BLACK, -2                                                                'Set color; -2 is "don't draw" for the background color
    GRAPHIC PRINT "Done: " & FORMAT$(PARSECOUNT(pointList$(recordingWhat)) \ 2) & " points."    'Write text with point count
    GRAPHIC REDRAW                                                                              'And update screen

    'Restore button and other stuff
    CONTROL SEND hCreatorDialog, %IDC_RECORD_0 + recordingWhat, %WM_SETFONT, hFont1, 0          'Set the recording button to normal font since we're done
    CONTROL REDRAW hCreatorDialog, %IDC_RECORD_0 + recordingWhat                                'Redraw that button
    GRAPHIC DETACH                                                                              'And detach from graphic control
    recordingWhat = -1                                                                          'We're no longer recording
    lastDrawing = -1                                                                            'And drawing viewing is reset as well
    unsavedChars = %TRUE                                                                        'And we definitely have unsaved characters (this one)

END FUNCTION



CALLBACK FUNCTION ShowMAINDIALOGProc()                                      'Deal with action in the main dialog
    LOCAL temp$, res AS LONG, sFileSpec$, TempFilename$
    LOCAL charsLoaded AS LONG, pointsLoaded AS LONG
    LOCAL dummy AS LONG, dummyThread???

    SELECT CASE AS LONG CB.MSG
        CASE %WM_INITDIALOG
            SetTimer(CBHNDL, %IDC_SAMPLECLOCK, 1000, BYVAL %NULL)               'Ping the timer once a second to update the clock

        CASE %WM_CLOSE                                                          'Window closed
            KillTimer CBHNDL, %IDC_SAMPLECLOCK                                  'Kill timer
            wrapUnregisterHotkey()                                              'Free the hotkey

        CASE %WM_TIMER
            SELECT CASE CBWPARAM
                CASE %IDC_SAMPLECLOCK                                           'Update the clock display
                    CONTROL SET TEXT hMainDialog, %IDC_LABEL_CLOCKSAMPLE, GetCurrentTime$()     'Write current time
            END SELECT

        CASE %WM_HotKey
           SELECT CASE CB.WPARAM
                CASE %IDC_HOTKEY                                                'They hit the show time hotkey
                    THREAD CREATE doPlay(dummy) TO dummyThread???               'Create the time player thread
                    THREAD CLOSE dummyThread??? TO res                          'and throw away the handle

           END SELECT

        CASE %WM_NCACTIVATE
            STATIC hWndSaveFocus AS DWORD
            IF ISFALSE CB.WPARAM THEN
                hWndSaveFocus = GetFocus()   'Save control focus
            ELSEIF hWndSaveFocus THEN
                SetFocus(hWndSaveFocus)          'Restore control focus
                hWndSaveFocus = 0
            END IF

        CASE %WM_COMMAND, %WM_NOTIFY
            SELECT CASE AS LONG CB.CTL
                CASE %IDC_COMBOBOX_CLOCKSTYLE                                   'Clock style combobox
                    IF CB.CTLMSG = %CBN_SELENDOK THEN                           'Clock format has been updated
                        CONTROL GET TEXT CBHNDL, %IDC_COMBOBOX_CLOCKSTYLE TO ClockStyle$    'Grab the new style
                        WriteSettings()                                                     'Update settings file
                    END IF

                CASE %IDC_COMBOBOX_SHORTCUTKEY_MODIFIER                         'Shortkey modifier combobox
                    IF CB.CTLMSG = %CBN_SELENDOK THEN                           'Shortkey modifier has been updated
                        CONTROL GET TEXT CBHNDL, %IDC_COMBOBOX_SHORTCUTKEY_MODIFIER TO ShortcutKeyModifier$ 'Grab it
                        wrapUnregisterHotkey()                                  'Dump the old hotkey
                        wrapRegisterHotkey()                                    'And create the new hotkey
                        WriteSettings()                                         'Update settings file
                    END IF

                CASE %IDC_COMBOBOX_SHORTCUT_KEY                                 'Shortcut key combobox
                    IF CB.CTLMSG = %CBN_SELENDOK THEN                           'Shortcut key has been updated
                        CONTROL GET TEXT CBHNDL, %IDC_COMBOBOX_SHORTCUT_KEY TO ShortcutKey$     'Grab it
                        wrapUnregisterHotkey()                                  'Dump the old hotkey
                        wrapRegisterHotkey()                                    'And create the new hotkey
                        WriteSettings()                                         'Update settings file
                    END IF

                CASE %IDC_BUTTON_SHOW_NOW                                       'Show time now button
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        THREAD CREATE doPlay(dummy) TO dummyThread???           'Create time display thread
                        THREAD CLOSE dummyThread??? TO res                      'And dump the handle
                    END IF

                CASE %IDC_BUTTON_BROWSE_CS                                      'Browsing for a new character set
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        sFileSpec$ = ""                                         'No default; next line opens the file
                        DISPLAY OPENFILE hCreatorDialog, , , "Please select a file to load from", EXE.PATH$, _
                            "All mouse movement sets (*.set)" & CHR$(0) & "*.set" & CHR$(0), sFileSpec$, "set", _
                            %OFN_FILEMUSTEXIST OR %OFN_PATHMUSTEXIST OR %OFN_ENABLESIZING OR %OFN_OVERWRITEPROMPT OR %OFN_CREATEPROMPT TO TempFilename$
                        TempFilename$ = TRIM$(TempFilename$)                    'Clean file
                        IF DIR$(TempFilename$) <> "" THEN                       'Valid file (it exists), we can open it
                            CONTROL SET TEXT CBHNDL, %IDC_TEXTBOX_CHARACTERSET, TempFilename$   'Update the dialog with this valid filename
                            charsLoaded = LoadPoints(tempFilename$, pointsLoaded)               'Try and load the file, and then tell the user the results of the load
                            MSGBOX "Number of data sets of mouse motion digits loaded is " & FORMAT$(charsLoaded) + " with " & FORMAT$(pointsLoaded) & " individual coordinates", %MB_ICONINFORMATION, "Loaded Successfully"
                            WriteSettings()                                     'Update settings file
                        END IF
                    END IF

                CASE %IDC_BUTTON_EDIT_CS                                        'Edit character set button
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        ShowCREATOR_DIALOG hMainDialog                          'Open the character editor
                    END IF

                CASE %IDC_TEXTBOX_PIXELHEIGHT                                   'Character pixel height box
                    IF CB.CTLMSG = %EN_KILLFOCUS THEN                           'Has it just lost edit focus?
                        CONTROL GET TEXT CBHNDL, %IDC_TEXTBOX_PIXELHEIGHT TO temp$  'Grab the value
                        IF VAL(temp$) <> MaxPixelHeight THEN                    'Has the value changed from the current setting?
                            MaxPixelHeight = VAL(temp$)                         'Grab the new value
                            IF MaxPixelHeight < 50 THEN                         'Is it too small?
                                MaxPixelHeight = 50                             'Set to minimum
                            ELSEIF MaxPixelHeight > 800 THEN                    'Is it too big?
                                MaxPixelHeight = 800                            'Set to maximum
                            END IF
                            temp$ = FORMAT$(MaxPixelHeight, "0")                'Convert to string
                            CONTROL SET TEXT CBHNDL, %IDC_TEXTBOX_PIXELHEIGHT, temp$    'And write back to dialog
                            WriteSettings()                                     'Update settings file
                        END IF
                    END IF

                CASE %IDC_CHECKBOX_LEAVE_MOUSE_TRAILS                           'Mouse trails checkbox
                    IF CB.CTLMSG = %BN_CLICKED THEN                             'Has it just been clicked on?
                        CONTROL GET CHECK CBHNDL, %IDC_CHECKBOX_LEAVE_MOUSE_TRAILS TO res   'Grab the current value
                        IF res <> %FALSE THEN res = %TRUE                       'Massage for consistency
                        IF res <> LeaveMouseTrails THEN                         'Have they changed the value?
                            LeaveMouseTrails = res                              'Update setting
                            WriteSettings()                                     'Update settings file
                        END IF
                    END IF

                CASE %IDC_TEXTBOX_SLOWDOWN                                      'Slowdown textbox
                    IF CB.CTLMSG = %EN_KILLFOCUS THEN                           'Has it just lost edit focus?
                        CONTROL GET TEXT CBHNDL, %IDC_TEXTBOX_SLOWDOWN TO temp$ 'Grab the value
                        IF VAL(temp$) <> SlowdownFactor THEN                    'Has the value changed from the current setting?
                            SlowdownFactor = VAL(temp$)                         'Grab the new value
                            IF SlowdownFactor < 1 THEN                          'Is it too fast?
                                SlowdownFactor = 1                              'Set to minimum
                            ELSEIF SlowdownFactor > 200 THEN                    'Is it too slow?
                                SlowdownFactor = 200                            'Set to maximum
                            END IF
                            temp$ = FORMAT$(SlowdownFactor, "0")                'Convert to string
                            CONTROL SET TEXT CBHNDL, %IDC_TEXTBOX_SLOWDOWN, temp$   'And write back to dialog
                            WriteSettings()                                     'Update settings file
                        END IF
                    END IF

                CASE %IDC_COLORPICKER                                           'Line color picker box
                    IF CB.CTLMSG = %BN_CLICKED THEN
                        DISPLAY COLOR CBHNDL, 100, 100, 0, CustomColorList, 0 TO trailsColor        'Open color picker dialog
                        GRAPHIC ATTACH CBHNDL, %IDC_COLORPICKER                 'Attach to the box
                        GRAPHIC CLEAR trailsColor                               'Fill it with the selected color
                        GRAPHIC DETACH                                          'Detach from the box
                        WriteSettings()                                         'Save the settings
                    END IF

                CASE %IDC_TEXTBOX_ACCELERATION                                  'Acceleration textbox
                    IF CB.CTLMSG = %EN_KILLFOCUS THEN                           'Has it just lost edit focus?
                        CONTROL GET TEXT CBHNDL, %IDC_TEXTBOX_ACCELERATION TO temp$ 'Grab the value
                        IF VAL(temp$) <> AccelerationFactor THEN                'Has the value changed from the current setting?
                            AccelerationFactor = VAL(temp$)                     'Grab the new value
                            IF AccelerationFactor < 1 THEN                      'Is it too slow?
                                AccelerationFactor = 1                          'Set to minimum
                            ELSEIF AccelerationFactor > 10 THEN                 'Is it too fast?
                                AccelerationFactor = 10                         'Set to maximum
                            END IF
                            temp$ = FORMAT$(AccelerationFactor, "0")            'Convert to string
                            CONTROL SET TEXT CBHNDL, %IDC_TEXTBOX_ACCELERATION, temp$   'Write to dialog
                            WriteSettings()                                     'Update settings file
                        END IF
                    END IF

                CASE %IDC_BUTTON_RESTORE_DEFAULTS                               'Restore defaults button
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        SetProgramDefaults()                                    'Set to defaults
                        wrapUnregisterHotkey()                                  'Dump the hotkey
                        wrapRegisterHotkey()                                    'Turn the hotkey back on
                        WriteSettingsToScreen()                                 'Update the settings visually
                        WriteSettings()                                         'And save the defaults to disk
                    END IF

                CASE %IDC_BUTTON_QUIT_PROGRAM                                   'Quit button
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        DIALOG END CBHNDL                                       'Quit
                    END IF

            END SELECT
    END SELECT
END FUNCTION


FUNCTION ShowMAINDIALOG(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt  AS LONG, hFont1 AS DWORD, ctr AS LONG, hInstance AS DOUBLE
    LOCAL ClockstyleArray$(), ShortcutModifier$(),ShortcutKey$()

    'Set up the contents of the combo boxes
    DIM ClockstyleArray$(5)
    ARRAY ASSIGN ClockstyleArray$() = "HH:MM AM (12hr)", "HH:MM (12hr)", "HHMM AM (12hr)", "HHMM (12hr)", "HH:MM (24hr)", "HHMM (24hr)"
    DIM ShortcutModifier$(5)
    ARRAY ASSIGN ShortcutModifier$() = "Ctrl", "Alt", "Ctrl+Alt", "Ctrl+Shift", "Alt+Shift", "Ctrl+Alt+Shift"
    DIM ShortcutKey$(48)
    FOR ctr = 0 TO 9
        ShortcutKey$(ctr) = FORMAT$(ctr, "0")
    NEXT
    FOR ctr = 65 TO 90
        ShortcutKey$(ctr - 55) = CHR$(ctr)
    NEXT
    FOR ctr = 1 TO 12
        ShortcutKey$(ctr + 35) = "F" & FORMAT$(ctr)
    NEXT

    'Create the window
    DIALOG NEW hParent, "The Ghost in the Machine Clock", 251, 116, 304, 137, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_CAPTION OR _
        %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_CENTER OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
        %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hMainDialog

    'Add the interface
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_CLOCKSTYLE, "Clock style:", 5, 10, 60, 10, %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD COMBOBOX, hMainDialog, %IDC_COMBOBOX_CLOCKSTYLE, ClockstyleArray$(), 70, 8, 75, 75, %CBS_DROPDOWNLIST OR %CBS_HASSTRINGS
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_CURRENTLYLOOKSLIKE, "Currently looks like:", 150, 10, 80, 10, %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_CLOCKSAMPLE, "HH:MM AM", 235, 8, 60, 10, %WS_CHILD OR %WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_SHORTCUTKEY, "Shortcut key:", 5, 27, 60, 10, %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD COMBOBOX, hMainDialog, %IDC_COMBOBOX_SHORTCUTKEY_MODIFIER, ShortcutModifier$(), 70, 25, 75, 75, %CBS_DROPDOWNLIST OR %CBS_HASSTRINGS
    CONTROL ADD COMBOBOX, hMainDialog, %IDC_COMBOBOX_SHORTCUT_KEY, ShortcutKey$(), 150, 25, 40, 155, %CBS_DROPDOWNLIST OR %CBS_HASSTRINGS OR %WS_VSCROLL
    CONTROL ADD BUTTON,   hMainDialog, %IDC_BUTTON_SHOW_NOW, "Show Now", 235, 25, 60, 15
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_CHARACTERSET, "Character set:", 5, 47, 60, 10, %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD TEXTBOX,  hMainDialog, %IDC_TEXTBOX_CHARACTERSET, "", 70, 45, 100, 15, %ES_READONLY OR %WS_BORDER
    CONTROL ADD BUTTON,   hMainDialog, %IDC_BUTTON_BROWSE_CS, "Browse", 175, 45, 40, 15
    CONTROL ADD BUTTON,   hMainDialog, %IDC_BUTTON_EDIT_CS, "Edit", 220, 45, 35, 15
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_PIXELHEIGHT, "Max pixel height:", 5, 67, 60, 10, %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD TEXTBOX,  hMainDialog, %IDC_TEXTBOX_PIXELHEIGHT, "", 70, 65, 40, 15
    CONTROL ADD CHECKBOX, hMainDialog, %IDC_CHECKBOX_LEAVE_MOUSE_TRAILS, "Leave mouse trails (OS dependent)", 120, 67, 130, 8
    CONTROL ADD GRAPHIC, hMainDialog, %IDC_COLORPICKER, "", 250, 67, 30, 10, %WS_BORDER OR %SS_NOTIFY
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_SLOWDOWN, "Slowdown factor:", 5, 87, 60, 10, %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD TEXTBOX,  hMainDialog, %IDC_TEXTBOX_SLOWDOWN, "", 70, 85, 40, 15
    CONTROL ADD LABEL,    hMainDialog, %IDC_LABEL_ACCELERATION, "Acceleration factor:", 120, 87, 65, 8, %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD TEXTBOX,  hMainDialog, %IDC_TEXTBOX_ACCELERATION, "", 190, 85, 40, 15
    CONTROL ADD LINE,     hMainDialog, %IDC_LINE, "", 10, 109, 285, 1
    CONTROL ADD BUTTON,   hMainDialog, %IDC_BUTTON_RESTORE_DEFAULTS, "Reset to Defaults", 145, 115, 75, 15
    CONTROL ADD BUTTON,   hMainDialog, %IDC_BUTTON_QUIT_PROGRAM, "Kill Clock Ghost", 230, 115, 65, 15

    'Set the font of the clock to slightly larger and bolder
    FONT NEW "MS Sans Serif", 10, 1, %ANSI_CHARSET TO hFont1
    CONTROL SET FONT hMainDialog, %IDC_LABEL_CLOCKSAMPLE, hFont1

    SetProgramDefaults()        'Start up with settings at default
    LoadSettings()              'Load the settings
    wrapRegisterHotkey()        'Register the hotkey
    WriteSettingsToScreen()     'Update the settings visually

    'Set up the program icon
    hInstance = GetModuleHandle("")
    DIALOG SEND hMainDialog, %WM_SETICON, %ICON_BIG, LoadIcon(hInstance, "0L")

    'And turn on interface
    DIALOG SHOW MODAL hMainDialog, CALL ShowMAINDIALOGProc TO lRslt

    FONT END hFont1
    FUNCTION = lRslt
END FUNCTION

SUB WriteSettingsToScreen() 'Write all the settings to the dialog
    LOCAL boxSize AS LONG, ctr AS LONG, temp$, tempFilename$, res AS LONG
    LOCAL hNull AS LONG
    LOCAL szName AS ASCIIZ * 40
    LOCAL lRet1 AS LONG, lRet2 AS LONG
    LOCAL dRet1 AS DWORD, dRet2 AS DWORD
    LOCAL sBuff AS STRING
    LOCAL ff AS LONG

    'Set up the clock style combobox
    COMBOBOX GET COUNT hMainDialog, %IDC_COMBOBOX_CLOCKSTYLE TO boxSize             'How many items on this list
    FOR ctr = 1 TO boxSize                                                          'Go through all the items
        COMBOBOX GET TEXT hMainDialog, %IDC_COMBOBOX_CLOCKSTYLE, ctr TO temp$       'Grab the text of this item
        IF temp$ = ClockStyle$ THEN                                                 'If it matches...
            COMBOBOX SELECT hMainDialog, %IDC_COMBOBOX_CLOCKSTYLE, ctr              '       ...select this item...
            EXIT FOR                                                                '                       ...and we're done
        END IF
    NEXT

    'Set up the shortcut key modifier combobox
    COMBOBOX GET COUNT hMainDialog, %IDC_COMBOBOX_SHORTCUTKEY_MODIFIER TO boxSize           'How many items on this list
    FOR ctr = 1 TO boxSize                                                                  'Go through all the items
        COMBOBOX GET TEXT hMainDialog, %IDC_COMBOBOX_SHORTCUTKEY_MODIFIER, ctr TO temp$     'Grab the text of this item
        IF temp$ = ShortcutKeyModifier$ THEN                                                'If it matches...
            COMBOBOX SELECT hMainDialog, %IDC_COMBOBOX_SHORTCUTKEY_MODIFIER, ctr            '       ...select this item...
            EXIT FOR                                                                        '                       ...and we're done
        END IF
    NEXT

    'Set up the shortcut key combobox
    COMBOBOX GET COUNT hMainDialog, %IDC_COMBOBOX_SHORTCUT_KEY TO boxSize           'How many items on this list
    FOR ctr = 1 TO boxSize                                                          'Go through all the items
        COMBOBOX GET TEXT hMainDialog, %IDC_COMBOBOX_SHORTCUT_KEY, ctr TO temp$     'Grab the text of this item
        IF temp$ = ShortcutKey$ THEN                                                'If it matches...
            COMBOBOX SELECT hMainDialog, %IDC_COMBOBOX_SHORTCUT_KEY, ctr            '       ...select this item...
            EXIT FOR                                                                '                       ...and we're done
        END IF
    NEXT

    'Set color
    GRAPHIC ATTACH hMainDialog, %IDC_COLORPICKER
    GRAPHIC CLEAR trailsColor
    GRAPHIC DETACH

    'Deal with character set
    IF CharacterSet$ = "Default.set" THEN       'We might need to extract the default file from the RC file
        IF DIR$(EXE.PATH$ & "default.set") = "" THEN        'Default does not exist
            hNull = 0                                'Null = Current process
            szName = "DEFAULTFONT"                  'This is the name of our default font
            lRet1 = FindResource(hNull, szName, BYVAL %RT_RCDATA)
            IF ISFALSE lRet1 THEN                   'Couldn't find the resource... Exe is damaged
                MSGBOX "Could not find and create default font. Application may be damaged.", %MB_SYSTEMMODAL OR %MB_ICONERROR, "Error"
            ELSE
                dRet1 = SizeofResource(hNull,lRet1)      'How big is the installer file?
                lRet2 = LoadResource(hNull,lRet1)        'Try and start loading it into memory
                IF ISFALSE lRet2 THEN
                    MSGBOX "Could not load and create installer. Application may be damaged.", %MB_SYSTEMMODAL OR %MB_ICONERROR, "Error"        'This one is "load", the other is "find"
                ELSE
                    dRet2 = LockResource(lRet2)             'Lock it down
                    sBuff = PEEK$(dRet2, dRet1)             'Now copy it from memory into the string
                    ff = FREEFILE                           'Get the next available file handle
                    OPEN EXE.PATH$ & "default.set" FOR BINARY AS #ff     'Open the requested output file
                    PUT$ #ff, sBuff                         'Spit the buffer out to file
                    CLOSE #ff                               'Close the file
                END IF
            END IF
        END IF
    END IF
    IF INSTR(CharacterSet$, "\") > 0 THEN       'Is it a long filename?
        tempFilename$ = CharacterSet$
    ELSE
        tempFilename$ = EXE.PATH$ & CharacterSet$
    END IF
    res = LoadPoints(tempFilename$, ctr)
    CONTROL SET TEXT hMainDialog, %IDC_TEXTBOX_CHARACTERSET, CharacterSet$

    'Rest of settings are pretty basic
    CONTROL SET TEXT hMainDialog, %IDC_TEXTBOX_PIXELHEIGHT, FORMAT$(MaxPixelHeight)
    IF LeaveMouseTrails = %FALSE THEN
        CONTROL SET CHECK hMainDialog, %IDC_CHECKBOX_LEAVE_MOUSE_TRAILS, %FALSE
    ELSE
        CONTROL SET CHECK hMainDialog, %IDC_CHECKBOX_LEAVE_MOUSE_TRAILS, %TRUE
    END IF
    CONTROL SET TEXT hMainDialog, %IDC_TEXTBOX_SLOWDOWN, FORMAT$(SlowdownFactor)
    CONTROL SET TEXT hMainDialog, %IDC_TEXTBOX_ACCELERATION, FORMAT$(AccelerationFactor)
END SUB

SUB SetProgramDefaults()    'Set default of program
    ClockStyle$ = "HH:MM (12hr)"
    ShortcutKeyModifier$ = "Ctrl"
    trailsColor = 0
    ShortcutKey$ = "T"
    CharacterSet$ = "Default.set"
    MaxPixelHeight = 323
    LeaveMouseTrails = %FALSE
    SlowdownFactor = 5
    AccelerationFactor = 2
END SUB

SUB WriteSettings()         'Write the INI file to disk
    LOCAL ff AS LONG, IniFile$
    IniFile$ = EXE.PATH$ & "gitm-clock.ini"        'This is the filename of the program's INI file
    ff = FREEFILE
    OPEN iniFile$ FOR OUTPUT AS #ff
    PRINT #ff, "TrailsColor: " & FORMAT$(trailsColor)
    PRINT #ff, "ClockStyle: " & ClockStyle$
    PRINT #ff, "ShortcutKeyModifiers: " & ShortcutKeyModifier$
    PRINT #ff, "ShortcutKey: " & ShortcutKey$
    PRINT #ff, "CharacterSet: " & CharacterSet$
    PRINT #ff, "MaxPixelHeight: " & FORMAT$(MaxPixelHeight)
    PRINT #ff, "LeaveMouseTrails: " & FORMAT$(LeaveMouseTrails)
    PRINT #ff, "SlowdownFactor: " & FORMAT$(SlowdownFactor)
    PRINT #ff, "AccelerationFactor: " & FORMAT$(AccelerationFactor)
    CLOSE #ff
END SUB

SUB LoadSettings()          'Load the INI file
    LOCAL ff AS LONG, IniFile$, temp$, lineCmd$, lineData$
    IniFile$ = EXE.PATH$ & "gitm-clock.ini"        'This is the filename of the program's INI file
    IF DIR$(iniFile$) <> "" THEN                        'We need the settings file to be able to load it
        ff = FREEFILE
        OPEN IniFile$ FOR INPUT AS #ff
        DO UNTIL EOF(ff)
            LINE INPUT #ff, temp$                                       'This looks like "ShortCutKeyModifier: Ctrl" and so on
            lineCmd$ = LCASE$(TRIM$(PARSE$(temp$, ":", 1)))             'This is the item being set
            lineData$ = TRIM$(MID$(temp$, INSTR(temp$, ":") + 1))       'This is the value it's being set to
            IF lineData$ <> "" THEN
                SELECT CASE lineCmd$                                    'Assign the values from the ini file
                    CASE "trailscolor"
                        trailsColor = VAL(lineData$)
                    CASE "clockstyle"
                        ClockStyle$ = lineData$
                    CASE "shortcutkeymodifier"
                        ShortcutKeyModifier$ = lineData$
                    CASE "shortcutkey"
                        ShortcutKey$ = lineData$
                    CASE "characterset"
                        CharacterSet$ = lineData$
                    CASE "maxpixelheight"
                        MaxPixelHeight = VAL(lineData$)
                    CASE "leavemousetrails"
                        LeaveMouseTrails = VAL(lineData$)
                    CASE "slowdownfactor"
                        SlowdownFactor = VAL(lineData$)
                    CASE "accelerationfactor"
                        AccelerationFactor = VAL(lineData$)
                END SELECT
            END IF
        LOOP
        CLOSE #ff
    END IF
END SUB

SUB UpdateShowButtons()     'Update the show buttons with bold/non-bold on the creator form to represent if they have data
    LOCAL hFont1 AS DWORD, ctr AS LONG
    FOR ctr = 0 TO 12       'Set fonts of show buttons to indicate whether they exist or not
        IF TRIM$(pointList$(ctr)) = "" THEN     'No pointlist = regular font
            hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 400, %FALSE, %FALSE, %FALSE, %ANSI_CHARSET)
        ELSE                                    'Has pointlist = bold font
            hFont1 = PBFormsMakeFont("MS Sans Serif", 10, 700, %FALSE, %FALSE, %FALSE, %ANSI_CHARSET)
        END IF
        CONTROL SEND hCreatorDialog, %IDC_SHOW_0 + ctr, %WM_SETFONT, hFont1, 0
        CONTROL REDRAW hCreatorDialog, %IDC_SHOW_0 + ctr
    NEXT
END SUB

FUNCTION LoadPoints(pointFilename$, pointsLoaded AS LONG) AS LONG      'Load a point set, return the number of characers and points loaded
    LOCAL ff AS LONG, ctr AS LONG, charsLoaded AS LONG
    pointsLoaded = 0
    IF DIR$(pointFilename$) = "" THEN       'File not found
        FUNCTION = 0
    ELSE
        ff = FREEFILE
        OPEN pointFilename$ FOR INPUT AS #ff        'Open found file
        FOR ctr = 0 TO 12                           'Go through all the points
            IF NOT(EOF(ff)) THEN                    '(Avoiding damaged files)
                LINE INPUT #ff, pointList$(ctr)     'And load them sequentially
            ELSE
                pointList$(ctr) = ""                'Should never happen
            END IF
        NEXT
        CLOSE #ff
        charsLoaded = 0
        FOR ctr = 0 TO 12       'Set fonts of buttons to indicate whether they exist or not
            IF TRIM$(pointList$(ctr)) <> "" THEN
                pointsLoaded = pointsLoaded + (PARSECOUNT(pointList(ctr)) \ 2)      'How many points does this character have?
                INCR charsLoaded                                                    'This character has data
            END IF
        NEXT
        FUNCTION = charsLoaded
    END IF
END FUNCTION

FUNCTION GetCurrentTime$()          'Return the current time, in the current clock style
    LOCAL HH AS LONG, MM AS LONG, HH12 AS LONG, AMPM$, renderTime$
    'Get the basic data that we need for building all the clock types
    HH = VAL(MID$(TIME$, 1, 2))         'Get the hour (24-hour time)
    MM = VAL(MID$(TIME$, 4, 2))         'Get the minutes
    HH12 = HH
    IF HH12 > 12 THEN
        HH12 = HH12 - 12  'Get the hour (12-hour time)
        AMPM$ = "PM"
    ELSE
        IF HH12 = 12 THEN
            AMPM$ = "PM"
        ELSE
            AMPM$ = "AM"
        END IF
        IF HH12 = 0 THEN
            HH12 = 12
        END IF
    END IF
    'Using that data, create the clock string
    SELECT CASE ClockStyle$
        CASE "HH:MM AM (12hr)"
            renderTime$ = FORMAT$(HH12, "0") & ":" & FORMAT$(MM, "00") & " " & AMPM$
        CASE "HH:MM (12hr)"
            renderTime$ = FORMAT$(HH12, "0") & ":" & FORMAT$(MM, "00")
        CASE "HHMM AM (12hr)"
            renderTime$ = FORMAT$(HH12, "0") & FORMAT$(MM, "00") & " " & AMPM$
        CASE "HHMM (12hr)"
            renderTime$ = FORMAT$(HH12, "0") & FORMAT$(MM, "00")
        CASE "HH:MM (24hr)"
            renderTime$ = FORMAT$(HH, "0") & ":" & FORMAT$(MM, "00")
        CASE "HHMM (24hr)"
            renderTime$ = FORMAT$(HH, "0") & FORMAT$(MM, "00")
    END SELECT
    FUNCTION = renderTime$
END FUNCTION


SUB wrapRegisterHotkey()                'Register the hotkey for the program
    LOCAL res AS LONG, theMod AS LONG, theKey AS LONG

    'Deal with the control/alt/shift keys
    theMod = 0
    IF INSTR(ShortcutKeyModifier$, "Ctrl") > 0 THEN
        theMod = theMod OR %HOTKEYF_CONTROL
    END IF
    IF INSTR(ShortcutKeyModifier$, "Alt") > 0 THEN
        theMod = theMod OR %HOTKEYF_ALT
    END IF
    IF INSTR(ShortcutKeyModifier$, "Shift") > 0 THEN
        theMod = theMod OR %HOTKEYF_SHIFT
    END IF

    'Now deal with the main key
    SELECT CASE ShortcutKey$
        CASE "0"
            theKey = %VK_0
        CASE "1"
            theKey = %VK_1
        CASE "2"
            theKey = %VK_2
        CASE "3"
            theKey = %VK_3
        CASE "4"
            theKey = %VK_4
        CASE "5"
            theKey = %VK_5
        CASE "6"
            theKey = %VK_6
        CASE "7"
            theKey = %VK_7
        CASE "8"
            theKey = %VK_8
        CASE "9"
            theKey = %VK_9
        CASE "A"
            theKey = %VK_A
        CASE "B"
            theKey = %VK_B
        CASE "C"
            theKey = %VK_C
        CASE "D"
            theKey = %VK_D
        CASE "E"
            theKey = %VK_E
        CASE "F"
            theKey = %VK_F
        CASE "G"
            theKey = %VK_G
        CASE "H"
            theKey = %VK_H
        CASE "I"
            theKey = %VK_I
        CASE "J"
            theKey = %VK_J
        CASE "K"
            theKey = %VK_K
        CASE "L"
            theKey = %VK_L
        CASE "M"
            theKey = %VK_M
        CASE "N"
            theKey = %VK_N
        CASE "O"
            theKey = %VK_O
        CASE "P"
            theKey = %VK_P
        CASE "Q"
            theKey = %VK_Q
        CASE "R"
            theKey = %VK_R
        CASE "S"
            theKey = %VK_S
        CASE "T"
            theKey = %VK_T
        CASE "U"
            theKey = %VK_U
        CASE "V"
            theKey = %VK_V
        CASE "W"
            theKey = %VK_W
        CASE "X"
            theKey = %VK_X
        CASE "Y"
            theKey = %VK_Y
        CASE "Z"
            theKey = %VK_Z
        CASE "F1"
            theKey = %VK_F1
        CASE "F2"
            theKey = %VK_F2
        CASE "F3"
            theKey = %VK_F3
        CASE "F4"
            theKey = %VK_F4
        CASE "F5"
            theKey = %VK_F5
        CASE "F6"
            theKey = %VK_F6
        CASE "F7"
            theKey = %VK_F7
        CASE "F8"
            theKey = %VK_F8
        CASE "F9"
            theKey = %VK_F9
        CASE "F10"
            theKey = %VK_F10
        CASE "F11"
            theKey = %VK_F11
        CASE "F12"
            theKey = %VK_F12
    END SELECT

    'And set it
    res = RegisterHotKey(hMainDialog, %IDC_HOTKEY, theMod, theKey)
    IF res = 0 THEN
        MSGBOX "Error: I could not register your selected hotkey " & ShortcutKeyModifier$ & "+" & ShortcutKey$ & " -- it may already be in use. Try another key combination.", %MB_SYSTEMMODAL OR %MB_ICONERROR, "Error"
    END IF
END SUB


SUB wrapUnregisterHotkey()                                      'Free the hotkey
    UnregisterHotkey hMainDialog, %IDC_HOTKEY
END SUB


SUB CalculateWorkspace(Digits AS LONG, canvasX AS LONG, canvasY AS LONG, canvasW AS LONG, canvasH AS LONG, charW AS LONG, charH AS LONG, ratio AS DOUBLE)    'Calculate the size of characters and canvas
    'Digits is the number of characters long the string to be written is
    'canvasX, canvasY is the screen coordinate of the top-left corner of the canvas required
    'canvasW, canvasH is the size of the canvas required
    'charW, charH is the size of the individual characters
    'ratio is the scaling ratio from the original point size to the new one
    LOCAL screenW AS LONG, screenH AS LONG
    ratio = MaxPixelHeight / 323                'Sizing ratio in comparison to normal
    charW = 230 * ratio                         'Size of scaled character
    charH = MaxPixelHeight
    canvasW = charW * Digits                    'Size of total canvas
    canvasH = charH
    DESKTOP GET CLIENT TO screenW, screenH      'Screen size, excluding toolbars
    canvasX = (screenW \ 2) - (canvasW \ 2)     'Size of canvas, centered on screen
    canvasY = (screenH \ 2) - (canvasH \ 2)
    theCanvasX = canvasX
    theCanvasY = canvasY
END SUB



FUNCTION doPlay(BYVAL dummy AS DWORD) AS DWORD      'Draw the time
    LOCAL x AS INTEGER, y AS INTEGER, ctrInt AS INTEGER, res AS LONG, ctr AS LONG, timeStr$, thisDigit AS LONG
    LOCAL canvasX AS LONG, canvasY AS LONG, canvasW AS LONG, canvasH AS LONG, charW AS LONG, charH AS LONG, ratio AS DOUBLE
    LOCAL drawX AS LONG, drawY AS LONG, hScreenCap AS DWORD, lineIt AS LONG
    LOCAL hDlg  AS DWORD
    LOCAL lRslt AS LONG
    LOCAL Ret AS LONG

    timeStr$ = REMOVE$(GetCurrentTime$(), ANY " M")     'We don't need the space at the end, nor the "M" in AM/PM

    CalculateWorkspace LEN(timeStr$), canvasX, canvasY, canvasW, canvasH, charW, charH, ratio   'Where are we working, and how big?
    
    lineIt = 0

    'If we're drawing mousetrails
    IF LeaveMouseTrails <> %FALSE THEN
        'Take a screen cap
        CLIPBOARD RESET                         'Clear clipboard
        keybd_event(%VK_SnapShot, 0, 0, 0)      'This copies the screen to the clipboard
        SLEEP 500                               'Wait for it to be copied
        CLIPBOARD GET BITMAP TO hScreenCap, res 'Grab the clipboard's bitmap
        IF res <> 0 THEN                        'We successfully got the screencap
            lineIt = 1
            'Open a window with no border or caption that matches the canvas we just got info on
            DIALOG NEW PIXELS, %HWND_DESKTOP, "1", canvasX, canvasY, canvasW, canvasH, %WS_POPUP OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
            CONTROL ADD GRAPHIC, hDlg, %IDC_GRAPHIC_FAKE, "", 0, 0, canvasW, canvasH

            'Set the window's transparency to 50%
            Ret = GetWindowLong(hDlg, %GWL_EXSTYLE)
            Ret = Ret OR %WS_EX_LAYERED
            SetWindowLong hDlg, %GWL_EXSTYLE, Ret
            SetLayeredWindowAttributes hDlg, 0, 128, %LWA_ALPHA     '0=fully transparent, 255 = opaque

            'Paste the captured background into this window using GRAPHIC COPY
            GRAPHIC ATTACH hDlg, %IDC_GRAPHIC_FAKE
            GRAPHIC COPY hScreenCap, 0, (canvasX + 3, canvasY)-(canvasX + 3 - canvasW, canvasY + canvasH) TO (0, 0)
            GRAPHIC REDRAW

            GRAPHIC BITMAP END      'Throw away the bitmap we no longer need

            'Turn on dialog
            DIALOG SHOW MODELESS hDlg
        END IF
    END IF

    MOUSEPTR 1    'normal cursor

    'Go through the digits one by one
    FOR ctr = 1 TO LEN(timeStr$)
        drawX = canvasX + (charW * (ctr - 1))       'Where are we drawing this one?
        drawY = canvasY
        SELECT CASE MID$(timeStr$, ctr, 1)          'What are we drawing this time?
            CASE "0" TO "9"
                thisDigit = VAL(MID$(timeStr$, ctr, 1))
            CASE ":"
                thisDigit = 10
            CASE "A"
                thisDigit = 11
            CASE "P"
                thisDigit = 12
            CASE ELSE
        END SELECT
        res = DrawDigit(thisDigit, drawX, drawY, lineIt, ratio) 'Now draw it
        SLEEP 200
    NEXT

    'Turn off window if we're done
    IF LeaveMouseTrails <> %FALSE THEN
        Ret = GetWindowLong(hDlg, %GWL_EXSTYLE)
        Ret = Ret OR %WS_EX_LAYERED
        SetWindowLong hDlg, %GWL_EXSTYLE, Ret
        FOR ctr = 128 TO 0 STEP -8      'Fade out the window
            SetLayeredWindowAttributes hDlg, 0, ctr, %LWA_ALPHA     '0=fully transparent, 255 = opaque
            SLEEP 50
        NEXT
        DIALOG END hDlg
    END IF

END FUNCTION


FUNCTION DrawDigit(whatDigit AS LONG, whereX AS LONG, whereY AS LONG, lineIt AS LONG, OPTIONAL ratio AS DOUBLE) AS LONG        'Using the mouse, draw a digit
    'whatDigit = 0-9, 10, 11, 12
    'whereX, whereY = top left screen co-ord
    'ratio = scaling variable

    LOCAL thisDataset$, numPoints AS LONG, curPointX AS LONG, curPointY AS LONG, ctr AS LONG, ctr2 AS LONG
    LOCAL stepX AS DOUBLE, stepY AS DOUBLE, thisPointX AS LONG, thisPointY AS LONG, numSteps2 AS LONG

    IF ISMISSING(ratio) THEN        'If ratio is not set, draw at full size
        ratio = 1
    END IF

    numPoints = PARSECOUNT(pointList$(whatDigit))       'How many data points are there?

    IF lineIt = %TRUE THEN                              'Are we drawing lines (ie. mouse trails)?
        thisPointX = (VAL(PARSE$(pointList$(whatDigit), 1)) * ratio) + whereX   'Figure out start point
        thisPointY = (VAL(PARSE$(pointList$(whatDigit), 2)) * ratio) + whereY
        GRAPHIC COLOR trailsColor                       'Set the color
        GRAPHIC WIDTH 5                                 'Draw fat lines
        GRAPHIC SET PIXEL (thisPointX - thecanvasX, thisPointY - thecanvasY)    'Set start point
    END IF


    FOR ctr = 1 TO numPoints STEP (AccelerationFactor * 2)      'Go through all the points, at the requested speed
        thisPointX = (VAL(PARSE$(pointList$(whatDigit), ctr)) * ratio) + whereX         'Where is this point?
        thisPointY = (VAL(PARSE$(pointList$(whatDigit), ctr + 1)) * ratio) + whereY

        IF lineIt = %TRUE THEN
            GRAPHIC LINE STEP - (thisPointX - thecanvasX, thisPointY - thecanvasY)      'Draw a line to it if needed
        END IF

        SetCursorPos thisPointX, thisPointY             'Move mouse cursor to here
        SLEEP SlowdownFactor                            'Pause as needed
    NEXT

    FUNCTION = %TRUE
END FUNCTION
RC file:

Code:
0L ICON "GITM-CLOCK.ICO"

DEFAULTFONT RCDATA DISCARDABLE "default.set"
Note that the RC file is intended to include the default font data, so that if a user installs the program it will automatically extract that file for them so they have a character set.

--Note: updated source code to fix a typo, add "fade out" of trails, and fix mouse cursor in trail mode

Last edited by Shannon David Larratt; Dec 30th, 2009 at 03:23 PM.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 07:42 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Copyright © 1999-2010 PowerBASIC, Inc. All Rights Reserved.
Error in my_thread_global_end(): 1 threads didn't exit