Charles,
Attached compiles and runs fine with 0.8.0 2025-02-19
James
Hi James,
I found some logistical problems with macro '=' default values, so I had to withdraw this feature. but you can still test any macro parameter, and provide a default definition/value:
'Macro LineInput string (s,c,b=1024)
Macro LineInput string (s,c,b)
#ifndef b
% b=1024
#endif
s = nuls b
s = (char*)fgets(s,b,c)
End Macro
Hi Charles,
I also have problems with version 0.9.0 2025-03-31. If I run the demos in folder ... WinGUI\Autosizing I get error messages like: Undefined Symbol: maxpinned.count. If I run in !ProjB\Console\AsciTetris the app, the program will not run correctly or not at all, showing an error message with unidentified names.
I replaced oxygen.dll 0.9.0 with oxygen.dll 0.8.0 and everything works fine. I am not sure if I have to modify anything with the .o2bas or .inc files?
I only tested with oxygen.dll 32-bit and only these applications. Are changes to the programs necessary for 0.9.0?
Thanks Roland,
I've fixed 2 problems exposed by your code.
One affected redims using an object member as an index.
The other was an unwanted (internal) macro symbol case conversion.
I've also restored macro default values, so James' original example now works.
I made over 60 changes for version 0.9.0. The main ones are to remove the upper limit on primary symbol count (was 32k) by using dynamic storage. Also to make macro compiling more efficient. I also discovered a memory overflow bug which could destabilize larger compilations.
QuoteRELEASE 0.9.0
16:14 01/04/2025 Fix macro symbol case-matching (himac icase=1)
16:12 01/04/2025 Fix dynamic array index (ert=504)
00:51 01/03/2025 Reduce code for function defaults (subsas)
18:16 31/03/2025 Restore Macro default values. New code. (Himac w5)
12:02 31/03/2025 Remove string initializers (reco.inc strini strinr)
02:33 31/03/2025 Fix records clearing size (reco.inc init4 @drc)
09:22 30/03/2025 Dynamic Records (reco.inc maxit)
02:51 30/03/2025 Fix records member int sizes .a and .f (reco.inc)
17:12 28/03/2025 Reduce nest/unnest staticvars etc (reco.inc)
13:49 28/03/2025 Fix 'unnest' to always retain local space (reco.inc lclr)
02:05 26/03/2025 Change namespace symbol from '..' to '::' (colom setnamespace)
20:15 23/03/2025 Revoke checking for colons in single line type statements (tran.inc " : ")
11:39 23/03/2025 Revoke recursion/expansion for deff macros. (expr.inc expandfmac)
22:20 21/03/2025 Fix higher type '+=' '*=' macros (tran.inc expr.inc cpa>2)
04:56 21/03/2025 Fix higher function return copy (rps=16)
16:52 20/03/2025 Optimize Higher types assignment (tran.inc accg)
22:20 17/03/2025 Inhibit macro param case conversion (parse.inc lomac icas=1)
22:10 11/03/2025 Implement more efficient namespace resolution (reco.inc dotm))
15:53 10/03/2025 Implement nested namespace without leading '..' (reco.inc nss nk))
11:04 10/03/2025 Implement %0 unique symbol substitution in def macros (lomac)
11:03 10/03/2025 Revoke %% escape check in def macros. (lomac)
03:38 09/03/2025 Support d[1]={...} : n=countof (massign elct)
14:16 08/03/2025 Revoke default values in macros (pars.inc himac)
15:42 07/03/2025 Implement #unquote (pars.inc mword() )
11:55 07/03/2025 Remove ##. from OpenglScrnrFrame.inc etc macros
01:44 07/03/2025 Rework himac and replacewd / macro (pars.inc lexi.inc)
20:40 04/03/2025 Revoke embedfile (ebd)
22:16 03/03/2025 Support infinity as a variable (lang.inc)
22:04 03/03/2025 Implement initialization macro (lang.inc tran.inc)
17:44 03/03/2025 Changes in lang.inc: pow and exp (lang.inc ~~~)
00:51 01/03/2025 Prevent peroxide terminating on escape key (27) (peroxide.o2as)
21:20 28/02/2025 Support 'foreach x x[ i ]= ...' (lang.inc)
21:20 28/02/2025 Support 'on x gosub/goto' (lang.inc)
21:20 28/02/2025 Support 'view x' (lang.inc)
21:20 28/02/2025 Support 'stretch x(n)' (lang.inc)
21:20 28/02/2025 Support 'dyn int x(n)' (lang.inc)
21:09 28/02/2025 Support '#tally {1,2,3 ...}' (pars.inc)
12:37 28/02/2025 Revoke 'inner', use 'scope' instead (lang.inc)
12:06 28/02/2025 Improve 'anymatch' (meta.inc anymatch idword)
02:42 28/02/2025 Rearrange records structure (reco.inc records)
02:34 27/02/2025 Fix detection of excess left bracket in classes etc (nocapt)
19:40 26/02/2025 Extend #show to display resolved macros (pars.inc shd...)
11:20 25/02/2025 Fix redim zc / idx / mf (glo2\graphicOjects.inc)
03:12 24/02/2025 Annotation of code in #show (enco.inc shd)
19:12 23/02/2025 Change asm loading literal numbers 64it (CheckLiteral)
19:09 23/02/2025 Display variale names in #show (shd)
23:19 22/02/2025 Enable all dynamic arrays to define multidims (rarray)
23:19 22/02/2025 Remove array Attribs table from class _table (no vot)
23:19 22/02/2025 Fix flagsof() on undefined variable ('flagsof)
05:43 22/02/2025 Support simple arrays without attribs table ( _dims_ )
05:43 22/02/2025 Fix dynamic arrays (ert=503)
04:40 21/02/2025 Expand capacity from 32k to 128k symbols etc (maxit)
05:17 19/02/2025 Fix on .. macro params (lang.inc)
05:17 19/02/2025 Fix goto/gosub labels/variables (tran.inc 'goto fwd)
20:02 18/02/2025 Undef insturction extended to block labels (o2 z)
04:56 18/02/2025 Support ForEach x {x[ i ]=...} (lang.inc)
01:24 18/02/2025 Fix #unique: allow function overloads and declarations (rec.inc -5)
23:09 17/02/2025 Support 'view' macros (lang.inc)
20:28 17/02/2025 Change messagebox title from O2H to O2H (mbox RTL32/64)
16:58 17/02/2025 Support 'on' macro for on gosub/goto (lang.inc)
02:42 15/02/2025 Fix register spills for ms64 byval h params (typq aprm))
20:17 13/02/2025 Support pseudo-variable assignment with default param functions (subsas)
11:15 12/02/2025 Changes to Manual (oxyDatabase.inc OxygenBasic_Manual.chm)
05:34 10/02/2025 Support subroutines to always retain local space (lclr)
14:58 06/02/2025 Support dim c as asciiz*20*10 (rmuldim:)
Hi Charles,
these are really a lot of Innovations and it will take some time to test them all.
Unfortunatelly the AsciTerix.o2bas app still does not work correctly. The shape on the left side does not correspond to the shape of the right side. Moreover the shape leaves the ground on the left side, and nothing works any more..
Demo1.o2bas and SmallApp.o2bas of the Autosizing folder work as expected, but the sizing of demo2, demo3, demo4, demo5, demo6 does not happen.
Demo4.o2bas also show errors like: Cannot find hCtl: 590640in PinCtl_Rec, hctl: 329524 in PinCtl_Rec
Demo7Dlg.o2bas shows an error in line 32: Unidentified element type: WORD type... The app then terminates
As these apps work fine with version 0.8.0 I have not yet started further examination.
I also noticed that in console mode printl without argument does not work anymore. This form is used in testlog2.o2bas and testlog3.o2bas too.
I found in Console.inc:
function printl(cstr_*s="")
'==========================
output s cr
end function
In ConsoleG.inc there is:
sub printl(optional string s)
=============================
output s,1.0
end sub
Does this make a difference?
@Charles Pegge recommend that you try Googles AI-Studio.
https://aistudio.google.com/prompts/new_chat (http://ai-studio/)it has up to MB Kontextwindow, means you can just drop your whole code and ask "Where are the bugs"".
It may even return you the corrections needed. Give it a try.
Of course googe wil lcollect code this way to train their systems.
But ... our code is not a secret.
I saved hours or days of coding and bug-searching.
Just dropped the not working Sub into google ... got the corrected code back.
Together with a commentblock.
TIP: If you have special coding wishes write them into the system prompt at the top of the page.
TIP: It will also write your helpfiles. Drop it the source code of the commands .... and a sample of the format of your help file. Thats all, it will then write the XML-Code (or whatever you like) for your helpfile.
Help file writing is most annoying. I am so happy AI does it.
I get strange messages:
Edge:
Hmmm...diese Seite ist leider nicht erreichbar
Überprüfen Sie, ob in ai-studio ein Tippfehler vorliegt.
Im Web nach ai-studio suchen
Another Browser:
Diese Website ist nicht erreichbar
Prüfe, ob ,,ai-studio" einen Tippfehler enthält.
Wenn die URL keinen Tippfehler enthält, kannst du die Windows-Netzwerkdiagnose durchführen.
DNS_PROBE_FINISHED_NXDOMAIN
Heading:
Website not safe
At last I've fixed THE issues with redim and macro which caused problems with your autosizing and Tetris demos.
The only change that needs to be made is to reformat the single liner types in demos\WinGUI\Autosizing\Demo7dlg.o2bas. Colons in types are no longer supported. Just use commas. but for easier reading, the larger types should be presented in the standard block format.
type TCITEM int mask,dwState,dwStateMask, char* pszText, int cchTextMax,iImage, sys lParam
typedef TCITEM TC_ITEM
type TBADDBITMAP , sys hInst , sys nID
type TBBUTTON , int iBitmap , int idCommand , BYTE fsState , BYTE fsStyle , dword dwData , sys iString
Further update fixing James' console print problem. Macros handling complex expression params:
Hi Charles,
I downloaded Oxygenbasic.zip version 0.09.0 2025-04-04T15:04. AsciTerix works fine, also AsciTerix2 where you used different coding variations. But I suppose the Home - Shortcut is superfluous?
Checking the demos in the WinDynDialogs folder, most of the apps work fine. But I noticed that in Listview.o2bas there is an error message:
ERROR: unclosed brackets at end of script (1)
COL: 1
LINE: 271
FILE: "main source"
Moreover Pgbar3d.o2bas and Pgbar3d3.o2bas do not run at all. As all the demos work fine with version 0.8.0 I am not sure if there are changes like with the single liner types, which must be taken into account, or if there is something missing in oxygen.dll. Hopefully you do not think that I am lazy.
Hi Charles,
I found the missbehaviour of Listview.o2bas in function AboutDlgProc in line 116, 117. If I modify this:
' if loword(wParam) = IDCANCEL or
' loword(wParam) = IDOK then
if loword(wParam) = IDCANCEL or loword(wParam) = IDOK then
then the app will run. But I think line 116, 117 should also work?
Nevertheless there is a mistake in line 201 / 202 also. The line should read.
Dialog( 0,0,144,77, "About Listview Sample",
So this would be the interim code:
'====================================================================
' Listview example, nested modeless dialog.
'====================================================================
$ filename "ListView.exe"
'uses rtl32
'uses rtl64
'% review
uses dialogs
'Identifiers
#define IDD_DLG1 1000
#define IDC_LSV1 1001
#define IDM_EXIT 104
#define IDM_ABOUT 105
#define IDI_LOGO 106
macro ListView_InsertColumn(hwnd,iCol,pcol) (SendMessage(hwnd, LVM_INSERTCOLUMN, iCol, pcol))
macro ListView_SetColumnWidth(hwnd,iCol,cx) (SendMessage(hwnd, LVM_SETCOLUMNWIDTH, iCol, cx))
macro ListView_InsertItem(hwnd,pitem) (SendMessage(hwnd, LVM_INSERTITEM,0, pitem))
macro ListView_SetItem(hwnd,pitem) (SendMessage(hwnd, LVM_SETITEM,0, pitem))
% DS_CENTER=0x0800
% DS_MODALFRAME=0x80
% SS_CENTERIMAGE=0x200
% LVS_LIST 0x0003
% LVS_REPORT 0x0001
% LVS_EX_GRIDLINES 1
% LVS_EX_CHECKBOXES 4
% LVS_EX_FULLROWSELECT 0x0020
% LVSCW_AUTOSIZE -1
% LVSCW_AUTOSIZE_USEHEADER -2
% LVM_INSERTCOLUMN=4123
% LVM_SETCOLUMNWIDTH=4126
% LVM_INSERTITEM=4103
% LVM_SETITEM=4102
% LVCF_FMT 1
% LVCF_WIDTH 2
% LVCF_TEXT=4
% LVCF_SUBITEM 8
% LVIF_TEXT=1
% LVM_SETEXTENDEDLISTVIEWSTYLE 0x1036
% LVN_COLUMNCLICK = -108
% LVN_ITEMCHANGED = -101
% LR_LOADFROMFILE=0x0010
% IMAGE_ICON=1
% STM_SETIMAGE=0x172
% SWP_NOZORDER=4
type LVCOLUMN
uint mask
int fmt
int cx
char* pszText
int cchTextMax
int iSubItem
int iImage
int iOrder
int cxMin
int cxDefault
int cxIdeal
end type
typedef LVCOLUMN LV_COLUMN
type LVITEM
uint mask
int iItem
int iSubItem
uint state
uint stateMask
char* pszText
int cchTextMax
int iImage // index of the list view item's icon
sys lParam // 32-bit value to associate with item
int iIndent
int iGroupId
uint cColumns
uint *puColumns
int *piColFmt
int iGroup
end type
typedef LVITEM LV_ITEM
% LVROWS = 200 ' Number of rows in the ListView
% LVCOLS = 3 ' Number of columns in the ListView
! GetDlgItem lib "user32.dll" (sys hDlg, int nIDDlgItem) as sys
! IsDialogMessage lib "user32.dll" alias"IsDialogMessageA" (sys hDlg, sys lpMsg) as bool
! IsWindow lib "user32.dll" (sys hWnd) as bool
sys AboutDlg
'string o2dir = "c:\oxygenbasic\"
string o2dir = "..\..\"
string fullname
init_common_controls()
function AboutDlgProc( sys hDlg, uint uMsg, sys wParam, lParam) as sys callback
select case uMsg
case WM_INITDIALOG
fullname = o2dir + "tools\OxideIcon.ico"
sys hIcon = LoadImage( 0, fullname, IMAGE_ICON,0,0, LR_LOADFROMFILE )
if hIcon=null then mbox "Cannot load " + fullname +"!"
SendMessage (GetDlgItem(hDlg,IDI_LOGO), STM_SETIMAGE, IMAGE_ICON, hIcon)
case WM_COMMAND
' if loword(wParam) = IDCANCEL or
' loword(wParam) = IDOK then
if loword(wParam) = IDCANCEL or loword(wParam) = IDOK then
DestroyWindow( hDlg )
end if
case WM_CLOSE
DestroyWindow( hDlg )
'Reset so main can determine if nested dialog is open.
AboutDlg = 0
end select
return 0
end function
'====================================================================
function DlgProc( sys hDlg, uint uMsg, sys wParam, lParam ) as sys callback
sys hMenu
sys hListview = GetDlgItem(hDlg, IDC_LSV1)
int i,j
LV_COLUMN lvc
LV_ITEM lvi
select case uMsg
case WM_INITDIALOG
MENU(hMenu)
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit",IDM_EXIT
ENDMenu
POPUP "&Help"
BEGIN
MENUITEM "&About...",IDM_ABOUT
ENDMenu
ENDMenu
if SetMenu( hDlg, hMenu ) = 0 then
mbox "SetMenu hMenu failed!"
end if
string text
'Column Headers
For i = 0 To LVCOLS
lvc.mask = LVCF_FMT OR LVCF_WIDTH OR LVCF_TEXT OR LVCF_SUBITEM 'LVCF_TEXT
text="Column #" & str(i+1)
lvc.pszText = text
ListView_InsertColumn(hListview, i, &lvC)
Next i
'Rows
For i=1 To LVROWS
'First column
lvi.mask = LVIF_TEXT
text = "Row #" & str(200-i+1) ", Col # 1"
lvi.pszText = text
lvi.iSubItem = 0
ListView_InsertItem(hListview, &lvi)
'Remaining columns
for j=2 to LVCOLS
text = "Row #" & str(200-i+1) ", Col # " & str(j)
lvi.pszText = text
lvi.iSubItem = j-1
ListView_SetItem(hListview, &lvi)
next j
Next i
for i = 0 to LVCOLS
ListView_SetColumnWidth(hListview,i,LVSCW_AUTOSIZE_USEHEADER)
next i
SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES)
' SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES)
' SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_CHECKBOXES)
case WM_COMMAND
select case loword(wParam)
case IDM_ABOUT
'Open nested dialog only if not already open.
if IsWindow( AboutDlg ) = 0 then
Dialog( 0,0,144,77, "About Listview Sample",
WS_POPUP|WS_VISIBLE|WS_CAPTION|DS_MODALFRAME or DS_SETFONT or DS_CENTER,
8,"MS Sans Serif" )
CONTROL "OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,54,51,40,14
CONTROL "Creating a Listview Control",-1,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP, 50,17,92,8
CONTROL "in OxygenBasic",-1,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,65,27,70,8
Control( "",IDI_LOGO, "STATIC", SS_ICON|SS_CENTERIMAGE, 0, 0, 40, 40 )
AboutDlg = CreateModelessDialog( hDlg, @AboutDlgProc, 0 )
end if
case IDCANCEL, IDM_EXIT
DestroyWindow( hDlg )
end select
case WM_NOTIFY
NMHDR pnm at lParam
if pnm.hwndFrom = hListview then 'ListView
select case pnm.code
case LVN_COLUMNCLICK
mbox "LVN_COLUMNCLICK"
case LVN_ITEMCHANGED
#ifdef review
printl "LVN_ITEMCHANGED"
printl
#endif
end select
end if
case WM_SIZE
RECT rcClient
// Calculate remaining height and size edit
GetClientRect(hDlg, &rcClient)
SetWindowPos(hListview, NULL, 0, rcClient.top, rcClient.right, rcClient.bottom, SWP_NOZORDER)
case WM_CLOSE
DestroyWindow( hDlg )
case WM_DESTROY
PostQuitMessage( null )
end select
return 0
end function
'====================================================================
sys hDlg
MSG wMsg
Dialog( 10,10,280,150, "Listview example",
WS_OVERLAPPEDWINDOW or DS_CENTER or WS_VISIBLE,
8,"MS Sans Serif" )
CONTROL "",IDC_LSV1,"SysListView32", _
WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER|LVS_REPORT, _
3,3,273,141,WS_EX_CLIENTEDGE
hDlg = CreateModelessDialog( 0, @DlgProc, 0 )
while GetMessage( @wMsg, null, 0, 0 ) <> 0
if IsDialogMessage( hDlg, @wMsg ) = 0 then
if IsDialogMessage( AboutDlg, @wMsg ) = 0 then
TranslateMessage( @wMsg )
DispatchMessage( @wMsg )
end if
end if
wend
Thanks Roland,
I've corrected the compiler so it will read the 'or' split expression correctly again (line 116/117 Listview.o2bas).
But I am still baffled by the GPF triggered by:
hBar = CreateWindowEx(... in Pgbar3d.inc.
Hi Charles,
that seems to be a bit tricky. I searched in the demos for apps with CreateWindowEx statement. Most of them seem to work fine. I found difficulties with:
\demos\Sound\WhoNext.o2bas - runs fine with 0.8.0 2025-02-19,
with 0.9.0 2025-04-04T 15:04 the text on labels does not work, after some time the app crashes
\demos\WinGui\BurningControl.o2bas - message that registering fails, and control does not work - neither in version 0.8.0
\demos\WinGui\Doublebuff1(2).o2bas - message that registering fails, but works nevertheless(?), same with 0.8.0
The apps work with older versions of oxygen.dll, but replacing the dll in the latest release does not work, because the structure of the include files has changed too much.
I am a little confused. After installing a new Oxygenbasic.zip version 0.8.0 2025-02-19T05:08:06 in a separate folder, I ran all the demos again in this folder with Oxide. There was no problem with any of the demos also not with the Pgbar3d(3) demos. I thought it would be sufficient to replace the oxygen.dll in the 0.9.0 folder, but this is not true.
Hi Roland,
I find that Windows is quite capable of using the wrong DLL - very confusing when switching DLL versions.
With regard to CreateWindowEx in Pgbar3d, the GPF is actually triggered in PgbWndProc.
case PGB_GETGRADIENTDIR
return 1
'return 0 'horizontal gpf
return pgb.gradientDir 'return gradient direction
But there is nothing wrong with this procedure that I can see. The gpf is avoided if I return 1. So the problem is on the outside.
I found a few problems with demos\Sound\WhoNext.o2bas, so I made some changes and rewrote the WM_TIMER section. I avoids multiple iterations of SetWindowText calls, and seems to have cleared the problem.
$ filename "Lyrics.exe"
'uses rtl32
'uses rtl64
uses WinUtil
'uses console
indexbase 1
% DS_MODALFRAME=128
% GCLP_HBRBACKGROUND= -10
% COLOR_3DFACE=15
extern lib "winmm.dll"
! mciSendString "mciSendStringA" '4
end extern
declare sub loadlyrics()
redim bstring lyrics[30]
sys lbl[5]
loadlyrics()
sys hInstance=inst
MainWindow 400,220, DS_MODALFRAME OR WS_POPUP OR WS_CAPTION OR WS_SYSMENU
function WndProc(sys hwnd, uMsg, wParam, lParam) as sys callback
int unit, x
select uMsg
case WM_CREATE
static string temp=space 256
SetWindowText(hwnd, "Tom Lehrer - Who's next")
'Adjust color of MainWindow
SetClassLongPtr(hwnd,GCLP_HBRBACKGROUND, GetSysColorBrush(COLOR_3DFACE))
char cts="static"
int sty=WS_CHILDWINDOW | WS_VISIBLE
lbl[1]=CreateWindowEx(0,cts,"",sty, 20, 30,360,25, hwnd,0,hinstance,0)
lbl[2]=CreateWindowEx(0,cts,"",sty, 20, 55,360,25, hwnd,0,hinstance,0)
lbl[3]=CreateWindowEx(0,cts,"",sty, 20, 80,360,25, hwnd,0,hinstance,0)
lbl[4]=CreateWindowEx(0,cts,"",sty, 20,105,360,25, hwnd,0,hinstance,0)
lbl[5]=CreateWindowEx(0,cts,"",sty, 20,130,360,25, hwnd,0,hinstance,0)
mciSendString("open whonext.mid type sequencer alias whonext", 0, 0, 0)
mciSendString("status whonext length", temp, 256,0)
unit=val(temp)
if unit=0 then
mbox "Cannot open whonext.mid. Sorry!"
SendMessage(hwnd, WM_CLOSE,0,0)
end if
if unit !=759 then
mbox "Wrong midi file. Sorry!"
SendMessage(hwnd, WM_CLOSE,0,0)
end if
mciSendString("play whonext", 0, 0, 0)
SetTimer(hwnd,1000,10,0)
/*
'check the position
case WM_LBUTTONDOWN
mciSendString("status whonext position", temp, 256,0)
unit=val(temp)
printl unit
*/
case WM_TIMER
'
static int m, n, cn, nn
subroutine Clear
if n<>cn
for x=1 to 5 : SetWindowText(lbl[x])="" : next
cn=n
endif
end subroutine
'
mciSendString("status whonext position", temp, 256,0)
unit=val(temp)
select unit
case >= 725 : m=4 : n=30 : KillTimer(hwnd)
case >= 705 : m=3 : n=29
case >= 692 : m=2 : n=28
case >= 682 : m=1 : n=27 : gosub clear '6'
case >= 660 : m=4 : n=26
case >= 636 : m=3 : n=25
case >= 617 : m=2 : n=24
case >= 596 : m=1 : n=23 : gosub clear '5'
case >= 572 : m=5 : n=22
case >= 532 : m=4 : n=21
case >= 510 : m=3 : n=20
case >= 489 : m=2 : n=19
case >= 461 : m=1 : n=18 : gosub clear '4b'
case >= 422 : m=2 : n=17
case >= 379 : m=1 : n=16 : gosub clear '4a'
case >= 355 : m=5 : n=15
case >= 336 : m=4 : n=14
case >= 312 : m=3 : n=13
case >= 291 : m=2 : n=12
case >= 265 : m=1 : n=11 : gosub clear '3'
case >= 245 : m=5 : n=10
case >= 228 : m=4 : n=9
case >= 205 : m=3 : n=8
case >= 185 : m=2 : n=7
case >= 165 : m=1 : n=6 : gosub clear '2'
case >= 141 : m=5 : n=5
case >= 121 : m=4 : n=4
case >= 98 : m=3 : n=3
case >= 80 : m=2 : n=2
case >= 59 : m=1 : n=1 '1'
end select
'
if n<>nn
SetWindowText(lbl[m],lyrics[n])
nn=n
endif
'
case WM_CLOSE
'Close whonext.mid file and sequencer device
mciSendString("close whonext", 0, 0, 0)
KillTimer(hwnd)
DestroyWindow(hwnd)
case WM_DESTROY
del lyrics
PostQuitMessage(0)
case else
return DefWindowProc(hwnd, uMsg, wParam, lParam)
end select
return 0
end function
'Tom Lehrer - Who's next (1965)
sub loadlyrics()
lyrics={
"First we got the bomb, and that was good,",
"'Cause we love peace and motherhood.",
"Then Russia got the bomb, but that's okay,",
"'Cause the balance of power's maintained that way.",
"Who's next?",
"Then France got the bomb, but don't you grieve,",
"'Cause they're on our side (I believe).",
"China got the bomb, but have no fears,",
"'Cause they can't wipe us out for a least five years.",
"Who's next?",
"Japan will have its own device,",
"Transistorized at half the price.",
"South Africa wants two, that's right:",
"One for the black and one for the white.",
"Who's next?",
"Egypt's gonna get one too,",
"Just to use on you-know-who.",
"So Israel's getting tense,",
"Wants one in self defense.",
"The Lord's our shepherd says the psalm,",
"But just in case, we better get a bomb.",
"Who's next?",
"Luxembourg is next to go,",
"And (who knows?) maybe Monaco.",
"We'll try to stay serene and calm",
"When Alabama gets the bomb.",
"Who's next?",
"Who's next?",
"Who's next?",
"Who's next??"
}
'countof 30
end sub
Thank you Charles for the corrections to WhoNext.o2bas. The source code looks much clearer now than before. The program runs with the last 0.8.0 and the current 0.9.0 distribution. It appears that the 0.9.0 version of Oxygen is stricter and slightly less tolerant when processing commands. I liked the flickering of the lines, it captured the attention and feigned activity. But if this causes problems, this should be avoided.
May I ask why you applied bstring for arry lyrics? Does this save memory? I always have difficulties to distinguish between string and bstring.
Bstring uses bstr olestrings directly but does not hold them in a garbage collection list. So they have to be deleted explicitly.
Strings however, point to a location in a garbage collection list, which contains the actual bstr.
In this case, the lyrics dynamic array is explicitly deleted (del) in WM_DESTROY. My implementation of del when applied to dynamic arrays, frees each element before freeing the array itself.