Sunrise Calculation

Started by Theo Gottwald, May 06, 2024, 11:19:25 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

Copied from: Powerbasic Forum
'Reposted by Eric Pearson 03 May 2024 to remove COLOR tags caused by vBulletin database problems.
'Edited by David Roberts; 29 Mar 2015, 06:29 AM.
'"Calc_sunrise_set.bas" coded by O. Heinemeyer 3/2015
'Originally created for PBFORMS
'Modified to run in PBWIN10.4
'Update by Jim Fritts on 13 JAN 2017
'Added correction for negative longitude to locate west of Prime Meridian
'Added correction for Julian Date error
'Added display for Julian Date
'Added Date picker selection for DateStr
'Fairly accurate based on data from:
'http://aa.usno.navy.mil/data/docs/RS_OneYear.php
'Rise and Set times are within 3 minutes of table data
'when tested on the 1st and 15th of each month.

'note: did not correct issues with selecting a different UTC.
' Does not incorporate offset for DLS.

'Works with Jose Roca's includes
'Not tested with PB includes
'
'Program code to calculate sunrise and sunset times for any date and location
'Mr. Heinemeyer did a great job. Thanks!

'
'------------------------------------------------------------------------------
#COMPILER PBWIN 10
#COMPILE EXE "Calc_sunrise_set.exe"
#DIM ALL
#TOOLS OFF
'------------------------------------------------------------------------------
' ** Includes **
'------------------------------------------------------------------------------
%USEMACROS = 1
#INCLUDE ONCE "WIN32API.INC"
#INCLUDE ONCE "COMMCTRL.INC"
'---- -------------------------------------------------------------------------
GLOBAL ghDlg AS DWORD
GLOBAL stTime AS SYSTEMTIME
MACRO Pixz = 3.1415926535897932384626433832795##
MACRO Rad = 0.017453292519943295769236907684886##

GLOBAL NewComCtl AS LONG

'------------------------------------------------------------------------------
' ** Constants **
'------------------------------------------------------------------------------
%IDD_DIALOG1 = 101
%IDC_LABEL1 = 1006
%IDC_LABEL2 = 1007
%IDC_LABEL3 = 1008
%IDC_LABEL4 = 1009
%IDC_LABEL5 = 1012
%IDC_LABEL6 = 1013
%IDC_FRAME1 = 1014
%IDC_FRAME2 = 1015
%IDC_FRAME3 = 1016
%IDC_SYSMONTHCAL32_1 = 1020
%IDC_LABEL7 = 1021
%IDC_FRAME4 = 1022
%IDC_LABEL8 = 1023
%IDC_CALCULATE = 1004
%IDC_LATITUDE = 1010
%IDC_LONGITUDE = 1011
%IDC_SUNRISE = 1002
%IDC_SUNSET = 1003
%IDCANCEL = 2
%IDC_LABEL9 = 1026
%IDC_LABEL10 = 1027
%IDC_TEXTBOX1 = 1028
%IDC_LABEL11 = 1029
%IDC_UTC_0 = 1030
%IDC_UTC_1 = 1031
%IDC_UTC_2 = 1032
%IDC_TEXTBOX2 = 1033
%IDC_LABEL12 = 1034
%IDC_TEXTBOX3 = 1035 'display the selected julian date
'------------------------------------------------------------------------------
' ** Declarations **
'------------------------------------------------------------------------------
DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG

DECLARE FUNCTION zInitCommonControlsEx (icc AS INIT_COMMON_CONTROLSEX) AS LONG

'------------------------------------------------------------------------------
' ** Main Application Entry Point **
'------------------------------------------------------------------------------
FUNCTION PBMAIN()
'Variables for IP-Camera handling
LOCAL hDlg AS LONG
LOCAL t1, t2 AS STRING
LOCAL year, month, day AS WORD
'Variables for Sunriseset calculation
LOCAL tr, sr, ss, RA, Decl, latitude, longitude AS EXT
LOCAL sMsg AS STRING
LOCAL vDate AS DOUBLE
LOCAL st AS SYSTEMTIME

