PDA

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...