Hello all. As you can guess I am new to this combination and have hit a very basic snag.
I am just trying to implement some FLTK widgets into a FF FB project. I can understand that getting non native widgets to appear in the visual designer would be close to impossible but I cannot get them to even appear in the final exe.
This is just a straight forward FLTK project and works fine. Compiles, runs, the works. Doesnt do much but is a POC
#Include "fltk-c.bi"
#Include "string.bi"
Type flStruct
flClass as String '
flRight as Integer ' Widget X
flTop as Integer ' Widget Y
flWidth as Integer ' Widget Width
flHeight as Integer ' Widget Height
flLabel as String ' Widget Label
End Type
Dim Shared flDial1 as flStruct
flDial1.flClass = "Fl_Dial"
flDial1.flRight = 10
flDial1.flTop = 160
flDial1.flWidth = 20
flDial1.flHeight = 20
flDial1.flLabel = "1"
'Windows and widgets:
Dim Shared as Fl_Window Ptr Window_Main
Dim Shared as Fl_Menu_Bar Ptr Menu
Dim Shared as Fl_Box Ptr Box_text
Dim Shared as Fl_Output Ptr Output_text
Dim Shared as Fl_Dial Ptr Dial1
Dim Shared as Fl_Dial Ptr Dial2
Dim Shared as Fl_Dial Ptr Dial3
Dim Shared as Fl_Button Ptr Button1_Click
Dim Shared as Fl_Button Ptr Button2_Click
Sub Create_Window_Main ()
'Window with button and Stuff:
Window_Main = Fl_WindowNew (400, 200, "Button Test")
Menu = Fl_Menu_BarNew (0, 0, 400, 20)
Fl_Menu_Add (Menu, "File/New" ,,@flNewFile())
Fl_Menu_Add (Menu, "File/Open" ,, @flOpenFile())
Fl_Menu_Add (Menu, "File/Save" ,, @flSaveFile())
Fl_Menu_Add (Menu, "File/Exit" ,, @flEndProgram())
Fl_Menu_Add (Menu, "Edit" ,, @flDefault())
Fl_Menu_Add (Menu, "Search" ,, @flDefault())
Fl_Menu_Add (Menu, "View" ,, @flDefault())
Fl_Menu_Add (Menu, "Tools" ,, @flDefault())
Fl_Menu_Add (Menu, "Help/Info" ,, @flInfo())
Box_text = Fl_BoxNew(150, 50, 100, 20, "Welcome to FLTK! with FreeBasic")
Output_text = Fl_OutputNew (20, 140, 60, 20, "")
Dial1 = Fl_DialNew (flDial1.flRight, flDial1.flTop, flDial1.flWidth, flDial1.flHeight, flDial1.flLabel)
Dial2 = Fl_DialNew (flDial1.flRight+30, flDial1.flTop, flDial1.flWidth, flDial1.flHeight, "2")
Dial3 = Fl_DialNew (flDial1.flRight+60, flDial1.flTop, flDial1.flWidth, flDial1.flHeight, "3")
Fl_DialAngles(Dial1, 10, 350)
Fl_DialAngles(Dial2, 10, 350)
Fl_DialAngles(Dial3, 10, 350)
Button1_Click = Fl_ButtonNew (160, 160, 100, 20, "Click me!")
Button2_Click = Fl_ButtonNew (280, 160, 100, 20, "Not me!")
End Sub
'Menu Callback functions:
Sub flNewFile CDecl (widget as Fl_Widget Ptr, userData as Any Ptr)
flMessageBox ("File Menu", "New file")
End Sub
Sub flOpenFile CDecl (widget as Fl_Widget Ptr, userData as Any Ptr)
'Select a file to open:
Dim as ZString Ptr file
file = flFileChooser ("Open file", "*.bas" + Chr(9) + "*.txt", Exepath(), 1)
If file <> 0 Then flMessageBox ("Selected file:", file)
End Sub
Sub flSaveFile CDecl (widget as Fl_Widget Ptr, userData as Any Ptr)
' Just some silly crap for testing
Dim s as String
s = *flInput ("Enter your name:", "Who are you?")
If s <> "" Then flMessageBox ("Save file", "Hello " + s)
End Sub
Sub flEndProgram CDecl (widget as Fl_Widget Ptr, userData as Any Ptr)
End
End Sub
Sub flInfo CDecl (widget as Fl_Widget Ptr, userData as Any Ptr)
'Show Info:
flMessageBox ("Help Menu", "Application Info")
End Sub
Sub flDefault CDecl (widget as Fl_Widget Ptr, userData as Any Ptr)
'Show Info:
flMessageBox ("Other Menu's", "Not yet implemented")
End Sub
'Callback functions for the Buttons and Dials
Sub Button1_Click_Event CDecl (widget as FL_Widget Ptr)
Print "Button1 was clicked!"
'Show Info:
Fl_ValuatorSetValue(Dial1, 0.5)
Fl_ValuatorSetValue(Dial2, 0.5)
Fl_ValuatorSetValue(Dial3, 0.5)
Dial1_Event(Dial1, widget)
'flMessageBox ("You clicked Button 1", "Menu test program")
' End
End Sub
Sub Button2_Click_Event CDecl (widget as FL_Widget Ptr)
Print "Button2 was clicked!"
'Show Info:
flMessageBox ("You clicked Button 2", "I said NOT ME!")
End
End Sub
Sub Dial1_Event CDecl (widget as Fl_Widget Ptr, userData as Any Ptr)
Dim X_ as Double
Dim text as String
'X_ = (Fl_ValuatorGetValue(Dial1) * 340) + 10
X_ = Fl_ValuatorGetValue(Dial3)
X_ += Fl_ValuatorGetValue(Dial2) * 59
X_ += Fl_ValuatorGetValue(Dial1) * 300
'X_ *= 3.243243243
text = Format(X_, "###.##°")
Fl_Input_SetValue (Output_text, text)
' or the GN4RLY Hardcore c style below. Which works by the way
Select Case widget
Case Dial1
'If widget = Dial1 Then
'Fl_Input_SetValue (Output_text, Format(((Fl_ValuatorGetValue(Dial1) * 340) + 10), "###.##°"))
'EndIf
Case Dial2
'If widget = Dial2 Then
'Fl_Input_SetValue (Output_text, Format(((Fl_ValuatorGetValue(Dial2) * 340) + 10), "###.##°"))
'EndIf
Case Dial3
'If widget = Dial3 Then
'Fl_Input_SetValue (Output_text, Format(((Fl_ValuatorGetValue(Dial3) * 340) + 10), "###.##°"))
'EndIf
Case Else
' Fucked up?
End Select
End Sub
'Main program:
Create_Window_Main ()
Fl_WidgetSetCallback0(Button1_Click, @Button1_Click_Event())
Fl_WidgetSetCallback0(Button2_Click, @Button2_Click_Event())
Fl_WidgetSetCallback0(Dial1, @Dial1_Event())
Fl_WidgetSetCallback0(Dial2, @Dial1_Event())
Fl_WidgetSetCallback0(Dial3, @Dial1_Event())
Fl_WindowShow(Window_Main)
Fl_Run
End
This on the other hand compiles with no errors but does not have the FLTK button.
#Include Once "fltk-c-1.3.3/fltk-c.bi"
Dim Shared as Fl_Button Ptr FLButton1
'--------------------------------------------------------------------------------
Sub FLButton1_Event CDecl (widget as FL_Widget Ptr)
MessageBox( HWND_FBFORM, "Not here", "FLButton1 Event", MB_OK Or MB_DEFBUTTON1 Or MB_APPLMODAL )
End Sub
'--------------------------------------------------------------------------------
Function FBFORM_COMMAND1_BN_CLICKED ( _
ControlIndex as Long, _ ' index in Control Array
hWndForm as HWnd, _ ' handle of Form
hWndControl as HWnd, _ ' handle of Control
idButtonControl as Long _ ' identifier of button
) as Long
Select Case MessageBox( hWndForm, "Exit Button Properties" + Chr(13,10) + _
"Top = 230" + Chr(13,10) + _
"Left = 400" + Chr(13,10) + _
"Width = 70" + Chr(13,10) + _
"Height = 30", "FB-FLTK", _
MB_OK Or MB_DEFBUTTON1 Or MB_APPLMODAL )
Case IDOK
End
Case Else
MessageBox( hWndForm, "WTF?", "FB-FLTK Error" + Chr(13,10) + "Unknown button pressed", _
MB_OK Or MB_DEFBUTTON1 Or MB_APPLMODAL )
End Select
Function = 0 ' change according to your needs
End Function
'--------------------------------------------------------------------------------
Function FBFORM_WM_CREATE ( _
hWndForm as HWnd, _ ' handle of Form
ByVal UserData as Integer _ ' optional user defined value
) as Long
FLButton1 = Fl_ButtonNew (230, 300, 70, 30, "FLTK Button") ' Should be in front of Exit Button
Fl_WidgetSetCallback0(FLButton1, @FLButton1_Event())
Function = 0 ' change according to your needs
End Function
I can find the FF declarations of the command1 button but they are in the codegen files and of course get overwritten at compile time so no point in editing there and as far as I can figure Create should create. Here is the compilation log that does not help much.
FreeBASIC Compiler - Version 1.05.0 (01-31-2016), built for win32 (32bit)
Copyright (C) 2004-2016 The FreeBASIC development team.
standalone
target: win32, 486, 32bit
compiling: CODEGEN_FBFLTK_MAIN.bas -o CODEGEN_FBFLTK_MAIN.asm (main module)
assembling: f:\FreeBasic\bin\win32\as.exe --32 --strip-local-absolute "CODEGEN_FBFLTK_MAIN.asm" -o "CODEGEN_FBFLTK_MAIN.o"
compiling rc: f:\FreeBasic\bin\win32\GoRC.exe /ni /nw /o /fo "CODEGEN_FBFLTK_RESOURCE.obj" "CODEGEN_FBFLTK_RESOURCE.rc"
linking: f:\FreeBasic\bin\win32\ld.exe -m i386pe -o "FB-FLTK.exe" -subsystem windows "f:\FreeBasic\lib\win32\fbextra.x" --stack 1048576,1048576 -s -L "f:\FreeBasic\lib\win32" -L "." "f:\FreeBasic\lib\win32\crt2.o" "f:\FreeBasic\lib\win32\crtbegin.o" "f:\FreeBasic\lib\win32\fbrt0.o" "CODEGEN_FBFLTK_MAIN.o" "CODEGEN_FBFLTK_RESOURCE.obj" "-(" -lkernel32 -lgdi32 -lmsimg32 -luser32 -lversion -ladvapi32 -limm32 -lgdiplus -lole32 -luuid -loleaut32 -lcomctl32 -lcomdlg32 -lshell32 -lfltk-c-1.3.3-32 -lopengl32 -lfb -lgcc -lmsvcrt -lmingw32 -lmingwex -lmoldname -lgcc_eh "-)" "f:\FreeBasic\lib\win32\crtend.o"
So nothing wrong but it just does not work. Any ideas anyone.
I have never used the FLTK library but I wonder if created controls must be built inside of a Fl_WindowNew window? FireFly uses a standard WinApi CreateWindowEx for its windows/forms.
FLTK is a cross platform c++ library.
I believe Joshy has put a wrapper around it to allow Fb usage?
James
Thanks James, I am actually using Joshy's excellent wrapper. It works fine in the first example with a multitude of widgets. I think Paul has it right though. In the FLTK code everything is created in one sub along with the Window but note no use of a handle for anything except menu items in FLTK so the position in the code must decide which parent it is attached to.
Sub Create_Window_Main ()
'Window with buttons and Stuff:
Window_Main = Fl_WindowNew (400, 200, "Button Test")
Menu = Fl_Menu_BarNew (0, 0, 400, 20)
Fl_Menu_Add (Menu, "File/New" ,,@flNewFile())
Fl_Menu_Add (Menu, "File/Open" ,, @flOpenFile())
Fl_Menu_Add (Menu, "File/Save" ,, @flSaveFile())
Fl_Menu_Add (Menu, "File/Exit" ,, @flEndProgram())
Fl_Menu_Add (Menu, "Edit" ,, @flDefault())
Fl_Menu_Add (Menu, "Search" ,, @flDefault())
Fl_Menu_Add (Menu, "View" ,, @flDefault())
Fl_Menu_Add (Menu, "Tools" ,, @flDefault())
Fl_Menu_Add (Menu, "Help/Info" ,, @flInfo())
Box_text = Fl_BoxNew(150, 50, 100, 20, "Welcome to FLTK! with FreeBasic")
Output_text = Fl_OutputNew (20, 140, 60, 20, "")
Dial1 = Fl_DialNew (flDial1.flRight, flDial1.flTop, flDial1.flWidth, flDial1.flHeight, flDial1.flLabel)
Dial2 = Fl_DialNew (flDial1.flRight+30, flDial1.flTop, flDial1.flWidth, flDial1.flHeight, "2")
Dial3 = Fl_DialNew (flDial1.flRight+60, flDial1.flTop, flDial1.flWidth, flDial1.flHeight, "3")
Fl_DialAngles(Dial1, 10, 350)
Fl_DialAngles(Dial2, 10, 350)
Fl_DialAngles(Dial3, 10, 350)
Button1_Click = Fl_ButtonNew (160, 160, 100, 20, "Click me!")
Button2_Click = Fl_ButtonNew (280, 160, 100, 20, "Not me!")
End Sub
This gets called as a first order of business by what appears to be the equivalent of main() in C/C++
'Main program:
Create_Window_Main ()
Fl_WidgetSetCallback0(Button1_Click, @Button1_Click_Event())
Fl_WidgetSetCallback0(Button2_Click, @Button2_Click_Event())
Fl_WidgetSetCallback0(Dial1, @Dial1_Event())
Fl_WidgetSetCallback0(Dial2, @Dial1_Event())
Fl_WidgetSetCallback0(Dial3, @Dial1_Event())
Fl_WindowShow(Window_Main)
Fl_Run
FireFly has FF_WinMain but as you can see I tried that and same result ... No button or errors
Function FF_WINMAIN( ByVal hInstance as HINSTANCE, _
ByVal hPrevInstance as HINSTANCE, _
ByRef lpCmdLine as String, _
ByVal iCmdShow as Long ) as Long
'FLButton1 = Fl_ButtonNew (230, 300, 70, 30, "FLTK Button") ' Should be in front of Exit Button
'Fl_WidgetSetCallback0(FLButton1, @FLButton1_Event())
' If this function returns TRUE (non-zero) then the actual WinMain will exit
' thus ending the program. You can do program initialization in this function.
Function = False 'return TRUE if you want the program to end.
End Function
The FireFly create must create the window but then completes and goes out of scope I am guessing
Function FBFORM_WM_CREATE ( _
hWndForm as HWnd, _ ' handle of Form
ByVal UserData as Integer _ ' optional user defined value
) as Long
FLButton1 = Fl_ButtonNew (230, 300, 70, 30, "FLTK Button") ' Should be in front of Exit Button
Fl_WidgetSetCallback0(FLButton1, @FLButton1_Event())
Function = 0 ' change according to your needs
End Function
Thing that really gets me is that I have a floating widget declaration and callback assignment here and between the compiler, assembler and linker I should be getting at least six pages of warnings and a minimum of ten errors for it. Watch what happens when I make a simple typo.
BTW FireFly v3.78 and FreeBasic Version 1.05.0