NewComCtl = InitComctl32X (%ICC_BAR_CLASSES OR %ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR _
%ICC_INTERNET_CLASSES)

ShowDIALOG1 %HWND_DESKTOP

END FUNCTION
'------------------------------------------------------------------------------
' ** CallBacks **
'------------------------------------------------------------------------------
CALLBACK FUNCTION ShowDIALOG1Proc()

LOCAL pNMSC AS NMSELCHANGE PTR
LOCAL pDTMC AS NMDATETIMECHANGE PTR
GLOBAL DateStr AS STRING
STATIC time_zone AS LONG
LOCAL i, hFile, dayofyear, old_zone AS LONG
LOCAL a, srise, sset AS STRING

DIM buffer(6) AS STATIC STRING

'Variables for Sunriseset calculation
LOCAL result, sMsg AS STRING
LOCAL tr, sr, ss, RA, Decl, latitude, longitude AS EXT
LOCAL vDate AS DOUBLE
LOCAL st AS SYSTEMTIME

SELECT CASE AS LONG CB.MSG

CASE %WM_INITDIALOG
IF ISFILE(EXE.NAME$ +".inf") THEN
hFile = FREEFILE
OPEN EXE.NAME$+".inf" FOR INPUT AS hFile
WHILE NOT EOF (hFile)
LINE INPUT# hFile, buffer(i)
INCR i
WEND
CLOSE hFile
END IF
'data from .inf file -> dialog
CONTROL SET TEXT ghDlg, %IDC_LATITUDE, buffer(1)
CONTROL SET TEXT ghDlg, %IDC_LONGITUDE, buffer(2)

CONTROL SET OPTION ghDlg, %IDC_UTC_0+VAL(buffer(6)), %IDC_UTC_0, %IDC_UTC_2
time_zone = VAL(buffer(6)) ' 0, 1 or 2

DateStr = MID$(DATE$, 4, 2) + "." + MID$(DATE$, 1, 2) + "." + MID$(DATE$, 7, 4)
PostMessage ghDlg, %WM_COMMAND, %IDC_CALCULATE, 0


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

CASE %WM_NOTIFY

SELECT CASE CB.CTL

CASE %IDC_SYSMONTHCAL32_1
' Set up the NMSELCHANGE pointer passed in CB.LPARAM
pNMSC = CB.LPARAM

' Detect changes in the calendar control
IF @pNMSC.hdr.code = %MCN_SELCHANGE THEN ' Get selected date/time
DateStr = FORMAT$(@pNMSC.stSelStart.wDay,"00")+"." _
+ FORMAT$(@pNMSC.stSelStart.wMonth,"00")+"." _
+ FORMAT$(@pNMSC.stSelStart.wYear,"0000")

END IF

END SELECT


CASE %WM_SYSCOLORCHANGE, %WM_WININICHANGE
' If user changes system settings (color, etc), forward the change
' notification message to the Calendar control
CONTROL SEND CB.HNDL, %IDC_SYSMONTHCAL32_1, CB.MSG, CB.WPARAM, CB.LPARAM

CASE %WM_COMMAND
' Process control notifications
SELECT CASE AS LONG CB.CTL

CASE %IDC_UTC_0
old_zone = time_zone
time_zone = 0
IF time_zone <> old_zone THEN
ChangeTime(ghDlg,%IDC_SUNRISE, (time_zone-old_zone))
ChangeTime(ghDlg,%IDC_SUNSET, (time_zone-old_zone))
END IF
CASE %IDC_UTC_1
old_zone = time_zone
time_zone = 1
IF time_zone <> old_zone THEN
ChangeTime(ghDlg,%IDC_SUNRISE, (time_zone-old_zone))
ChangeTime(ghDlg,%IDC_SUNSET, (time_zone-old_zone))
END IF
CASE %IDC_UTC_2
old_zone = time_zone
time_zone = 2
IF time_zone <> old_zone THEN
ChangeTime(ghDlg,%IDC_SUNRISE, (time_zone-old_zone))
ChangeTime(ghDlg,%IDC_SUNSET, (time_zone-old_zone))
END IF

