Folks,
I finally bit the bullet and converted one of my larger, data-intensive, applications from FF/PB to PureBasic. It was bit of an adventure and learning curve.
The forms designer with PureBasic is pretty basic and don't try to put any additional code within the generated form code as it will be deleted when you compile the code!
The variable typing is a pain "Dim abc As Long" becomes "Define abc.l"
Procedures have to appear before the main code or be declared above the main code or you will get syntax errors.
The Structure notation is a bit different in that you use a "\" instead of "." to select the component with the structure.
Strings within the structures do not have to be pre-sized (a good thing!).
I really liked the integrated debugger which works quite well.
I basically cut and pasted my code from FF/PB and edited to meet the new syntax and order.
The result was a slightly larger executable 179 KB versus 161 KB but there was no need to provide any additional library files (just the executable).
In terms of performance, the new code ran 175% faster than the FF/PB code.
The code involved loading a large flat file (500 MB), doing 4 quick sorts on it and then outputting it into a smaller set of 79 output files based upon the sort criteria and some other flags found within the data.
There is a free book called "Purebasic - A Beginner's Guide to Computer Programming" by Gary Willoughby that I found very helpful (http://www.purearea.net/pb/download/PureBasicBook.pdf).
/Dave
Hi David,
Thanks for sharing your PureBasic experience :)
I have not used PureBasic. I think that I feel comfortable enough now with FreeBasic that I will stick with that language. I know many PowerBasic'ers who have switched to PureBasic and I think they are enjoying the experience.
I'm fascinated using PureBasic...It has many benefits ... and is cross platform.
To handle images (PNG, JPG etc.), using database SQLITE 3. It's a beauty.
It would be great to have a version of FireFly for PureBasic.
This code is for make a application:
XIncludeFile "C:\PUREBASIC5\CSGRID\CSGRID.pbi"
XIncludeFile "MENU.pbf"
IncludeFile "C:\PUREBASIC5\buttonscool\buttonscool.pbi"
;Agrega Control Grid
WindowID = #Window_0 ; NEW !!! - This must be defined for CS-Grid, as it can now be on several windows.
UsePNGImageDecoder()
OpenWindow_0()
;If #Window_0
; MessageRequester("dd","EEE",0)
UseGadgetList(WindowID(WindowID))
TEST = CSGridGadget(#PB_Any,10,10,620,200,10,100) ; Creates a CS-Grid-Gadget
;MessageRequester("DDD",Str(TEST),0)
CSGridGadget_SetAutoRedraw(TEST,1) ; Turns off Auto-Redraw for Grid 1 for faster setup
CSGridGadget_SetColCaptionVisibility(TEST,0) ; Shows a column header (default empty caption)
CSGridGadget_SetColCaptionVisibility(TEST,0) ; Shows a column header (default empty caption)
CSGridGadget_SetColCaption(TEST,0,"String") ; Defines custom header Labels for all Columns
CSGridGadget_SetColCaption(TEST,1,"Long") ; Defines custom header Labels for all Columns
CSGridGadget_SetColCaption(TEST,2,"Float") ; Defines custom header Labels for all Columns
CSGridGadget_SetColCaption(TEST,3,"Formatted") ; Defines custom header Labels for all Columns
CSGridGadget_SetColCaption(TEST,4,"Percentage") ; Defines custom header Labels for all Columns
CSGridGadget_SetColCaption(TEST,5,"US Dollars") ; Defines custom header Labels for all Columns
CSGridGadget_SetColCaption(TEST,6,"User Fmt") ; Defines custom header Labels for all Columns
CSGridGadget_SetRowCaptionVisibility(TEST,1) ; Shows a row header (default numbered caption)
CSGridGadget_SetColWidth(TEST,2,100) ; Defines Column-Width for Column 2
CSGridGadget_SetColWidth(TEST,3,100) ; Defines Column-Width for Column 3
CSGridGadget_SetColWidth(TEST,5,100) ; Defines Column-Width for Column 5
CSGridGadget_SetColWidth(TEST,6,100) ; Defines Column-Width for Column 6
CSGridGadget_SetColDataType(TEST,0,0) ; Defines Output-Type to Text for Column 0
CSGridGadget_SetCellValue(TEST,0,0,"testING") ; Defines new Content for Cell C:0 R:0
CSGridGadget_SetColInputType(TEST,0,32) ; Defines Input via Rollup (values-list) for Column 0
CSGridGadget_SetColInputRessource(TEST,0,"Input 1"+Chr(13)+Chr(10)+"Input 2"+Chr(13)+Chr(10)+"Input 3") ; Defines a values list with 3 values (separated with CHR(13)+CHR(10)) for Column 0
CSGridGadget_SetColDataType(TEST,1,1) ; Defines Output-Type to Long Integer for Column 1
CSGridGadget_SetCellValue(TEST,1,0,"654924") ; Defines new Content for Cell C:1 R:0
CSGridGadget_SetColDataType(TEST,2,16) ; Defines Output-Type to Float for Column 2
CSGridGadget_SetCellValue(TEST,2,0,"139.6548") ; Defines new Content for Cell C:2 R:0
CSGridGadget_SetColSummary(TEST,2,1) ; Defines Column-Summary
CSGridGadget_SetColDataType(TEST,3,17) ; Defines Output-Type to Formatted Fload, 2 decimals places
CSGridGadget_SetCellValue(TEST,3,0,"1221.105") ; Defines new Content for Cell C:3 R:0
CSGridGadget_SetColDataType(TEST,4,64) ; Defines Output-Type to Percentage, 4 decimals places
CSGridGadget_SetCellValue(TEST,4,0,"0.456789") ; Defines new Content for Cell C:3 R:0
CSGridGadget_SetFormatComma(TEST,".") ; Enables support for US/UK-style comma-symbol
CSGridGadget_SetColDataType(TEST,5,33) ; Defines Output-Type to US Dollars, 2 decimals places
CSGridGadget_SetCellValue(TEST,5,0,"150286") ; Defines new Content for Cell C:3 R:0
CSGridGadget_SetColDataType(TEST,6,127) ; User defined Output-Type
CSGridGadget_SetColUserNumberFormat(TEST,6,"#######0.00") ; Defines User-Output-Type for Column 3
CSGridGadget_SetCellValue(TEST,6,0,"1502.86") ; Defines new Content for Cell C:3 R:0
CSGridGadget_SetColDataType(TEST,7,2) ; Boolean
; CSGridGadget_SetCellLockStatus(TEST,7,2,-16) ; Locks Cell C:2 R:2 for access (and input)
CSGridGadget_SetCellValue(TEST,2,1,"No Access") ; Defines new Content for Cell C:2 R:1
; CSGridGadget_SetCellLockStatus(TEST,2,2,-16) ; Locks Cell C:2 R:2 for access (and input)
CSGridGadget_SetCellValue(TEST,3,3,"No Edit") ; Defines new Content for Cell C:3 R:3
;CSGridGadget_SetCellLockStatus(TEST,3,3,-1) ; Locks Cell C:3 R:3 for input
CSGridGadget_SetColsUserSort(TEST,1) ; Activates user sorting via double-click on column headder
CSGridGadget_SetAutoRedraw(TEST,1) ; Turns on Auto-Redraw for Grid 1 for faster setup
CSGridGadget_SetColCaptionVisibility(TEST,1) ; Shows a column header (default empty caption)
;EndIf
SetGadgetText(text_0,"VALOR:")
If Not(is_jelly_button(BTN_IMG_ACTUALIZARCATALOGO))
Add_Some_Jelly(BTN_IMG_ACTUALIZARCATALOGO, 10)
set_jelly_text_color(BTN_IMG_ACTUALIZARCATALOGO, #Blue)
set_jelly_shadow_color(BTN_IMG_ACTUALIZARCATALOGO, #Green )
Spread_Jelly(BTN_IMG_ACTUALIZARCATALOGO, RGB(255,155,255))
EndIf
If Not(is_jelly_button(TEXT_0))
Add_Some_Jelly(TEXT_0,100)
set_jelly_text_color(TEXT_0, #Blue)
set_jelly_shadow_color(TEXT_0, -2)
Spread_Jelly(TEXT_0, -2)
EndIf
If Not(is_jelly_button(ButtonIMAGE_1))
Add_Some_Jelly(ButtonIMAGE_1, 10)
set_jelly_text_color(ButtonIMAGE_1, #Blue)
set_jelly_shadow_color(ButtonIMAGE_1, #Green )
Spread_Jelly(ButtonIMAGE_1, RGB(0,155,255))
EndIf
If Not(is_jelly_button(BTN_IMG_SALIR))
Add_Some_Jelly(BTN_IMG_SALIR, 10)
set_jelly_text_color(BTN_IMG_SALIR, #Red)
set_jelly_shadow_color(BTN_IMG_SALIR, #Black)
Spread_Jelly(BTN_IMG_SALIR, RGB(100,155,255))
EndIf
Repeat
Event = WaitWindowEvent()
CSGridGadget_EventHandling(Event); Processes all Grid-Gadget events (for all CS-Grid-Gadgets)
Window_0_Events(Event) ; This procedure name is always window name followed by '_Events'
Select Event
Case #Window_0
;Window_0_Events(Event) ; This procedure name is always window name followed by '_Events'
Case #PB_Event_Gadget
Select EventGadget()
Case Window_0
Select EventType()
Case #PB_EventType_LeftClick : Debug "Click with left mouse button"
Case #PB_EventType_RightClick : Debug "Click with right mouse button"
Case #PB_EventType_LeftDoubleClick : Debug "Double-click with left mouse button"
Case #PB_EventType_RightDoubleClick : Debug "Double-click with right mouse button"
EndSelect
Case TEST
Select EventType()
Case #PB_EventType_LeftClick : Debug "Click with left mouse button"
Case #PB_EventType_RightClick : Debug "Click with right mouse button"
Case #PB_EventType_LeftDoubleClick : Debug "Double-click with left mouse button"
Case #PB_EventType_RightDoubleClick : Debug "Double-click with right mouse button"
EndSelect
Case BTN_IMG_ACTUALIZARCATALOGO
Select EventType()
Case #PB_EventType_LeftClick : Debug "Click with left mouse button"
Case #PB_EventType_RightClick : Debug "Click with right mouse button"
Case #PB_EventType_LeftDoubleClick : Debug "Double-click with left mouse button"
Case #PB_EventType_RightDoubleClick : Debug "Double-click with right mouse button"
EndSelect
Case BTN_IMG_SALIR
Select EventType()
Case #PB_EventType_LeftClick : Break ;Debug "Click with left mouse button"
Case #PB_EventType_RightClick : Debug "Click with right mouse button"
Case #PB_EventType_LeftDoubleClick : Debug "Double-click with left mouse button"
Case #PB_EventType_RightDoubleClick : Debug "Double-click with right mouse button"
EndSelect
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow ; Quit on any window close
CSGridGadget_FreeGadget(TEST)
This code is for use SQLITE 3
UseSQLiteDatabase()
Procedure CheckDatabaseUpdate(Database, Query$)
Result = DatabaseUpdate(Database, Query$)
If Result = 0
Debug DatabaseError()
EndIf
ProcedureReturn Result
EndProcedure
DatabaseFile$ = GetCurrentDirectory()+"TARCAL.DAT"
If CreateFile(0, DatabaseFile$)
CloseFile(0)
If OpenDatabase(0, DatabaseFile$, "", "")
CheckDatabaseUpdate(0, "CREATE TABLE TARJETAS(CODIGO VARCHAR(10),NOMBRE VARCHAR(80),FECHAREC CHAR(10),FECHAENT CHAR(10))")
For X=1 To 100000
CheckDatabaseUpdate(0, "INSERT INTO TARJETAS(CODIGO, NOMBRE, FECHAREC, FECHAENT) VALUES ('"+Str(X)+"', 'NOMBRE"+Str(X)+"','2015-01-01','2015-01-02')")
Next X
If DatabaseQuery(0, "SELECT * FROM TARJETAS")
;FirstDatabaseRow(0)
While NextDatabaseRow(0)
Debug GetDatabaseString(0, 1)
Wend
FinishDatabaseQuery(0)
EndIf
CloseDatabase(0)
Else
Debug "Can't open database !"
EndIf
Else
Debug "Can't create the database file !"
EndIf
And for open a database of MS Access with this simple code:
EnableExplicit
#ODBC_ADD_DSN = 1
#ODBC_CONFIG_DSN = 2
#ODBC_REMOVE_DSN = 3
#ODBC_ADD_SYS_DSN = 4
#ODBC_CONFIG_SYS_DSN = 5
#ODBC_REMOVE_SYS_DSN = 6
#ODBC_REMOVE_DEFAULT_DSN = 7
Procedure AddConnection(Driver$,ConnectString$)
ProcedureReturn SQLConfigDataSource_(0,#ODBC_ADD_DSN,Driver$,ConnectString$)
EndProcedure
Procedure RemoveConnection(Driver$,DSN$)
ProcedureReturn SQLConfigDataSource_(0,#ODBC_REMOVE_DSN,Driver$,"DSN=" + DSN$)
EndProcedure
UseODBCDatabase()
Define Result
Define DSN$ = "MYACCESSDB"
Define Database$ = "C:\RADBUILDER\APFONACOT\APFONACOT.mdb" ; folder+name of your Access file
Define UserID$ = ""
Define Password$ = ""
Define Table$ = "CEDULA"
Define Column$ = "NOMBRE"
Result = AddConnection("Microsoft Access Driver (*.mdb, *.accdb)","Server=127.0.0.1;Description=My ODBC Access;DSN=" + DSN$ + ";DBQ=" + Database$ + ";UID=" + UserID$ + ";PWD=" + Password$ + ";")
If Result
Result = OpenDatabase(0,DSN$,"","")
If Result
If DatabaseQuery(0,"SELECT " + Column$ + " FROM " + Table$)
While NextDatabaseRow(0)
Debug GetDatabaseString(0, 0)
Wend
FinishDatabaseQuery(0)
EndIf
CloseDatabase(0)
EndIf
EndIf
RemoveConnection("Microsoft Access Driver (*.mdb, *.accdb)",DSN$)
PureBasic is very good...but It does not have a good visual designer how Firefly.
SQLConfigDataSource is not something privative to PureBasic. It is an API function of the ODBC driver that you can call with any compiler.
Yes, that's true Jose, but the nice thing is that this is a "complete" compile-able example with no 'Include' file necessary.
PureBasic has built-in the Win API definitions... so all you have to do is add an '_' after
the actual API command (SQLConfigDataSource_) in order to use it... becoming an ordinary PureBasic command.
Bottom line is that you can do a lot more without all the verbose typing in other languages.
I find that a big plus, and... the code becomes very readable because of this. :)
What about his?
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "CODBC.INC"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
' // Create an instance of the class
LOCAL pOdbc AS IOdbc
pOdbc = NewOdbc(%SQL_OV_ODBC3_80)
IF ISNOTHING(pOdbc) THEN EXIT FUNCTION
TRY
' // Create a connection object
LOCAL pCon AS IOdbcConnection
pCon = pOdbc.Connection("Connection1")
' // Open the database
pCon.OpenDatabase("DRIVER={Microsoft Access Driver (*.mdb)};DBQ=biblio.mdb;UID=;PWD=;")
' // Allocate an statement object
LOCAL pStmt AS IOdbcStatement
pStmt = pCon.Statement("Statement1")
' // Cursor type
pStmt.SetMultiuserKeysetCursor
' // Generate a result set
pStmt.ExecDirect ("SELECT TOP 20 * FROM Authors ORDER BY Author")
' // Parse the result set
LOCAL strOutput AS STRING
DO
' // Fetch the record
IF ISFALSE pStmt.Fetch THEN EXIT DO
' // Get the values of the columns and display them
strOutput = ""
strOutput += pStmt.GetDataString(1) & " "
strOutput += pStmt.GetDataString(2) & " "
strOutput += pStmt.GetDataString(3)
? strOutput
' // Note: Instead of retrieving the data by ordinal,
' // you can also do it by column name.
' strOutput = ""
' strOutput += pStmt.GetDataString("Au_ID") & " "
' strOutput += pStmt.GetDataString("Author") & " "
' strOutput += pStmt.GetDataString("Year Born")
' ? strOutput
LOOP
CATCH
' // Display error information
? OdbcOleErrorInfo(OBJRESULT)
END TRY
' // Destroy the class
pOdbc = NOTHING
#IF %DEF(%PB_CC32)
WAITKEY$
#ENDIF
END FUNCTION
' ========================================================================================
Or this?
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "CSQLite.INC"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
' // Create an instance of the class
LOCAL pSQL AS ISQLite
pSQL = CLASS "CSQLite"
IF ISNOTHING(pSQL) THEN EXIT FUNCTION
' // Create a connection object
LOCAL pDbc AS ISQLiteConnection
pDbc = pSQL.Connection
IF ISNOTHING(pDbc) THEN EXIT FUNCTION
TRY
' // Delete our test database if it exists
IF ISFILE(EXE.PATH$ & "Test.sdb") THEN KILL EXE.PATH$ & "Test.sdb"
' // Create a new database
pDbc.OpenDatabase(EXE.PATH$ & "Test.sdb")
' // Create a table
pDbc.Exec("CREATE TABLE t (xyz text)")
' // Insert rows
pDbc.Exec("INSERT INTO t (xyz) VALUES ('fruit')")
pDbc.Exec("INSERT INTO t (xyz) VALUES ('fish')")
' ' // Prepare a query
LOCAL pStmt AS ISQLiteStatement
pStmt = pDbc.Prepare("SELECT * FROM t")
? "Column count:" & STR$(pStmt.ColumnCount)
' // Read the column names and values
LOCAL i AS LONG
DO
' // Fetch rows of the result set
IF pStmt.Step = %SQLITE_DONE THEN EXIT DO
' // Read the columns and values
FOR i = 0 TO pStmt.ColumnCount- 1
? pStmt.ColumnName(i)
' ? pStmt.ColumnText(i)
? pStmt.ColumnText("xyz")
NEXT
LOOP
CATCH
' // Display error information
? pSql.OleErrorInfo
END TRY
' // Cleanup
pStmt = NOTHING ' // Deletes the prepared statement
pDbc = NOTHING ' // Closes the database
pSQL = NOTHING
#IF %DEF(%PB_CC32)
WAITKEY$
#ENDIF
END FUNCTION
' ========================================================================================
PowerBASIC es great and I love this compiler and I would like to continue using PowerBASIC, but I believe that no more updates...no 64 bits.
PowerBASIC not have built-in Database or Images...but thanks to your great working (Jose Roca Includes) we can do a wide thinks how ADO, SQLite, GDI...).
By example in PureBasic with this code (built-in) I can set background a form:
UseJPEGImageDecoder()
DataSection
Img_fondo:
IncludeBinary "FONDO.JPG"
EndDataSection
IMAGEN_FONDO = CatchImage(#PB_Any, ?img_fondo)
SetBackgroundImage(#window_0, IMAGEN_FONDO)