View Full Version : Control Listbox - why does it always crash?
ReneMiner
09-11-2012, 22:26
Yeah, why does it?
Here's my script. (has to be saved near "thinBasic_Keywords.ini" or just comment line 37 out)
it's just supposed to load a tBasic-file into sepereate lines. and just display all lines in that listbox.
(it's not the intention, later some other stuff shall be displayed in that listbox)
but just accessing the listbox (line 152) makes the program crash, if ListBox Add, Reset or whatever. No Error, nothing...
' Basic Template for custom dialog
' Start Date 11-09-2012
' Created by
Uses "UI", "FILE"
' -- ID numbers of controls
Begin ControlID
%bSelectFile
%bClose
%myList
End ControlID
Begin Const
%MAIN_WIDTH = 400
%MAIN_HEIGHT = 480
End Const
Dim sFile As String
Dim hDlg As DWord
Dim hList As DWord
Dim keyWord() As String
Dim nKeyWords As Long
Dim ScriptLine() As String
Dim nScriptLines As Long
' -- Create dialog here
Function TBMain()
ReadKeyWords
Dialog New Pixels, 0, "<Enter title here>",-1,-1, %MAIN_WIDTH, %MAIN_HEIGHT, _
%WS_POPUP Or %WS_VISIBLE Or %WS_CAPTION Or %WS_SYSMENU Or %WS_MINIMIZEBOX To hDlg
' -- Place controls here
Control Add Button, hDlg, %bSelectFile, "Select file" ,30, %Main_Height - 30, 100, 25, Call cbSelectButton
Control Add Button, hDlg, %bClose, "Close", %MAIN_WIDTH-105, %MAIN_HEIGHT-30, 100, 25, Call cbCloseButton
Control Add LISTBOX, hDlg, %myList,, 0,0 , %Main_Width, %Main_Height - 40, %WS_VSCROLL
Dialog Show Modal hDlg, Call cbDialog
End Function
' -- Callback for dialog
CallBack Function cbDialog()
' -- Test for messages
Select Case CBMSG
Case %WM_INITDIALOG
' -- Put code to be executed after dialog creation here
Case %WM_COMMAND
' -- You can handle controls here
'SELECT CASE CBCTL
'
' CASE ...
' IF CBCTLMSG = ... THEN
'
' END IF
'
'END SELECT
Case %WM_CLOSE
' -- Put code to be executed before dialog end here
End Select
End Function
' -- Callback for close button
CallBack Function cbCloseButton()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
' -- Closes the dialog
Dialog End CBHNDL
End If
End If
End Function
' -- Callback for file-select button
CallBack Function cbSelectButton()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
sFile = Dialog_OpenFile(hDlg, "Select file to check", DIR_GetCurrent, "thinBasic Files (*.tBasic, *.tBasicc)|*.tBasic;*.tBasicc", "tBasic", %OFN_FILEMUSTEXIST )
If sFile <> "" Then
If GetFile Then Spellcheck
EndIf
End If
End If
End Function
' -- Read-In all keywords
Sub ReadKeywords()
Local fNum As Long
sFile = APP_ScriptPath + "thinBasic_Keywords.ini"
If Not FILE_Exists(sFile) Then
MsgBox(0, "Keyword-file not found!", %MB_OK Or %MB_ICONERROR, "Problem:")
Dialog End CBHNDL
EndIf
fNum = FILE_Open(sFile , "INPUT" )
If fNum Then
While Not FILE_EOF(fNum)
' -- read in a line...
nKeywords += 1
ReDim Preserve KeyWord(nKeyWords)
KeyWord(nKeyWords) = FILE_LineInput(fNum)
Wend
FILE_Close(fNum)
Else
MsgBox(0, "Unable to open Keyword-file!", %MB_OK Or %MB_ICONERROR, "Problem:")
Dialog End CBHNDL
EndIf
End Sub
Function GetFile() As Long
Local fNum As Long
fNum = FILE_Open(sFile , "INPUT" )
nScriptLines = 0
If fNum Then
While Not FILE_EOF(fNum)
nScriptLines += 1
ReDim Preserve ScriptLine(nScriptLines)
ScriptLine(nScriptLines) = FILE_LineInput(fNum)
scriptLine(nScriptlines) = TrimFull$(Scriptline(nScriptlines))
LISTBOX Add hDlg, %myList, Scriptline(nScriptlines)
Wend
FILE_Close(fNum)
GetFile = TRUE
Else
MsgBox(0, "Unable to open this file!", %MB_OK Or %MB_ICONERROR, "Problem:")
GetFile = FALSE
EndIf
End Function
Sub Spellcheck()
' nothing happens yet...
End Sub
ErosOlmi
09-11-2012, 23:41
There are some problems in your script:
you cannot use automatic callback meta keywords like CBHNDL inside functions that are not callbacks
So "Dialog End CBHNDL" cannot be used inside ReadKeywords function
If you perform "Dialog End ..." you are trying to close a dialog that has never been created because ReadKeywords function is executed before dialog creation
The full ReadKeywords function can be substituted with just one line:
Parse (FILE AnyTextFile, KeyWord, $CRLF)
See help at http://www.thinbasic.com/public/products/thinBasic/help/html/index.html?parse.htm
Here your script with some tricks:
' Basic Template for custom dialog' Start Date 11-09-2012
' Created by
Uses "UI", "FILE"
' -- ID numbers of controls
Begin ControlID
%bSelectFile
%bClose
%myList
End ControlID
Begin Const
%MAIN_WIDTH = 400
%MAIN_HEIGHT = 480
End Const
Dim sFile As String
Dim hDlg As DWord
Dim hList As DWord
Dim keyWord() As String
Dim nKeyWords As Long
Dim ScriptLine() As String
Dim nScriptLines As Long
' -- Create dialog here
Function TBMain()
Dialog New Pixels, 0, "<Enter title here>",-1,-1, %MAIN_WIDTH, %MAIN_HEIGHT, _
%WS_POPUP Or %WS_VISIBLE Or %WS_CAPTION Or %WS_SYSMENU Or %WS_MINIMIZEBOX To hDlg
' -- Place controls here
Control Add Button, hDlg, %bSelectFile, "Select file" ,30, %Main_Height - 30, 100, 25, Call cbSelectButton
Control Add Button, hDlg, %bClose, "Close", %MAIN_WIDTH-105, %MAIN_HEIGHT-30, 100, 25, Call cbCloseButton
Control Add LISTBOX, hDlg, %myList,, 0,0 , %Main_Width, %Main_Height - 40, %WS_VSCROLL
Dialog Show Modal hDlg, Call cbDialog
End Function
' -- Callback for dialog
CallBack Function cbDialog()
' -- Test for messages
Select Case CBMSG
Case %WM_INITDIALOG
' -- Put code to be executed after dialog creation here
ReadKeyWords
Case %WM_COMMAND
' -- You can handle controls here
'SELECT CASE CBCTL
'
' CASE ...
' IF CBCTLMSG = ... THEN
'
' END IF
'
'END SELECT
Case %WM_CLOSE
' -- Put code to be executed before dialog end here
End Select
End Function
' -- Callback for close button
CallBack Function cbCloseButton()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
' -- Closes the dialog
Dialog End CBHNDL
End If
End If
End Function
' -- Callback for file-select button
CallBack Function cbSelectButton()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
sFile = Dialog_OpenFile(hDlg, "Select file to check", DIR_GetCurrent, "thinBasic Files (*.tBasic, *.tBasicc)|*.tBasic;*.tBasicc", "tBasic", %OFN_FILEMUSTEXIST )
If sFile <> "" Then
If GetFile(sFile) Then Spellcheck
EndIf
End If
End If
End Function
' -- Read-In all keywords
Sub ReadKeywords()
'---With just one line it loads into an array all lines of a file
Parse (File APP_ScriptFullName , KeyWord, $CRLF )
'---With just one line loads an array of items into a listbox
LISTBOX Add hDlg, %myList, Join$(KeyWord, $NUL) Using $NUL
End Sub
Function GetFile(ByVal sFile As String) As Long
'---With just one line it loads into an array all lines of a file
Parse (File sFile, ScriptLine, $CRLF )
'---With just one line loads an array of items into a listbox
LISTBOX Add hDlg, %myList, Join$(Scriptline, $NUL) Using $NUL
End Function
Sub Spellcheck()
' nothing happens yet...
End Sub
ReneMiner
10-11-2012, 00:15
it does not read the keywords from the ini-file that way. So I used my old function. Now please explain it to me:
WHY DOES IT CRASH?
It's the function you wrote. It works if I take all your stuff, but does not read the keywords right then.
and if I do it that way, it crashes when selecting a file. What is wrong?
Uses "UI", "FILE"
' -- ID numbers of controls
Begin ControlID
%bSelectFile
%bClose
%myList
End ControlID
Begin Const
%MAIN_WIDTH = 400
%MAIN_HEIGHT = 480
End Const
Dim sFile As String
Dim hDlg As DWord
Dim keyWord() As String
Dim nKeyWords As Long
Dim ScriptLine() As String
Dim nScriptLines As Long
' -- Create dialog here
Function TBMain()
Dialog New Pixels, 0, "<Enter title here>",-1,-1, %MAIN_WIDTH, %MAIN_HEIGHT, _
%WS_POPUP Or %WS_VISIBLE Or %WS_CAPTION Or %WS_SYSMENU Or %WS_MINIMIZEBOX To hDlg
' -- Place controls here
Control Add Button, hDlg, %bSelectFile, "Select file" ,30, %Main_Height - 30, 100, 25, Call cbSelectButton
Control Add Button, hDlg, %bClose, "Close", %MAIN_WIDTH-105, %MAIN_HEIGHT-30, 100, 25, Call cbCloseButton
Control Add LISTBOX, hDlg, %myList,, 0,0 , %Main_Width, %Main_Height - 40, %WS_VSCROLL
Dialog Show Modal hDlg, Call cbDialog
End Function
' -- Callback for dialog
CallBack Function cbDialog()
' -- Test for messages
Select Case CBMSG
Case %WM_INITDIALOG
' -- Put code to be executed after dialog creation here
If Not ReadKeyWords Then Dialog End CBHNDL
Case %WM_COMMAND
' -- You can handle controls here
'SELECT CASE CBCTL
'
' CASE ...
' IF CBCTLMSG = ... THEN
'
' END IF
'
'END SELECT
Case %WM_CLOSE
' -- Put code to be executed before dialog end here
End Select
End Function
' -- Callback for close button
CallBack Function cbCloseButton()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
' -- Closes the dialog
Dialog End CBHNDL
End If
End If
End Function
' -- Callback for file-select button
CallBack Function cbSelectButton()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
sFile = Dialog_OpenFile(hDlg, "Select file to check", _
DIR_GetCurrent, "thinBasic Files (*.tBasic, *.tBasicc)|*.tBasic;*.tBasicc", "tBasic", _
%OFN_FILEMUSTEXIST )
If sFile <> "" Then
If GetFile(sFile) Then Spellcheck
EndIf
End If
End If
End Function
' -- Read-In all keywords
Function ReadKeywords() As Long
Local fNum As Long
sFile = APP_ScriptPath + "thinBasic_Keywords.ini"
If Not FILE_Exists(sFile) Then
MsgBox(0, "Keyword-file not found!", _
%MB_OK Or %MB_ICONERROR, "Problem:")
Return FALSE
EndIf
fNum = FILE_Open(sFile , "INPUT" )
If fNum Then
While Not FILE_EOF(fNum)
' -- read in a line...
nKeywords += 1
ReDim Preserve KeyWord(nKeyWords)
KeyWord(nKeyWords) = FILE_LineInput(fNum)
Wend
FILE_Close(fNum)
'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<at this line it works<<<<<<<<<<<<<<<
LISTBOX Add hDlg, %myList, Join$(KeyWord, $NUL) Using $NUL
Else
MsgBox(0, "Unable to open Keyword-file!", _
%MB_OK Or %MB_ICONERROR, "Problem:")
Return FALSE
EndIf
Return TRUE
End Sub
Function GetFile(ByVal sFile As String) As Long
'---With just one line it loads into an array all lines of a file
Parse (File sFile, ScriptLine, $CRLF )
'---With just one line loads an array of items into a listbox
' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CRASH HERE, WHY?<<<<<<<<<<<<<<<<<
LISTBOX Add hDlg, %myList, Join$(Scriptline, $NUL) Using $NUL
End Function
Sub Spellcheck()
' nothing happens yet...
End Sub
It does not crash if I use a textbox instead of a listbox. And I won't append the scriptline array so does Add also replace? I thought of using Reset, but that crashes also.
ErosOlmi
10-11-2012, 00:25
Here your code is working fine.
ReneMiner
10-11-2012, 00:29
It does???? :suicide: not here... it crashes instantly when Listbox gets accessed. No Message - no Error-Description, just whoops-dialog gone... I can not run it. But I would like to use the listbox... so I've to find something else...best would be a new computer...
ErosOlmi
10-11-2012, 00:48
Attached my execution of your last script example.
Maybe others can give a try and confirm
Michael Clease
10-11-2012, 01:54
Works fine on my Laptop.
I did add the following line for ease of testing.
FILE_Save(sFile,APP_ListKeywords($CRLF) )
ReneMiner
10-11-2012, 01:56
no, that's not it. It loads the keywords by itself first (i have a copy of that ini in my script-path) to have them in memory, and when i click on "select file", a tb-file gets chosen that shall be spellchecked. but that is secondary:
when the listbox gets accessed by WRITING NEW STUFF IN it crashes
just the "ListBox Add", or "Reset" or whatever makes it crash. It woorks fine when I use textbox, so I damned the listbox deep behind and gonna delete it from my help-file cause i cannot use it.
Michael Clease
10-11-2012, 02:15
no, that's not it. It loads the keywords by itself first (i have a copy of that ini in my script-path) to have them in memory
But I dont so I took the simple approach :|
Whats this ?
Parse (File sFile, ScriptLine, $CRLF )
ReneMiner
10-11-2012, 02:23
I took this function from Eros' script above... but it's the same as described in help
the ini you find in
C:\thinBasic\thinAir\Syntax\thinBasic
copy it besides the scripts location, run, it should display all keywords,
then click select file, and select any basic file then... :skull:
Edit: Spellchecker replaced, pretty fast now, but still some problem with string-comparison - does not always find matching strings, mostly Subs & Functions names & constants, I don't know how comes, running it on itself results 3 words that are twice - I'm at loss... :confused:
ErosOlmi
10-11-2012, 15:17
Rene,
I was able to replicate the problem you are facing with LIST ADD ...
I tested under my Windows XP virtual machine and effectively under XP LIST ADD ... function fails when used with arrays.
I'm trying to understand why under Windows 7 or 8 all is OK and under XP not
Eros
ErosOlmi
10-11-2012, 15:55
Rene,
please try to remove the very last carriage return/line feed char (CRLF) from the file "thinBasic_Keywords.ini" so the file ends without any blank line
Let me know if it makes any difference
Eros
ReneMiner
10-11-2012, 16:22
dont't know if I did it right,
I use script, postet at 23:15
added this below line 127:
If Len(Keyword(nKeywords)) < 2 Then
nKeywords -= 1
ReDim Preserve Keyword(nKeywords)
Else
keyword(nKeywords) = LEFT$(keyword(nKeywords),Len(keyword(nKeywords))-1)
EndIf
' here comes first Listbox add now
same result. Crash on loading second list - But does that what I wrote truncate the crlf?
Second try: I erased last (empty) line of the ini-file. Still crashes on "Select file"
Query-checked with Hex-Editor:
last Char of ini-file = &H45 "E"
last char of Testbasicfile = &H62 "b"
btw. It does not just fail with complete Arrays, see my first script where I put that all in one by one.
It not fails with an empty RESET - but if I try to replace the list- whoops- program gone.
It Does not crash if i do at end of sub Getfile() this:
LISTBOX Reset hDlg, %myList
LISTBOX Add hDlG, %myList, Join$(Scriptline, $CRLF) Using $NUL
but it shows all on one line with some unusable chars,
it could be something with that $Nul in Join$, I can replace $Nul in Join$() with almost anything, $CR, $LF, $CRLF, $TAB, $VT, even strings like "hello" or Chr$(32) - except CHR$(0)!!! - without any crash. but writes all in first line of listbox then. that's not my intention.
if I omit Join and just pass the array-name it crashes too
I'm through with testing: only crashes if Join$(sString, EvilParameter = CHR$(0) )...which is probably the default if omitted...
Chr$(1) to Chr$(255) - no crash!
:idea: Another try, this is the whole GetFile-Function:
Function GetFile(ByVal sFile As String) As Long
Local i As Long
Parse (File sFile, ScriptLine, $CRLF )
LISTBOX Reset hDlg, %myList
If UBound(Scriptline) > 0 Then
For i = 1 To UBound(Scriptline)
LISTBOX Add hDlg, %myList, Scriptline(i) + " " Using $NUL
Next i
EndIf
End Function
this works at least that far that all Scriptlines are on single list-rows,
no crash, just one space added to the elements!
works even if "Using $NUL" omitted
ErosOlmi
10-11-2012, 19:17
OK for the GPF under XP I need to work a little bit.
Instead shange to just
LISTBOX AddhDlg, %myList, Scriptline(i)
without USING clause. USING clause is when you have a string that you want to split into multiple elements inside a list box.
To speed up your script you need to avoid loops and MID$ as much as possible because they are time consuming.
So change is_Keyword function into something like the following in order to greatly speed up searching inside arrays:
Function is_Keyword(ByVal aString As String) As Long
Local lResult As Long
lResult = Array Scan Keyword(), Collate Ucase, = aString
If lResult Then Function = %TRUE
End Function
Than change is_Numeral_or_Empty function into the following in order to avoid char checking and use VERIFY function
Function is_Numeral_or_Empty(ByVal aString As String) As Long
' find out if aString contains just numerals
Local lStart As Long
If Len(aString) = 0 Then
Return TRUE
ElseIf Len(aString) > 2 Then
If LEFT$(aString, 2) ="&H" Or LEFT$(aString, 2) = "&h" Then
lStart = 3
Else
lStart = 1
EndIf
Else
lStart = 1
EndIf
If Verify(lStart, aString, "01234567890.") = 0 Then
Function = %TRUE
End If
End Function
In general thinBasic has a HUGE number of functions already built in.
If you like, you can improve your parsing speed using dictionaries and tokenizer module.
Ciao
Eros
ReneMiner
10-11-2012, 20:04
...
In general thinBasic has a HUGE number of functions already built in.
If you like, you can improve your parsing speed using dictionaries and tokenizer module.
Ciao
Eros
I appreciate your tips 'n tricks, the thing is, I would use such functions if I would know that they exist and what they do.
Array Scan, Collate, nice but I am already happy if i stumble across some keyword that I'm looking for. I never made it to find an AscII-Table in the help, so I do boo-boo-crime and start purebasic just to check that help which is quite well organized and clearly arranged.(purebasic-language is as long not as good as thinBasic, there are universes between) but in that help I find everything I'm looking for in less than one minute, vb6.0-help is even faster, there I find all I look for within a few seconds and real good information, that leaves no open questions - but vb-help needs longer to load than purebasic-help.
thinBasic-help, I sit in front of for hours, read lots - but don't find what I'm looking for, except I remind me reading it somewhere - than I just have to find that paragraph again, which isn't quite easy.
So in the meantime I already hate to search something in help-file - i just look for syntax there.
If I have to read and understand the whole help before I try to program something I'll never get started. And in case I don't know that a function like Array Scan exists, I do it the old-fashioned way like we did in the 80s and 90s of last century ;)
PS. I made a bug, function has to be that way
Function is_Numeral_or_Empty(ByVal aString As String) As Long
If Len(aString) = 0 Then
Return TRUE
ElseIf Len(aString) > 2 Then
If LEFT$(aString, 2) ="&H" Or LEFT$(aString, 2) = "&h" Then
If Verify(3, aString, "01234567890.ABCDEF") = 0 Then Return %TRUE
Else
If Verify(1, aString, "01234567890.") = 0 Then Return %TRUE
EndIf
Else
If Verify(1, aString, "01234567890.") = 0 Then Return %TRUE
EndIf
End Function
so I replaced the script (1 page back). There's still something wrong with comparing strings... some that are twice get presented as if they occur once...