CASE %IDCANCEL
IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
FetchData buffer()
buffer(6) = STR$(time_zone)
hFile = FREEFILE
OPEN EXE.NAME$+".inf" FOR OUTPUT AS hFile
FOR i = 0 TO 6
PRINT# hFile, buffer(i)
NEXT i
CLOSE hFile
DIALOG END CB.HNDL, 0
END IF

CASE %IDC_CALCULATE
IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
FetchData buffer()
CONTROL SET TEXT ghDlg, %IDC_FRAME1, "times calculated for " + MID$(DateStr, 7, 4) + "-" + MID$(DateStr, 4, 2) + "-" + MID$(DateStr, 1, 2)'buffer(5)
'1=latitude, 2=longitude, 3=sunr, 4=suns, 5=date, 6=time_zone
IF TRIM$(buffer(1)) = "" THEN EXIT FUNCTION
IF TRIM$(buffer(2)) = "" THEN EXIT FUNCTION
latitude = VAL(buffer(1))
longitude= VAL(buffer(2))

vDate = INT(StrToVBDate(buffer(5)))
VariantTimeToSystemTime vDate, st
sMsg = ""

result = Sun_rise_set_advanced(latitude, longitude, JulianDate, time_zone)
SetTime ghDlg, %IDC_SUNRISE, PARSE$(result, $TAB, 2)+":00" 'set new sunrise
SetTime ghDlg, %IDC_SUNSET, PARSE$(result, $TAB, 3)+":00" 'set new sunset
CONTROL SET TEXT ghDlg, %IDC_TEXTBOX3, STR$(JulianDate)
SetFocus GetDlgItem(ghDlg, %IDC_CALCULATE)
END IF
END SELECT
END SELECT
END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
' ** Dialogs **
'------------------------------------------------------------------------------
FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
LOCAL lRslt AS LONG

LOCAL hDlg AS DWORD

DIALOG NEW hParent, "Calculate sunrise & sunset times", 73, 105, 401, _
222, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR _
%WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
%WS_VISIBLE OR %DS_MODALFRAME 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 "SysDateTimePick32", hDlg, %IDC_SUNRISE, _
"SysDateTimePick32_1", 180, 20, 60, 15, %WS_CHILD OR %WS_VISIBLE OR _
%WS_TABSTOP OR %DTS_TIMEFORMAT, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
%WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
CONTROL ADD "SysDateTimePick32", hDlg, %IDC_SUNSET, _
"SysDateTimePick32_1", 180, 40, 60, 15, %WS_CHILD OR %WS_VISIBLE OR _
%WS_TABSTOP OR %DTS_TIMEFORMAT, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
%WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
CONTROL ADD "SysMonthCal32", hDlg, %IDC_SYSMONTHCAL32_1, _
"SysMonthCal32_1", 265, 70, 125, 110, %WS_CHILD OR %WS_VISIBLE OR _
%WS_TABSTOP OR %MCS_NOTODAYCIRCLE, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT _
OR %WS_EX_LTRREADING OR %WS_EX_LEFTSCROLLBAR

CONTROL ADD TEXTBOX, hDlg, %IDC_LATITUDE, "", 165, 80, 75, 15
CONTROL ADD TEXTBOX, hDlg, %IDC_LONGITUDE, "", 165, 100, 75, 15

CONTROL ADD TEXTBOX, hDlg, %IDC_TEXTBOX3, "", 20, 185, 75, 15

CONTROL ADD BUTTON, hDlg, %IDCANCEL, "Terminate", 280, 185, 95, 20
CONTROL ADD LABEL, hDlg, %IDC_LABEL1, "sunrise ", 105, 20, 60, 15
CONTROL ADD LABEL, hDlg, %IDC_LABEL2, "sunset", 105, 40, 60, 15
CONTROL ADD LABEL, hDlg, %IDC_LABEL5, "Latitude [N=+, S=-]", 45, 80, _
105, 15
CONTROL ADD LABEL, hDlg, %IDC_LABEL6, "Longitude [W=-, E=+]", 45, 100, _
110, 15
CONTROL ADD FRAME, hDlg, %IDC_FRAME1, "calculated times", 20, 5, 235, _
55
CONTROL ADD FRAME, hDlg, %IDC_FRAME2, "localization [decimal degrees]", _
20, 65, 235, 55
CONTROL ADD BUTTON, hDlg, %IDC_CALCULATE, "Calculate", 295, 10, 65, 20
CONTROL ADD LABEL, hDlg, %IDC_LABEL7, "Choose the date you want the " + _
"calculation to be made for from below. Then press 'Calculate'", _
270, 40, 115, 30, %WS_CHILD OR %WS_VISIBLE OR %SS_CENTER, _
%WS_EX_LEFT OR %WS_EX_LTRREADING
CONTROL ADD OPTION, hDlg, %IDC_UTC_0, "UTC+0", 25, 20, 65, 10
CONTROL ADD OPTION, hDlg, %IDC_UTC_1, "UTC+1", 25, 30, 65, 10
CONTROL ADD OPTION, hDlg, %IDC_UTC_2, "UTC+2", 25, 40, 65, 10
CONTROL ADD LABEL, hDlg, %IDC_LABEL12, "This user interface is just a " + _
"stub for your own modifications. Feel free to modify and use the " + _
"code for any of your needs. The same applies for the code for the " + _
"calculations .", 20, 130, 235, 40
ghDlg = hDlg
DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt

FUNCTION = lRslt
END FUNCTION

' --------------------------------------------------------------------------
SUB ChangeTime(BYVAL hWnd AS DWORD, BYVAL CtlID AS DWORD, change AS LONG)
' Retrieve Time String from Control in HH:MM:SS format
LOCAL dt AS SYSTEMTIME

CONTROL SEND hWnd, CtlID, %DTM_GETSYSTEMTIME, 0, VARPTR(dt)
dt.wHour = dt.whour + change
CONTROL SEND hWnd, CtlID, %DTM_SETSYSTEMTIME, %GDT_VALID, VARPTR(dt)

END SUB
' --------------------------------------------------------------------------
SUB GetDate(BYVAL hWnd AS DWORD, BYVAL CtlID AS DWORD, DateStr AS STRING)
' Retrieve Date String from Control in yyyy:mm:dd format
LOCAL dt AS SYSTEMTIME

CONTROL SEND hWnd, CtlID, %DTM_GETSYSTEMTIME, 0, VARPTR(dt)
Datestr = FORMAT$(dt.wDay,"00") & "." & _
FORMAT$(dt.wMonth,"00") & "." & _
FORMAT$(dt.wYear, "0000")

END SUB

' --------------------------------------------------------------------------
SUB SetTime(BYVAL hWnd AS DWORD, BYVAL CtlID AS DWORD, TimeStr AS STRING)
' Set Control to time in string HH:MM:SS format.
LOCAL dt AS SYSTEMTIME
LOCAL x AS WORD

' These date items must be set or it won't work!
dt.wMonth = 1
dt.wDay = 1
dt.wYear = 2000

IF LEN(TimeStr) <> 8 THEN EXIT SUB ' Wrong Length
x = VAL(LEFT$(TimeStr,2)) ' First Check Hour
IF x > 23 THEN EXIT SUB ' Bad Format
dt.wHour = x
x = VAL(MID$(TimeStr,4,2))
IF x > 59 THEN EXIT SUB ' Bad Format
dt.wMinute = x
x = VAL(RIGHT$(TimeStr,2))
'x = 0
IF x > 59 THEN EXIT SUB ' Bad Format
dt.wSecond = x

CONTROL SEND hWnd, CtlID, %DTM_SETSYSTEMTIME, %GDT_VALID, VARPTR(dt)
END SUB

' --------------------------------------------------------------------------
SUB FetchData (buffer()AS STRING)
CONTROL GET TEXT ghDlg,%IDC_LATITUDE TO buffer(1)
CONTROL GET TEXT ghDlg,%IDC_LONGITUDE TO buffer(2)
CONTROL GET TEXT ghDlg,%IDC_SUNRISE TO buffer(3)
CONTROL GET TEXT ghDlg,%IDC_SUNSET TO buffer(4)
GetDate ghDlg, %IDC_SYSMONTHCAL32_1, buffer(5)
END SUB

FUNCTION uString(BYVAL x AS STRING) AS STRING
LOCAL y AS STRING
LOCAL n AS INTEGER
IF LEN(x) THEN
FOR n = 1 TO LEN(x)
y = y + MKI$(ASC(x, n))
NEXT n
END IF
FUNCTION = y
END FUNCTION

FUNCTION StrToVbDate(BYVAL dt AS STRING) AS DOUBLE
LOCAL x AS LONG
LOCAL y AS STRING
LOCAL vbdate AS DOUBLE
dt = uString(dt)
IF ISFALSE(VarDateFromStr(BYVAL STRPTR(dt), 0, 0, vbdate)) THEN
FUNCTION = vbdate
END IF
END FUNCTION

FUNCTION Sun_rise_set_advanced(latitude AS EXT, longitude AS EXT, JD AS DOUBLE, time_zone AS LONG) AS STRING
'advanced calculation function for sunrise and sunset times with respect to different years
'according to http://lexikon.astronomie.info/zeitgleichung/, Arnold Barmettler
'time_zone = 0 'Worldtime (UTC)
'time_zone = 1 'European Wintertime
'time_zone = 2 'European Summertime

LOCAL JD2000, T, h, B AS DOUBLE
LOCAL rise_LT, set_LT, rise_UTC, set_UTC, rise_SLT, set_SLT AS EXT
LOCAL declination, time_function, time_difference AS EXT

JD2000 = 2451545.0
T = (JD - JD2000)/36525.0
time_function = calculate_time_function(declination, T)

h = -50.0/60.0*Rad 'angel of sunrise = -50 minutes = -0.0145 rad
B = latitude*Rad
time_difference = 12.0*arccos((SIN(h) - SIN(B)*SIN(declination))/(COS(B)*COS(declination)))/Pixz

rise_LT = 12.0 - time_difference - time_function
set_LT = 12.0 + time_difference - time_function
rise_UTC = rise_LT - (longitude /15.0)
set_UTC = set_LT - (longitude /15.0)

rise_SLT = rise_UTC + time_zone 'in decimal hours Standard Local Time
IF rise_SLT<0.0 THEN : rise_SLT = rise_SLT + 24.0
IF rise_SLT>=24.0 THEN : rise_SLT = rise_SLT - 24.0

set_SLT = set_UTC + time_zone 'in decimal hours Standard Local Time
IF set_SLT<0.0 THEN : set_SLT = set_SLT + 24.0
IF set_SLT>=24.0 THEN : set_SLT = set_SLT - 24.0

FUNCTION = STR$(JD) + $TAB + toHHMMSS(rise_SLT) + $TAB + toHHMMSS(set_SLT)
END FUNCTION

FUNCTION JulianDate () AS DOUBLE ' (year AS WORD, month AS WORD, day AS WORD, hour AS WORD, minutes AS WORD, seconds AS DOUBLE) AS DOUBLE
LOCAL gregor AS LONG 'gregorian calender
LOCAL year AS WORD
LOCAL month AS WORD
LOCAL day AS WORD
LOCAL hour AS WORD
LOCAL minutes AS WORD
LOCAL seconds AS DOUBLE

'DateStr format DD.MM.YYYY
day = VAL(MID$(DateStr, 1, 2))
month = VAL(MID$(DateStr, 4, 2))
year = VAL(MID$(DateStr, 7, 4))

hour = 12
minutes = 0
seconds = 0

IF (month < =2) THEN
month = month + 12
year = year -1
END IF
gregor = (year/400)-(year/100)+(year/4)
FUNCTION = (2400000.5+365.0 * year - 679004.0 + gregor _
+ INT(30.6001*(month + 1)) + day + hour/24.0 _
+ minutes/1440.0 + seconds/86400.0) - 1

END FUNCTION

FUNCTION InPi(x AS EXT) AS EXT
LOCAL N AS LONG
n = INT(x/(2*Pixz))
x = x - n*2*Pixz
IF (x<0)THEN : x = x + 2*Pixz
FUNCTION = x
END FUNCTION

FUNCTION eps(T AS DOUBLE) AS EXT
'inclination of axis of the earth
FUNCTION = Rad *(23.43929111 + (-46.8150*T - 0.00059*T*T + 0.001813*T*T*T)/3600.0)
END FUNCTION

FUNCTION arcsin(Value AS EXT) AS EXT
FUNCTION = ATN(Value / SQR(1 - Value * Value))
END FUNCTION

FUNCTION arccos(Value AS EXT) AS EXT
FUNCTION = Pixz / 2 - ATN(Value / SQR(1 - Value * Value))
END FUNCTION

FUNCTION toHHMMSS(hh AS EXT) AS STRING
LOCAL mm, ss, ret AS STRING
LOCAL x AS EXT

ret = FORMAT$(INT(hh), "00") 'hours
x = hh - INT(hh)
x = x * 60
ret = ret + ":" + FORMAT$(INT(x), "00") 'minutes:
x = x - INT(x)
x = x * 60
'ret = ret + ":" + FORMAT$(x, "00.000") 'seconds:
FUNCTION = ret
END FUNCTION

FUNCTION calculate_time_function(declination AS EXT, T AS DOUBLE)AS EXT
LOCAL RA_mean, M, L, e, RA, dRA AS EXT

RA_mean = 18.71506921 + 2400.0513369*T +(2.5862e-5 - 1.72e-9*T)*T*T

'calculate the Sun's mean anomaly
M = InPi(Pixz*2 * (0.993133 + 99.997361*T))

'calculate the Sun's true longitude
L = InPi(Pixz*2 * (0.7859453 + M/(Pixz*2) + (6893.0*SIN(M)+72.0*SIN(2.0*M)+6191.2*T) / 1296.0e3))

'calculate the Sun's right ascension
e = eps(T)
RA = ATN(TAN(L)*COS(e))

'right ascension value needs to be in the same quadrant
IF (RA < 0.0) THEN : RA = RA + Pixz
IF (L > Pixz) THEN : RA = RA + Pixz

'right ascension value needs to be converted into hours
RA = 24.0*RA/(Pixz*2)

'calculate the Sun's declination
declination = arcsin(SIN(e)*SIN(L))

'calculate the Sun's local hour angle

'finish calculating H and convert into hours

RA_mean = 24.0*InPi(Pixz*2*RA_mean/24.0)/(Pixz*2) 'for 0<=RA_mean<24
dRA = RA_mean - RA
IF (dRA < -12.0)THEN: dRA = dRA + 24.0
IF (dRA > 12.0) THEN: dRA = dRA - 24.0
dRA = dRA* 1.0027379
FUNCTION = dRA
END FUNCTION


FUNCTION InitComctl32X (BYVAL iccClasses AS DWORD ) AS LONG
LOCAL hLib AS DWORD
LOCAL dwProc AS DWORD
LOCAL iccex AS INIT_COMMON_CONTROLSEX

hLib = LoadLibrary("COMCTL32.DLL")
IF hLib THEN
dwProc = GetProcAddress(hLib, "InitCommonControlsEx")
IF dwProc THEN
FUNCTION = 1 'return 1 on success
iccex.dwSize = SIZEOF(iccex) 'fill the iccex structure
iccex.dwICC = iccClasses 'tell what classes to initiate
CALL DWORD dwProc USING zInitCommonControlsEx(iccex)
ELSE
InitCommonControls
END IF
CALL FreeLibrary(hLib) 'we can FreeLibrary now, because InitCommonControls(Ex)
END IF 'has made sure comctl32.dll is loaded into the system.

END FUNCTION