Sei sulla pagina 1di 88

8/11/2015

Erco'sFLTKCheatPage

Erco'sFLTKCheatPage

ThesearesomecommonFLTKcodesnippetsIoftenfindhardtorememberhowtodowhenlookingatthedocs.Besides,Ilike
havingworkingcodeexampleshandythatIcancut+pastefromtogetstartedwithrightaway.Ioftenstartwiththesemini
programsandturnthemintoworkingprograms.
ThisisalwaysaworkinprogressIaddexamplesasIencountertheneedforthem.

TableOfContents
Fl_Browser

Tricksforusingabrowser

Fl_Text_Display

SimpleexampleofFl_Text_Display

Fl_Text_Displaywithcolors

SimpleexampleofFl_Text_Displaywithcolorstyles

Fl_Multiline_Output

SimpleexampleofFl_Multiline_Output

Fl_Menu_Bar:ChangingLabels

Showshowtoaccessandchangemenuitemlabelsatruntime

Fl_Menu_Bar:Togglingmenu
items

Showshowtotoggleamenuitemprocedurally

Fl_Menu_Barcallbacks

Onecallbackforallmenuitems,w/outuserdata!

Fl_Menu_Bar:Miscellaneous

MiscellaneoustechniquestomanipulateFl_Menu_Bar/Fl_Menu's

Fl_Radio_Button

Howtohandleradiobuttons

Fl_JPG_Image

SimpleexampletodisplayaJPEGimage

Fl_Image

HowtowalkpixelsofanFl_Image

Fl_Wizard

Howtomakea'wizard'usingFl_Wizard

AnimateImage

HowtoanimateimagesinFLTK

AnimateLineDrawing

HowtoanimatelinedrawinginFLTK

FltkEventNames

HowtoprintFLTKeventnamesfromwithinyourprogram(fordebugging)

popen()+add_fd()

Howtousepopen()withadd_fd()

Fltk+Fifos

Howtousefifostocontrolaconsoleprogramfromfltk,showingoutputinFl_Browser

Slider+Input

HowtotieanFl_SlidertoanFl_Int_Input

Slider+Tooltip

AnFl_Sliderwithafloating'tooltip'toshowthecurrentvalue

Fltktty

Showshowtofork()childprocessesanddisplaytheirrealtimeoutput

DrawAnX

SimpleFLTKcustomwidgettodrawan'X'

ScrollableCanvas

Showshowtomakeascrollablecustomcanvas

CustomBarGraph

Showshowtodrawacustomized'trigger'shapedbargraph

TableOfWidgets

Showshowtomakearesizable'table'ofwidgets,usingFl_ScrollandFl_Tile

DraggableBoxes

Simpleappshowsusercandragboxesonscrollable'desk'

PopupMenu

Showshowtomakeapopupmenuappear

RightClickPopupCopy/Paste
Menu

Showshowtoaddacopy/pastepopupmenutoFl_Input

PopupTextWindow

Showshowtomakeaborderlesstextwindowpopup

DrawCoordinates

Howtodrawmousecoordinatesw/outredrawingscreen

ProgressBarDemo

Howtoupdateaprogressbarinfltk

ScrollableWidgetBrowser

Demonstratesascrollablebrowserofwidgetsthatareresizable.

ScrollableImageViewer

Howtodisplayanimageinascrollableviewer

DisableSymbols

Howtodisable'@'symbolsthroughoutyourFLTKapplication

OpenGLSimpleExample

SimpleOpenGLexampleshowinghowtodrawan'X'

http://seriss.com/people/erco/fltk/

1/88

8/11/2015

Erco'sFLTKCheatPage

OpenGLAppwithFLTKWidgets

SimpleOpenGLappwithFLTKwidgetcontrols

OpenGLShapeInterpolation

Showshowtoanimatesimpleshapeinterpolationinopengl

OpenGLSphereWithLight

SimpleOpenGLShadedSpherewithLight

Fl_File_Browser

ShowshowtousetheverysparseFl_File_Browser

Fl_File_Chooser

ShowshowtouseFl_File_Chooser(simple,andfulltest)

ClicksonScrollableBox

Howtogetthecoordinatesformouseclicksonscrollablebox

Fl_BrowserwithColumns

HowtousetheFl_Browsermethodscolumn_widths()andcolumn_char()

Fl_BrowserSorting

HowtosortanFl_Browser

StrikeThroughText

Demonstratehowtodrawstrikethroughtext

Fl_Gl_Window+Cursor

DemonstratehowtochangethemousecursorforanFl_Gl_Window

Fl_Resize_Browser

HowtoextendFl_Browsertohaveinteractivelyresizablecolumns

Fl_Tile(4)PortFl_Gl_Window

Howtomakea4portproportionallyresizableOpenGLwindowusingFl_Tile

OpenGLwithDynamicPopup
Menu

HowtomakeadynamicpopupmenuforanOpenGLwindow

DropShadowBoxExample

Howtomaketextwithadropshadoweffect

OpenGL2DTexton3DObject

HowtomaketextappearonaspinningOpenGLobject

SimpleFl_TabsExample

SimpledemoofhowtousetheFl_Tabswidget

MakingaMac"Bundle"(.app)

HowtoturnaMacFLTKapplicationintoan".appbundle"

MakingiconsforMac"Bundles"

HowtomakeiconsforyourMacapplication

TouchPad

Howtomakeapopupnumerickeypadfortouchscreens

Drawingintooverlayplanes

Twoexamplesondrawingintotheoverlayplanes

ThumbnailsInScroller

Howtoshowascrollerofthumbnailimageswithlabels

DragAndDrop

HowtouseDrag+Drop

fl_draw_image()

Howtodrawintoapixelbuffer,anddisplayitusingfl_draw_image()

FLTK/WIN32FileChooser

HowtoopenaWIN32FileChooserdirectlyfromFLTK

Fl_GroupEventvs.DrawClipping

Fl_Groupxywhclipschildrenofevents,butnotgraphics

VerticalTabs

HowtouseFl_Browsertoimplementa'verticaltab'dialog

Fl_Chart

HowtouseFl_Chart

Fl_Scrollbar

HowtouseFl_Scrollbar

Howtodrawtextoveranimage

Howtoderiveaclassthatdrawstextoveranimage.

OpenGLTextureMappedCube

Atexturemappedcubewithperspective.

OpenGLImageTexturedCube

APNGimagetexturemappedtoacubewithlightingmodel,materials,andperspective.

UTF8JapaneseFontTest

AntestprogramusingJapaneseUTF8(fltk1.3.xandup)

AlphaBlending

ExampleofalphablendingwithPNGimages

SimpleTerminalEmulator

Exampleofhowtomakeascrollingterminalforexecutingcommandsusing
Fl_Text_Editor.

AToolbarWidgetwithFl_Pack

ExampleofhowtomakeanicontoolbarusinganFl_PackofFl_Button's.

KeyPress/Releasedemo

UseFl_Buttontovisualizekeyboardup/downevents.

MultipleSelectionsinFl_Table

ShowhowtomakeasecondaryselectionwithFl_Table

MultilanguageMenubar

Showshowtomakeamultilanguagemenubar.

ApplicationIcons

Howtomakeanapplicationiconforthedifferentplatforms.

DoubleClickDetection

Howtomutuallyexclusivelydetectsingleanddoubleclicks

DemonstrateFl_RGB_Image

HowtouseFl_RGB_Imagetodisplayaninlineimage.

PNGhexdumpofpixeldata

AusefulprogramthatdumpsaPNGfileinhex,suitableforinlineC/C++use

Amulticoloredbargraph

Demonstratehowtousealphachannelimagestoconstructacurvedbargraphwidget

SynchronizedKnobs

Demonstratehowtolocktwo(ormore)volumeknobs(likeanaudiomixingconsole)

ResizerBarWidget

Demonstratehowtomakearesizerbarthatcanbedraggedtoresizewidgets

http://seriss.com/people/erco/fltk/

2/88

8/11/2015

Erco'sFLTKCheatPage

SimpleFLTKTimer

DemonstratehowtouseFLTKtimers.

AJustifiedInputWidget

Demonstrateaninputwidgetthatsupportsvariousjustifications.

Spreadsheetw/HeaderEditing

Fl_Tablespreadsheeteditordemothatincludeseditingrow/colheaders

Also,someofmyotherfltkrelatedstuffvideos,LGPLwidgets,andGPLapps:
FltkVideosVideotutorialsonhowtousefltk
Fl_TreeAtreewidget(thishasbeenaddedtofltk1.3)
Fl_TableAtablewidget(thishasbeenaddedtofltk1.3)
Fl_OpDeskAfancyshmancy"nodegraph"or"nodetree"widget(like"ShadeTree"!)
Fl_Input_ChoiceAcomboofFl_InputandFl_Choice(thishasbeenaddedtofltk1.1.7)
Fl_Native_File_ChooserAwidgetforaccessingnativeOSfilebrowsers(thishasbeenaddedtofltk1.3)
Fl_Gel_TabsA'MacOSX'styletabwidget
Fl_Matte_ButtonA'mattefinish'buttonwidget
Fl_Fixed_GroupAfixedsizedgroupwhoseedgescanbeattachedtoaparent
nixieclockANixietubeClock(applicationandwidget)
flrulerAdesktopruler(GUIdebuggingtool)
Fl_BrowserAnsiPatchApatchtoFl_BrowseraddingANSIescapesequencesupport

Fl_Browser
OnethingIusealotisbrowsers,whichofteninvolvesrememberingcertainprogrammingtechniquestomanipulatethem.

Fl_Browser"HowTo"CodeSnippets
Fl_Browserbrowser(10,10,500,500,"Test")
//CLEARBROWSER
browser.clear()
//ADDLINESTOBROWSER
browser.add("One")//fltkdoesstrdup()internally
browser.add("Two")
browser.add("Three")
//FORMATCHARACTERS:CHANGINGTEXTCOLORSINLINES
//Warning:formatcharsarealsoreturnedbacktoyouvia::text()
//@C#textcolor@bbold
//@B#backgroundcolor@iitalic
//@F#setfontnumber@ffixedpitchfont
//@S#setpointsize@uunderline
//@.terminate'@'parser@strikeout
//
browser.add("Black@C1Red@C2Green@C3Yellow")
//DISABLINGFORMATCHARACTERS
browser.format_char(0)
//ACCESSALLSELECTEDITEMSINBROWSER
//Note:browser'stext()arrayis1based..!
//
for(intt=1t<=browser>size()t++){
if(browser>selected(t)){
printf("%d)'%s'\n",t,browser>text(t))
}
}
//PRESELECTALLLINESINBROWSER
//Note:indexnumbersare1based..!
//
for(intt=1t<=browser>size()t++){
browser>select(t)
}
//DESELECTALLLINESINBROWSER
browser>deselect()
//GETSINGLESELECTEDITEMFROMBROWSER
intindex=browser>value()
//USINGINDEXNUMBER,RETURNTEXT
//Note:indexnumbersare1based..!
//

http://seriss.com/people/erco/fltk/

3/88

8/11/2015

Erco'sFLTKCheatPage
if(index>0){
constchar*s=browser>text(index)
..
}

Here'sanolderexamplethatshowshowtoimplementaswap()methodforolderversionsofFl_Browser(Fltk1.1.5orless)

Fl_Multiline_Output
MakingwindowsthatdisplaymultiplelinesoftextisanothercommonthingIfindmyselfdoing.

DisplayingMultipleLinesOfText"HowTo"CodeSnippets
Fl_Multiline_Outputoutput(0,0,500,500)
//CLEAROUTPUT
output>value("")
//SETOUTPUT
output>value("one\ntwo")//fltkdoesstrdup()internally
//APPENDINGOUTPUT
//Wouldbeniceifthiswereanadd()methodinfltk)
//
char*news="Addthistext"
char*cat=(char*)malloc(strlen(output>value())+
istrlen(news)+1)
strcpy(cat,output>value())
strcat(cat,news)
output>value(cat)
free(cat)

Fl_Menu_Bar:ChangingMenuItem'sLabelsAtRuntime

Showshowtoaccessandchangemenuitemsatruntime.
Showshowtouseadd()todynamicallyadditemstoamenubar,andfind_item()tofind+modifyitems.
Inthisexample,clickingtheEdit|ChangemenuitemwillchangetheEdit|Submenu'snameinto"NewSubmenuName",and
changesthelabelofthe'Aaa'iteminitto"NewAaaName'.

AccessandChangeMenuItem'sLabels
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Menu_Bar.H>
#include<stdlib.h>
//
//Showhowtochangesubmenunamesandmenuitemnames
//ClickonEdit>ChangetochangethecontentsoftheEditmenu.
//
voidChange_CB(Fl_Widget*w,void*){
Fl_Menu_Bar*menu=(Fl_Menu_Bar*)w
Fl_Menu_Item*p
//Changesubmenuname
p=(Fl_Menu_Item*)menu>find_item("Edit/Submenu")
if(p)p>label("NewSubmenuName")
//Changeitemname
p=(Fl_Menu_Item*)menu>find_item("Edit/NewSubmenuName/Aaa")
if(p)p>label("NewAaaName")
}
voidQuit_CB(Fl_Widget*,void*){
exit(0)
}
intmain(){

http://seriss.com/people/erco/fltk/

4/88

8/11/2015

Erco'sFLTKCheatPage
Fl_Window*win=newFl_Window(400,400)
Fl_Menu_Bar*menu=newFl_Menu_Bar(0,0,400,25)
menu>add("File/Quit",FL_CTRL+'q',Quit_CB)
menu>add("Edit/Change",FL_CTRL+'c',Change_CB)
menu>add("Edit/Submenu/Aaa")
menu>add("Edit/Submenu/Bbb")
win>end()
win>show()
return(Fl::run())
}

Fl_Menu_Bar:TogglingAMenuItemAtRuntime
Showshowtotogglemenuitemsatruntime.
Usesadd()tocreatetoggleitems,find_item()tofindtheitem,andset()andclear()methodstochangetheitem'stogglestate.

ToggleMenuItems
#include<stdio.h>
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Menu_Bar.H>
//
//Demonstratehowtotoggleamenuitemprocedurallyerco05/14/09
//
//SETAMENUITEM'SSTATE
//Findthemenuitembyname,andchangeitsstate.
//Returns1ifnamedmenuitemnotfound.
//
intSetMenuItemState(Fl_Menu_Bar*menubar,constchar*name,intstate){
Fl_Menu_Item*m=(Fl_Menu_Item*)menubar>find_item(name)
if(!m)return(1)
if(state){m>set()}
else{m>clear()}
return(0)
}
intmain(intargc,char**argv){
Fl_Double_Window*win=newFl_Double_Window(720,486)
Fl_Menu_Bar*menubar=newFl_Menu_Bar(0,0,720,25)
menubar>add("Options/One",0,0,0,FL_MENU_TOGGLE)
menubar>add("Options/Two",0,0,0,FL_MENU_TOGGLE)
menubar>add("Options/Three",0,0,0,FL_MENU_TOGGLE)
win>end()
win>show()
//TESTTHESTATECHANGESTURN'ONE'OFF,OTHERS'ON'
if(SetMenuItemState(menubar,"Options/One",0)<0){fprintf(stderr,"FAILED[1]\n")}
if(SetMenuItemState(menubar,"Options/Two",1)<0){fprintf(stderr,"FAILED[2]\n")}
if(SetMenuItemState(menubar,"Options/Three",1)<0){fprintf(stderr,"FAILED[3]\n")}
return(Fl::run())
}

Fl_Menu_BarSingleCallbackExample
Here'sanexampleprogramshowinganeattrickthatletsthemenubar'scallbackdeterminethefullmenuitem's'pathname'(eg.
"File/Quit")withoutusinganyuserdata.

AccessingMenuItemsWithoutUsingCallbackData
//Showtheuseofitem_pathname()inacustomclass.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Menu_Bar.H>
classMyApp{
Fl_Window*win
Fl_Menu_Bar*menubar
//Staticmenucallback
staticvoidMenu_CB(Fl_Widget*w,void*data){
MyApp*o=(MyApp*)data
o>Menu_CB2()
}
//Callbackmethodwithclassaccess
voidMenu_CB2(){
charpicked[80]
menubar>item_pathname(picked,sizeof(picked)1)
printf("CALLBACK:Youpicked'%s'\n",picked)

http://seriss.com/people/erco/fltk/

5/88

8/11/2015

Erco'sFLTKCheatPage
//Howtohandlecallbacks..
if(strcmp(picked,"File/Quit")==0)exit(0)
if(strcmp(picked,"Help/Help")==0)printf("Helpgoeshere\n")
}
public:
MyApp(){
//Maketheappwindowandmenubarw/callbacks
win=newFl_Window(720,486)
menubar=newFl_Menu_Bar(0,0,win>w(),25)
menubar>add("File/Open",0,Menu_CB,(void*)this)//userdataisalways'this'
menubar>add("File/Quit",0,Menu_CB,(void*)this)
menubar>add("Help/Help",0,Menu_CB,(void*)this)
win>end()
win>show()
}
}
//MAIN
intmain(){
MyAppapp
return(Fl::run())
}

Here'sanolderexamplethatworkswithfltk1.1.5andbackthatdoesn'thaveitem_pathname()builtin.

Fl_Menu_Bar
Dynamicallycreating/clearingsubmenusinthemainmenubarissomethingIoftenneedtodo.Sinceit'snotwelldocumented
howthisisdone,thisiswhatI'vefiguredout.
WARNING:whencreatingormodifyingmenususingadd(),bewarethatifyounameitemsinfluid,thepointersmaybecome
invalid,sincedynamicmanipulationofthemenuscancausethearraytoberealloc()ed,causingmenuitempointerstobecome
STALE.Thesubmenusandalltheircontentsinthemenubararereallyallpartofasinglelinearinternalarraytothe
Fl_Menu_Barclass,andareaccessedas:

AccessingMenuItemsInFl_Menu_Bar
for(intt=0t<menubar>size()t++){
Fl_Menu_Item*m=(Fl_Menu_Item*)&(menubar>menu()[t])
:
:
}

Giventheaboveonhowthemenusarearrangedinthearray,herearesomeguidesforhowtowriteroutinestoworkwithFLTK
menusdynamically.

DynamicManipulationOfMenusinFLTK
//FINDMENUITEMINDEX,GIVENMENUPATHNAME
//eg."Edit/Copy"
//Willalsoreturnsubmenus,eg."Edit"
//Returns1ifnotfound.
//
intGetIndexByName(Fl_Menu_Bar*menubar,constchar*findname){
charmenupath[1024]=""//File/Export
for(intt=0t<menubar>size()t++){
Fl_Menu_Item*m=(Fl_Menu_Item*)&(menubar>menu()[t])
if(m>submenu()){
//Submenu?
if(menupath[0])strcat(menupath,"/")
strcat(menupath,m>label())
if(strcmp(menupath,findname)==0)return(t)
}else{
if(m>label()==NULL){
//Endofsubmenu?Popbackonelevel.
char*ss=strrchr(menupath,'/')
if(ss)*ss=0
elsemenupath[0]='\0'
continue
}
//Menuitem?
charitempath[1024]//eg.Edit/Copy
strcpy(itempath,menupath)
if(itempath[0])strcat(itempath,"/")
strcat(itempath,m>label())
if(strcmp(itempath,findname)==0){
return(t)
}
}
}
return(1)
}
//FINDAMENUITEMBYMENUPATHNAME
//eg."Edit/Copy"
//Willalsoreturnsubmenus,eg."Edit"

http://seriss.com/people/erco/fltk/

6/88

8/11/2015

Erco'sFLTKCheatPage
//ReturnsNULLifnotfound.
//
Fl_Menu_Item*GetMenuItemByName(Fl_Menu_Bar*menubar,constchar*findname){
intindex=GetIndexByName(menubar,findname)
if(index==1)return(NULL)
Fl_Menu_Item*m=(Fl_Menu_Item*)&(menubar>menu()[index])
return(m)
}
//TURNONRADIOBUTTONGIVENMENUPATHNAME
//eg.SetRadioByName(menubar,"File/Radio1")
//
voidSetRadioByName(Fl_Menu_Bar*menubar,constchar*menuname){
Fl_Menu_Item*m=GetMenuItemByName(menubar,menuname)
if(m==NULL)return
m>setonly()
}
//SETTOGGLEBUTTONONOROFF,GIVENMENUPATHNAME
//eg.SetToggleByName("File/Toggle1","on")
//
voidSetToggleByName(Fl_Menu_Bar*menubar,constchar*menuname,intval){
Fl_Menu_Item*m=GetMenuItemByName(menubar,menuname)
if(m==NULL)return
if(val)m>set()
elsem>clear()
}
//ACTIVATEMENUITEM,GIVENMENUITEMPATHNAME
//eg.SetActivateByName("File/Radio1")
//
voidSetActivateByName(Fl_Menu_Bar*menubar,constchar*menuname,intval){
Fl_Menu_Item*m=GetMenuItemByName(menubar,menuname)
if(m==NULL)return
if(val)m>activate()
elsem>deactivate()
}
//GETTOGGLEBUTTONSTATE,GIVENMENUPATHNAME
//eg.GetToggleByName("Edit/Preferences/Toggle1")
//
intGetToggleValueByName(Fl_Menu_Bar*menubar,constchar*menuname){
Fl_Menu_Item*m=GetMenuItemByName(menubar,menuname)
if(m==NULL)return
return(m>value())
}
//CLEARALLITEMSINSUBMENUBELOWTHENAMEDITEM
//eg.ClearItemsBelow("File/SaveAs")
//wheremenulookslike:
//
//File..New
//Open
//Save
//SaveAs
//__
///usr/tmp/foo.st|__Clearallthesesothey
///usr/tmp/bar.st|canberecreatedlater.
///usr/tmp/bla.st__|
//__
//Edit..Cut|
//Copy|Theseareunaffected.
//Paste__|
//
staticvoidClearItemsBelow(Fl_Menu_Bar*menubar,constchar*menuname){
intindex=GetIndexByName(menubar,menuname)
if(index==1)return
intlevel=0
++index//skiptheitemitself,sowedeletestuff_below_it
while(index<=menubar>size()){
Fl_Menu_Item*m=(Fl_Menu_Item*)&(menubar>menu()[index])
if(m>label()==NULL){
//Popoutofsubmenu,keeptrackoflevel
if(level<0)return
}else{
//Descendingintoasubmenu?KeeptrackofleveL
if(m>submenu())
++level
}
//Removeallmenuitems*and*submenus
menubar>remove(index)
}
}

Fl_Radio_Button
Dealingwithradiobuttonsinmenusisfairlyeasy,usingtheFl_Menu_Barroutinesdescribedabove.Iguessfltkgroupsradio
buttonstogetherbasedondividersandsubmenus.

UsingRadioButtonsInMenus
intindex=GetIndexByName(menubar,"Edit/Preferences/Radio1")
Fl_Menu_Item*m=menubar>menu()
m[index]>setonly()//setradioon,turnsother(s)off
intonoff=m[index]>value()//getradiobutton'sstate

http://seriss.com/people/erco/fltk/

7/88

8/11/2015

Erco'sFLTKCheatPage

Fl_Text_Display
AsimpleexampleofhowtouseFl_Text_Display,areadonlyviewer.
Ifyouwanttomakeitaneditor,changeallinstancesofthestring"Fl_Text_Display"to"Fl_Text_Editor".

SimpleExampleofHowToUseFl_Text_Display
//Fl_Text_Displayexample.erco
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Text_Display.H>
intmain(){
Fl_Window*win=newFl_Window(640,480)
Fl_Text_Buffer*buff=newFl_Text_Buffer()
Fl_Text_Display*disp=newFl_Text_Display(20,20,64040,48040,"Display")
disp>buffer(buff)
win>resizable(*disp)
win>show()
buff>text("line0\nline1\nline2\n"
"line3\nline4\nline5\n"
"line6\nline7\nline8\n"
"line9\nline10\nline11\n"
"line12\nline13\nline14\n"
"line15\nline16\nline17\n"
"line18\nline19\nline20\n"
"line21\nline22\nline23\n")
return(Fl::run())
}

Fl_Text_Displaywithcolors
AsimpleexampleofhowtouseFl_Text_Displaywithcolors.
Thisexampleshowshowtoaddtextwithdifferentcolorsbycreatinga'stylebuffer',whereeachcharacterinthestylebuffer
correspondstoacharacterinthetextbuffer,andthecontentsofthestylebufferspecifiescharacters(A,B,C..)that
correspondtoentriesinyourpredefined'styletable',thatdefinestheactualattributesofeachcharacter.
Thisschemeissimilartoa'colormap'inimages,wheretheimagedataisnotanRGBcolor,butanindexintoacolortable.
ThisexampleshouldworkequallywellwithFl_Text_Editor.(Justchangeallinstancesof"Fl_Text_Display"inthecodeto
"Fl_Text_Editor")

SimpleExampleofFl_Text_Displaywithcolors
//Fl_Text_Displayexamplewithcolorstyles.erco
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Text_Display.H>
intmain(){
//Styletable
Fl_Text_Display::Style_Table_Entrystable[]={
//FONTCOLORFONTFACEFONTSIZE
//
{FL_RED,FL_COURIER,18},//ARed
{FL_DARK_YELLOW,FL_COURIER,18},//BYellow
{FL_DARK_GREEN,FL_COURIER,18},//CGreen
{FL_BLUE,FL_COURIER,18},//DBlue
}
Fl_Window*win=newFl_Window(640,480)
Fl_Text_Display*disp=newFl_Text_Display(20,20,64040,48040,"Display")

http://seriss.com/people/erco/fltk/

8/88

8/11/2015

Erco'sFLTKCheatPage
Fl_Text_Buffer*tbuff=newFl_Text_Buffer()//textbuffer
Fl_Text_Buffer*sbuff=newFl_Text_Buffer()//stylebuffer
disp>buffer(tbuff)
intstable_size=sizeof(stable)/sizeof(stable[0])
disp>highlight_data(sbuff,stable,stable_size,'A',0,0)
//Text
tbuff>text("RedLine1\nYelLine2\nGrnLine3\nBluLine4\n"
"RedLine5\nYelLine6\nGrnLine7\nBluLine8\n")
//Stylefortext
sbuff>text("AAAAAAAAAA\nBBBBBBBBBB\nCCCCCCCCCC\nDDDDDDDDDD\n"
"AAAAAAAAAA\nBBBBBBBBBB\nCCCCCCCCCC\nDDDDDDDDDD\n")
win>resizable(*disp)
win>show()
return(Fl::run())
}

Fl_JPG_Image:Asimpleexample
AsimpleexampleofhowtoloadanddisplayaJPEGimage.
ForPNG's,justsubstitutealloccurancesof"Fl_JPEG_Image"with"Fl_PNG_Image".SameforGIFs,andothersupported
imageformats.

SimpleexampletodisplayaJPEGimage
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Shared_Image.H>
#include<FL/Fl_JPEG_Image.H>
#include<FL/Fl_Box.H>
//COMPILE:fltkconfiguseimagescompileloadjpeg.cxx
intmain(){
fl_register_images()//initializeimagelib
Fl_Windowwin(720,486)//makeawindow
Fl_Boxbox(10,10,72020,48620)//widgetthatwillcontainimage
Fl_JPEG_Imagejpg("/var/tmp/foo.jpg")//loadjpegimageintoram
box.image(jpg)//attachjpgimagetobox
win.show()
return(Fl::run())
}

Fl_Image
Anexampleofhowtowalkther/g/bpixeldataofanFl_BMP_Imageimage.
NOTE:Therearefasterwaysofcodingthistoavoidrecalculating'index'ateverypixel.Thisisjusttomakeaclearexampleof
howpixelindexesshouldbecalculated,eg.forrandomaccess.Optimizationisleftasanexercisetothereader.

AccessingRawRGBDatafromFl_Image
#include<stdio.h>
#include<FL/Fl_BMP_Image.H>
intmain(){
Fl_BMP_Image*img=newFl_BMP_Image("tiny.bmp")
if(img>d()==0){
perror("tiny.bmp")
exit(1)
}
charr,g,b
for(inty=0y<img>h()y++){//Xloop
for(intx=0x<img>w()x++){//Yloop
longindex=(y*img>w()*img>d())+(x*img>d())//X/Y>bufindex
switch(img>count()){
case1:{//bitmap
constchar*buf=img>data()[0]
switch(img>d()){
case1:{//8bit
r=g=b=*(buf+index)
break
}
case3://24bit

http://seriss.com/people/erco/fltk/

9/88

8/11/2015

Erco'sFLTKCheatPage
r=*(buf+index+0)
g=*(buf+index+1)
b=*(buf+index+2)
break
default://??
printf("Notsupported:chans=%d\n",img>d())
exit(1)
}
break
}
default://??pixmap,bitvals
printf("Notsupported:count=%d\n",img>count())
exit(1)
}
printf("%2x%2x%2x\n",//hexdumpr/g/b
(unsignedchar)r,
(unsignedchar)g,
(unsignedchar)b)
}
}
}

Fl_WizardExample

Asimple3screen'wizard'usingFl_Wizard,showinghowgroupscanbeusedtomovethroughthe'pages'ofthewizard.

FLTK'sWizard
#include<stdlib.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Group.H>
#include<FL/Fl_Wizard.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Multiline_Output.H>
//Simple'wizard'usingfltk'snewFl_Wizardwidget
Fl_Window*G_win=0
Fl_Wizard*G_wiz=0
voidback_cb(Fl_Widget*,void*){G_wiz>prev()}
voidnext_cb(Fl_Widget*,void*){G_wiz>next()}
voiddone_cb(Fl_Widget*,void*){exit(0)}
intmain(intargc,char**argv){
G_win=newFl_Window(400,300,"ExampleWizard")
G_wiz=newFl_Wizard(0,0,400,300)
//Wizard:page1
{
Fl_Group*g=newFl_Group(0,0,400,300)
Fl_Button*next=newFl_Button(290,265,100,25,"Next")next>callback(next_cb)
Fl_Multiline_Output*out=newFl_Multiline_Output(10,30,40020,30080,"Welcome")
out>labelsize(20)
out>align(FL_ALIGN_TOP|FL_ALIGN_LEFT)
out>value("ThisisFirstpage")
g>end()
}
//Wizard:page2
{
Fl_Group*g=newFl_Group(0,0,400,300)
Fl_Button*next=newFl_Button(290,265,100,25,"Next")next>callback(next_cb)
Fl_Button*back=newFl_Button(180,265,100,25,"Back")back>callback(back_cb)
Fl_Multiline_Output*out=newFl_Multiline_Output(10,30,40020,30080,"TermsAndConditions")
out>labelsize(20)
out>align(FL_ALIGN_TOP|FL_ALIGN_LEFT)
out>value("ThisistheSecondpage")
g>end()

http://seriss.com/people/erco/fltk/

10/88

8/11/2015

Erco'sFLTKCheatPage
}
//Wizard:page3
{
Fl_Group*g=newFl_Group(0,0,400,300)
Fl_Button*done=newFl_Button(290,265,100,25,"Finish")done>callback(done_cb)
Fl_Button*back=newFl_Button(180,265,100,25,"Back")back>callback(back_cb)
Fl_Multiline_Output*out=newFl_Multiline_Output(10,30,40020,30080,"Finish")
out>labelsize(20)
out>align(FL_ALIGN_TOP|FL_ALIGN_LEFT)
out>value("ThisistheLastpage")
g>end()
}
G_wiz>end()
G_win>end()
G_win>show(argc,argv)
returnFl::run()
}

ImageAnimationExample

ShowshowtoanimatesomeJPGfiles.Herearesomejpgsyoucanuseforplayback.

AnimatingImagesinFLTK
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Shared_Image.H>
#include<FL/Fl_JPEG_Image.H>
#include<FL/Fl_Box.H>
//animate.cxxAnimateplaybackofthreejpgimages(0001.jpg,0002.jpg..)
//HoldeachimageforRATEseconds
//
#defineRATE0.1//howlongtoholdeachimage
#defineTOTAL3//totalimages:/var/tmp/000{1,2,3}.jpg
Fl_Window*win=0//mainwindow
Fl_JPEG_Image*jpgs[TOTAL]//loadedimages
Fl_Group*grp=0//groupinwhichimagesaredisplayed
//SHOWNEXTIMAGE
//Slapsnextimageuponscreen,resetsframetimer.
//
voidShowNextImage_CB(void*){
staticintx=0
grp>image(jpgs[x++%TOTAL])
win>redraw()
//Fl::repeat_timeout(RATE,ShowNextImage_CB)//steadyrate
Fl::repeat_timeout(((x%TOTAL)==0)?2.0:RATE,ShowNextImage_CB)//eyeblink:hold0003.jpgfor2secs
}
//LOADALLIMAGESINTOMEMORY
intLoadImages(){
for(intt=0t<TOTALt++){
charfilename[80]
sprintf(filename,"%04d.jpg",t+1)//0001.jpg,0002.jpg..
jpgs[t]=newFl_JPEG_Image(filename)
if(jpgs[t]>w()==0){perror(filename)return(1)}
}
return(0)
}
//MAINOPENDOUBLEBUFFEREDWINDOW,LOADIMAGES,STARTPLAYBACK
intmain(){
fl_register_images()//initializeimagelib
win=newFl_Double_Window(720,486)//makeawindow
grp=newFl_Group(0,0,win>w(),win>h())
grp>align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE|FL_ALIGN_CLIP)

http://seriss.com/people/erco/fltk/

11/88

8/11/2015

Erco'sFLTKCheatPage
win>show()
if(LoadImages())return(1)
Fl::add_timeout(RATE,ShowNextImage_CB)
return(Fl::run())
}

I'vealsomadeatarfilethatincludestheabovecodealongwith45jpegimageshere:
smoothanimation45x.tar.gz
Theimagesareall720x720insize,andtheanimate.cxxfile(included)ismodifiedtoloadall45imagesandplaythembackat
30fps.ItincludesaMakefilewhichwillbuildandruntheprogramwith:
makecleanmake./animate

TheanimationitplaysbackisagreatCGIanimationmadebyFriedrichA.LohmullerhecallsPenroseTriangle.

LineDrawingAnimationExample

Showshowtoanimatelinedrawing,showingasimpletimerapplicationthatanimatesthe'secondhand'.

AnimatingLineDrawinginFLTK
//
//FLTKdrawingexampleshowingsimplelinedrawinganimation
//erco03/22/07
//
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Box.H>
#include<FL/fl_draw.H>
#include<math.h>
#include<stdio.h>
#include<time.h>
#defineBG_COLOR45
#defineTICK_COLOR50
#defineCIRC_COLOR0
classMyTimer:publicFl_Box{
voiddraw(){
//COMPUTENEWCOORDSOFLINE
staticlongstart=time(NULL)
longtick=time(NULL)start
charsecs[80]sprintf(secs,"%02ld:%02ld",tick/60,tick%60)
floatpi=3.14(((tick%60)/60.0)*6.28)
intradius=h()/2
intx1=(int)(x()+w()/2),
y1=(int)(y()+h()/2),
x2=(int)(x1+(sin(pi)*radius)),
y2=(int)(y1+(cos(pi)*radius))
//TELLBASEWIDGETTODRAWITSBACKGROUND
Fl_Box::draw()
//DRAW'SECONDHAND'OVERWIDGET'SBACKGROUND
fl_color(TICK_COLOR)
fl_line(x1,y1,x2,y2)
fl_color(CIRC_COLOR)
fl_pie(x110,y110,20,20,0.0,360.0)
//DRAWTIMERTEXTSTRING
fl_color(TICK_COLOR)
fl_font(FL_HELVETICA,16)
fl_draw(secs,x()+4,y()+h()4)
}
staticvoidTimer_CB(void*userdata){
MyTimer*o=(MyTimer*)userdata
o>redraw()
Fl::repeat_timeout(0.25,Timer_CB,userdata)
}
public:
//CONSTRUCTOR

http://seriss.com/people/erco/fltk/

12/88

8/11/2015

Erco'sFLTKCheatPage
MyTimer(intX,intY,intW,intH,constchar*L=0):Fl_Box(X,Y,W,H,L){
box(FL_FLAT_BOX)
color(BG_COLOR)
Fl::add_timeout(0.25,Timer_CB,(void*)this)
}
}
//MAIN
intmain(){
Fl_Double_Windowwin(220,220)
MyTimertim(10,10,win.w()20,win.h()20)
win.show()
return(Fl::run())
}

PrintingFLTKEventNames
Update06/01/2011:myeventnames.hhasbeenadoptedbytheFLTKprojectin1.1.8backin2007,renamedto'names.h'
andthearraynamedfl_eventnames[].Soyoucanaccessitwith:
#include<FL/names.h>
fprintf(stderr,"EVENT:%s(%d)\n",fl_eventnames[e],e)

ForversionsofFLTKolderthan1.1.8thatdon'thaveFL/names.h,youcangrabmyoriginaleventnames.hfileanduse
#include"eventnames.h"toloadit,andfl_eventnames[e](where'e'istheeventnumber)togettheeventnames.

PrintingFLTKEventNames
#include<FL/names.h>//FLTK1.1.8andup
:
classYourClass:publicFl_Window{
inthandle(inte){
:
fprintf(stderr,"EVENT:%s(%d)\n",fl_eventnames[e],e)
:
}
}

Usingpopen()andFl::add_fd()

Thefollowingcodeshowshowtousepopen()withFl::add_fd().
Youcanhighlighttextandscrollwhileoutputiscomingin,showingthattheFLTKinterfaceis'alive'whilethecommandis
running.
Theadd_fd()techniqueworkswellunderunix,butdoesnotworkunderWindows.

Example:Usingpopen()andFl::add_fd()
//demouseofpopen()andFl::add_fd()erco10/04/04
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Multi_Browser.H>
#include<stdio.h>
#include<unistd.h>

http://seriss.com/people/erco/fltk/

13/88

8/11/2015

Erco'sFLTKCheatPage
#definePING_CMD"pingi3localhost"//'slowcommand'underunix
FILE*G_fp=NULL
voidHandleFD(intfd,void*data){
Fl_Multi_Browser*brow=(Fl_Multi_Browser*)data
chars[1024]
if(fgets(s,1023,G_fp)==NULL){
Fl::remove_fd(fileno(G_fp))
pclose(G_fp)
return
}
brow>add(s)
}
intmain(){
Fl_Windowwin(600,600)
Fl_Multi_Browserbrow(10,10,580,580)
if((G_fp=popen(PING_CMD,"r"))==NULL){
perror("popenfailed")
return(1)
}
Fl::add_fd(fileno(G_fp),HandleFD,(void*)&brow)
win.resizable(brow)
win.show()
return(Fl::run())
}

Here'sasimilarexample,showinghowabuttoncanbeusedtoinvokethecommand,andthebuttongraysoutandcursor
changestoatimerwhilethecommandruns,andwhenthecommandfinishes,theinterfaceisrestoredtonormal.

Fltk+Fifos
Thefollowingshowshowtousefifostocontrolaconsoleorientedmenuprogramfromfltk,showingitsoutputinFl_Browser.
Unixonly.
Thisdemousesabourneshellscript[menu.sh]tobethe'menuprogram'tobecontrolledbythefltkprogram[demofifo.cxx].

Example:UsingFLTKwithnamedpipesandpopen()
[menu.sh]
#!/bin/bash
while[1]do
echo""
echo"MenuOptions"
echo"a)Doanlsla"
echo"b)netstat"
echo"c)date/uptime/w"
echo"q)quit"
echo""
echo"Yourchoice?"
readchoice
if[!$?]thenecho'Parentclosed'exit1fi
case$choicein
a)lsla
b)netstat
c)dateuptimew
q)exit0
esac
done

[demofifo.cxx]
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>//mkfifo
#include<sys/stat.h>//mkfifo
#include<fcntl.h>//open
#include<signal.h>//killpg
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Multi_Browser.H>
#include<FL/Fl_Button.H>

http://seriss.com/people/erco/fltk/

14/88

8/11/2015

Erco'sFLTKCheatPage
//
//Demonstratehowtousefltkwithnamedpipes
//erco1.0009/21/2005
//
//Globals
FILE*G_in=NULL//howwereadthechild
intG_out=0//howwewritetothechild
//Closealldescriptors,removefifo
voidCleanExit_CB(Fl_Widget*,void*data){
unlink("tomenu.fifo")
killpg(getpid(),SIGKILL)
_exit(0)
}
//Readoutputfromchild,appendtobrowser
voidHandleInput_CB(int,void*data){
Fl_Multi_Browser*brow=(Fl_Multi_Browser*)data
staticintx=0
staticchars[1024]
charc=fgetc(G_in)//readonecharatatime
if(c=='\n'||x==(sizeof(s)1))
{s[x]=0brow>add(s)x=0}
else
{s[x++]=c}
}
//Handlesendingcommandstochildwhenbuttonpressed
voidHandleButton_CB(Fl_Widget*,void*data){
write(G_out,data,strlen((char*)data))//'data'isastring,eg."a\n"
}
intmain(){
//Processgroupleader(forkillpg())
setsid()
//Makefifo
unlink("tomenu.fifo")
if(mkfifo("tomenu.fifo",0666)<0){
perror("mkfifo(tomenu.fifo)")
exit(1)
}
//Popenchildforreading,setchildtoreadfifo
if((G_in=popen("./menu.sh<tomenu.fifo","r"))==NULL){
perror("popenfailed")
exit(1)
}
setbuf(G_in,NULL)//disablebuffering
//Nowopenfifo
if((G_out=open("tomenu.fifo",O_WRONLY))<0){
perror("open(tomenu.fifo)forwritefailed")
unlink("tomenu.fifo")
exit(1)
}
//Fltkstuff
Fl_Windowwin(600,600)
win.callback(CleanExit_CB)
Fl_Buttona(10,10,20,20,"A")a.callback(HandleButton_CB,(void*)"a\n")
Fl_Buttonb(30,10,20,20,"B")b.callback(HandleButton_CB,(void*)"b\n")
Fl_Buttonc(50,10,20,20,"C")c.callback(HandleButton_CB,(void*)"c\n")
Fl_Buttonq(70,10,20,20,"q")q.callback(CleanExit_CB,(void*)"q\n")
Fl_Multi_Browserbrow(10,30,580,560)
brow.textfont(FL_COURIER)
Fl::add_fd(fileno(G_in),HandleInput_CB,(void*)&brow)
win.resizable(brow)
win.show()
return(Fl::run())
}

TyinganFl_SliderandFl_Int_InputTogether
ThefollowingcodeshowshowtotieFl_Int_InputandFl_Sliderwidgetstogether,makinganew'composite'widgetcalled
'SliderInput'.ThewidgetisderivedfromanFl_Group,sothatthetwowidgetscanexisttogether.
Draggingthesliderchangestheinputwidget,andchangingtheinputwidgetrepositionstheslider.eg:

SliderInputTieFl_SliderandFl_Int_Inputtogether
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Int_Input.H>

http://seriss.com/people/erco/fltk/

15/88

8/11/2015

Erco'sFLTKCheatPage
#include<FL/Fl_Slider.H>
#include<stdio.h>
//sliderinputsimpleexampleoftyinganfltksliderandinputwidgettogether
//1.00erco10/17/04
classSliderInput:publicFl_Group{
Fl_Int_Input*input
Fl_Slider*slider
//CALLBACKHANDLERS
//These'attach'theinputandslider'svaluestogether.
//
voidSlider_CB2(){
staticintrecurse=0
if(recurse){
return
}else{
recurse=1
chars[80]
sprintf(s,"%d",(int)(slider>value()+.5))
//fprintf(stderr,"SPRINTF(%d)>'%s'\n",(int)(slider>value()+.5),s)
input>value(s)//passslider'svaluetoinput
recurse=0
}
}
staticvoidSlider_CB(Fl_Widget*w,void*data){
((SliderInput*)data)>Slider_CB2()
}
voidInput_CB2(){
staticintrecurse=0
if(recurse){
return
}else{
recurse=1
intval=0
if(sscanf(input>value(),"%d",&val)!=1){
val=0
}
//fprintf(stderr,"SCANF('%s')>%d\n",input>value(),val)
slider>value(val)//passinput'svaluetoslider
recurse=0
}
}
staticvoidInput_CB(Fl_Widget*w,void*data){
((SliderInput*)data)>Input_CB2()
}
public:
//CTOR
SliderInput(intx,inty,intw,inth,constchar*l=0):Fl_Group(x,y,w,h,l){
intin_w=40
input=newFl_Int_Input(x,y,in_w,h)
input>callback(Input_CB,(void*)this)
input>when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED)
slider=newFl_Slider(x+in_w,y,win_w,h)
slider>type(1)
slider>callback(Slider_CB,(void*)this)
bounds(1,10)//someusabledefault
value(5)//someusabledefault
end()//closethegroup
}
//MINIMALACCESSORSAddyourownasneeded
intvalue()const{return((int)(slider>value()+0.5))}
voidvalue(intval){slider>value(val)Slider_CB2()}
voidminumum(intval){slider>minimum(val)}
intminumum()const{return((int)slider>minimum())}
voidmaximum(intval){slider>maximum(val)}
intmaximum()const{return((int)slider>maximum())}
voidbounds(intlow,inthigh){slider>bounds(low,high)}
}
intmain(){
Fl_Windowwin(240,90)
SliderInput*si=newSliderInput(20,20,200,50,"SliderInput")
si>bounds(1,100)//setmin/maxforslider
si>value(50)//setinitialvalue
win.show()
return(Fl::run())
}

http://seriss.com/people/erco/fltk/

16/88

8/11/2015

Erco'sFLTKCheatPage

Fl_Sliderwithafloatingtooltiptoshowcurrentvalue
Thefollowingcodeshowshowtogetafloatingtooltiptoshowthecurrentvalueofthesliderwhileit'sbeingmoved.Notwell
tested.'Itworksunderlinux'.Example:

Fl_Sliderwithafloatingtooltiptoshowcurrentvalue
//Demonstrateasliderwithtooltipthattracksthemouseerco11/18/04
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<FL/fl_draw.H>
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Group.H>
#include<FL/Fl_Slider.H>
#include<FL/Fl_Menu_Window.H>
#include<FL/Fl_Tooltip.H>
//FLOATINGTIPWINDOW
classTipWin:publicFl_Menu_Window{
chartip[40]
public:
TipWin():Fl_Menu_Window(1,1){//willautosize
strcpy(tip,"X.XX")
set_override()
end()
}
voiddraw(){
draw_box(FL_BORDER_BOX,0,0,w(),h(),Fl_Color(175))
fl_color(FL_BLACK)
fl_font(labelfont(),labelsize())
fl_draw(tip,3,3,w()6,h()6,Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP))
}
voidvalue(floatf){
sprintf(tip,"%.2f",f)
//Recalcsizeofwindow
fl_font(labelfont(),labelsize())
intW=w(),H=h()
fl_measure(tip,W,H,0)
W+=8
size(W,H)
redraw()
}
}
//VALUESLIDERWITHFLOATINGTIPWINDOW
classMyValueSlider:publicFl_Slider{
TipWin*tipwin
voidvalue_cb2(){
tipwin>value(value())
tipwin>position(Fl::event_x_root(),Fl::event_y_root()+20)
}
staticvoidvalue_cb(Fl_Widget*,void*data){
MyValueSlider*val=(MyValueSlider*)data
val>value_cb2()
}
public:
MyValueSlider(intx,inty,intw,inth,constchar*l=0):Fl_Slider(x,y,w,h,l){
type(FL_HOR_SLIDER)
callback(value_cb,(void*)this)
Fl_Group*save=Fl_Group::current()//savecurrentwidget..
tipwin=newTipWin()//..becausethistrashesit
tipwin>hide()
Fl_Group::current(save)//..thenbacktoprevious.
}
inthandle(inte){
switch(e){
caseFL_PUSH:
//XXX:ifoffscreen,movetipABOVEmouseinstead
tipwin>position(Fl::event_x_root(),Fl::event_y_root()+20)
tipwin>value(value())
tipwin>show()
break
caseFL_HIDE://valuatorgoesaway
caseFL_RELEASE://releasemouse
caseFL_LEAVE://leavefocus
//Makesuretipwincloseswhenappcloses
tipwin>hide()
break
}
return(Fl_Slider::handle(e))
}
}
intmain(){
Fl_Double_Window*win=newFl_Double_Window(640,100)
MyValueSlider*val1=newMyValueSlider(20,20,200,30)
MyValueSlider*val2=newMyValueSlider(20,50,200,30)

http://seriss.com/people/erco/fltk/

17/88

8/11/2015

Erco'sFLTKCheatPage
win>show()
return(Fl::run())
}

ShowRealTimeOutputofChildProcessesinFl_Text_Display

Thefollowingisaunixexamplethatstartsthreechildprocesses,showingtheirrealtimeoutputinseparateFLTK
Fl_Text_Displaywidgets.AlsodemonstrateshowtouseFl::add_fd(),Fl::remove_fd(),andtheunixcallswaitpid(),fork(),
execlp()andpipe()alltogetherinoneexample.Whenthewindowisclosed,anychildprocessesthatwererunningarekilled
first.
Thedesignisthis:
OpenthreeFl_Text_Displaywidgets[seemain()]
Startthreeexternalprocessesthatgeneratetextonstdout[seestart_child()],andconfigureFLTKtoinvokeacallback[data_ready()]whenever
outputfromtheseprocessesisgenerated,sothedataisappendedtotheappropriateFl_Text_Displaywidgetinrealtime
SetupFLTKtoinvokeacallback[close_cb()]iftheappisclosed,sochildprocessesarefirstkilled,beforetheappexits(preventingorphaned
processes).

Astheprocessesrun,FLTK'seventloopinvokescallbackswheneverdataisgeneratedbythechildprocesses,thanksto
FLTK'sadd_fd()mechanism.TheFLTKeventloopalsohandlesallFLTKevents,suchaswhentheusermovesthescrollbars,
highlightstext,etc.
Thisisunixspecificcode.(Won'tworkonWindows)

FltkTtyexample
#include<sys/types.h>
#include<sys/wait.h>
#include<errno.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Text_Display.H>
//
//fltkttysOpenseveralprocesses,displaytheiroutputinfltkwidgets
//GregErcolano02/21/20051.00
//
//Globals
Fl_Text_Display*G_disp[3]//onedisplayperchild
Fl_Text_Buffer*G_buff[3]//onebufferperchild
intG_outfd[3]//readpipeforchild'sstderr,oneperchild
pid_tG_pids[3]//pidforeachchild
//Startchildprocess,makesareadpipetoitsstderr
voidstart_child(intt){
intout[2]pipe(out)
switch((G_pids[t]=fork())){
case1://Error
close(out[0])close(out[1])
perror("fork()")
exit(1)
case0://Child
close(out[0])dup2(out[1],2)close(out[1])
switch(t){
case0:execlp("/bin/sh","sh","c","psauxww1>&2",0)
perror("execlp(ps)")
exit(1)

http://seriss.com/people/erco/fltk/

18/88

8/11/2015

Erco'sFLTKCheatPage
case1:execlp("/bin/sh","sh","c","perle'for($t=0sleep(1)$t++)"
"{printSTDERRrand().\"\\n\"if($t>5){kill(9,$$)}}'1>&2",0)
perror("execlp(perl)")
exit(1)
case2:execlp("/bin/sh","sh","c","(lslapingc8localhost)1>&2",0)
perror("execlp(ls/ping)")
exit(1)
default:exit(1)
}
default://Parent
G_outfd[t]=out[0]close(out[1])
return
}
}
//Datareadyinterrupt
voiddata_ready(intfd,void*data){
intt=(int)data
chars[4096]
intbytes=read(fd,s,40961)
//fprintf(stderr,"Datareadyfor%d)pid=%ldfd=%dbytes=%d\n",t,(long)G_pids[t],fd,bytes)
if(bytes==1){//ERROR
perror("read()")
}elseif(bytes==0){//EOF
G_buff[t]>append("\n\n***EOF***\n")
intstatus
if(waitpid(G_pids[t],&status,WNOHANG)<0){
sprintf(s,"waitpid():%s\n",strerror(errno))
}else{
if(WIFEXITED(status)){
sprintf(s,"Exit=%d\n",WEXITSTATUS(status))
close(fd)Fl::remove_fd(fd)G_pids[t]=1
}elseif(WIFSIGNALED(status)){
sprintf(s,"Killedwith%d\n",WTERMSIG(status))
close(fd)Fl::remove_fd(fd)G_pids[t]=1
}elseif(WIFSTOPPED(status)){
sprintf(s,"Stoppedwith%d\n",WSTOPSIG(status))
}
}
G_buff[t]>append(s)
}else{//DATA
s[bytes]=0
G_buff[t]>append(s)
}
}
//Cleanupifsomeoneclosesthewindow
voidclose_cb(Fl_Widget*,void*){
printf("Killingchildprocesses..\n")
for(intt=0t<3t++){
if(G_pids[t]==1)continue
kill(G_pids[t],9)
}
printf("Done.\n")
exit(0)
}
intmain(){
Fl_Double_Windowwin(620,520,"fltktty")
win.callback(close_cb)//killchildrenifwindowclosed
//Startchildren,onettyforeach
for(intt=0t<3t++){
start_child(t)
G_buff[t]=newFl_Text_Buffer()
G_disp[t]=newFl_Text_Display(10+t*200,10,200,500)
G_disp[t]>buffer(G_buff[t])
G_disp[t]>textfont(FL_COURIER)
G_disp[t]>textsize(12)
Fl::add_fd(G_outfd[t],data_ready,(void*)t)
}
win.resizable(win)
win.show()
return(Fl::run())
}

Showhowtodrawasimple'X'inFLTK

Here'showtomakeyourownFLTKwidgetthatjustdrawsasimple'X'toallfourcorners.Youcanresizethewindow,andtheX
http://seriss.com/people/erco/fltk/

19/88

8/11/2015

Erco'sFLTKCheatPage

changeswithit.Thisisagoodstartingpointforanyonewantingtomakeacustomwidgetthatdoesitsowndrawing,suchasa
graph.
Thisexampleusesfltk'sownbuiltindrawingroutines,whichusesthewindowmanager'ssimplenativedrawingfunctions,not
OpenGL.Soitshouldworkoneventhesimplestgraphicsheads.(ForanOpenGLexample,clickhere)

Example:Draw'X'
//DEMONSTRATEHOWTODRAWAN'X'INFLTK
#include<FL/Fl.H>
#include<FL/fl_draw.H>
#include<FL/Fl_Double_Window.H>
//SIMPLEWIDGETTHATDRAWSAN'X'
classDrawX:publicFl_Widget{
public:
DrawX(intX,intY,intW,intH,constchar*L=0):Fl_Widget(X,Y,W,H,L){
}
voiddraw(){
//DRAWBLACK'X'
fl_color(FL_BLACK)
intx1=x(),y1=y()
intx2=x()+w()1,y2=y()+h()1
fl_line(x1,y1,x2,y2)
fl_line(x1,y2,x2,y1)
}
}
intmain(){
Fl_Double_Windowwin(200,200,"DrawX")
DrawXdraw_x(0,0,win.w(),win.h())
win.resizable(draw_x)
win.show()
return(Fl::run())
}

HowtomakeaScrollable'Canvas'

AscrollableversionofthesimpleFLTKwidgetthatjustdrawsan'X'.Scrollersletyoupanaroundtolookatthe"canvas"
drawingofthe'X'.

Example:AScrollableCustomWidget"Canvas"
//DEMONSTRATEHOWTOMAKEASCROLLABLE"CANVAS"DRAWINGOFAN'X'
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Scroll.H>
#include<FL/fl_draw.H>
//SCROLLABLECANVASEXAMPLEJUSTDRAWSAN'X'
classMyCanvas:publicFl_Widget{
public:
MyCanvas(intX,intY,intW,intH,constchar*L=0):Fl_Widget(X,Y,W,H,L){
}
voiddraw(){
//DRAWBG
fl_color(color())
fl_rectf(x(),y(),w(),h())
//DRAW'X'OVERBG
//Doyourgraphicshere..
//
intx1=x(),y1=y()//Fl_Scrollworksbychangingourwidget'sx()andy(),
intx2=x()+w()1,y2=y()+h()1//sotaketheseintoaccountforourdrawingcoordinates
fl_color(FL_BLACK)
fl_line(x1,y1,x2,y2)
fl_line(x1,y2,x2,y1)
}
}
intmain(){
Fl_Double_Windowwin(200,200)
Fl_Scrollscroll(0,0,200,200)

http://seriss.com/people/erco/fltk/

20/88

8/11/2015

Erco'sFLTKCheatPage
MyCanvascanvas(0,0,350,350)//purposelymakedrawingarealargerthanscroll
scroll.end()
win.end()
win.resizable(canvas)
win.show()
return(Fl::run())
}

Showhowtodrawacustombargraph

ThefollowingisanexampleIpostedtothenewsgroup,inresponsetoarequestforaveryspecific'triggershaped'bargraphto
appearintheleftcornerofanelipticalLCDscreen.

Example:Custom'TriggerShaped'BarGraph
//DEMONSTRATEHOWTODRAWATRIGGERSHAPEDBARGRAPH
#include<stdlib.h>
#include<math.h>
#include<FL/Fl.H>
#include<FL/fl_draw.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Group.H>
//LEDDISPLAYCLASS
classMyDisplay:publicFl_Group{
int_value//0100
public:
MyDisplay(intX,intY,intW,intH,constchar*L=0):Fl_Group(X,Y,W,H,L){
_value=0
}
voidvalue(intval){
_value=val
redraw()
}
voiddraw(){
Fl_Group::draw()
//TRIGGERGRAPHICDRAWINGCODE
fl_color(42)
intw=1
for(intt=0t<_valuet+=2){
floatf=(t/100.0)//f=0.0~1.0
floatf2=(abs(t50)/100.0)//f=.5~0~.5
intxoff=(int)(f2*f2*100+.5)
w+=1
intx1=x()+10+xoff
intx2=x()+10+w+xoff
inty1=y()+h()10t
fl_line(x1,y1,x2,y1)
}
}
}
//
//TESTTHECLASSSendasinewavetotheclassoffatimer
//
MyDisplay*disp=0
voidTimer_CB(void*){
staticfloatf=6.28/4f+=.1
floatv=(sin(f)+1.0)*.5//sinewave:0~1
v=v*100//sinewave:0~100
disp>value((int)(v+.5))
Fl::repeat_timeout(0.03,Timer_CB)
}
intmain(){
Fl_Double_Windowwin(240,240)
disp=newMyDisplay(20,20,24040,24040)
disp>box(FL_BORDER_BOX)
disp>value(100)
Fl::add_timeout(1.0,Timer_CB)
win.show()
return(Fl::run())
}

CellTable

http://seriss.com/people/erco/fltk/

21/88

8/11/2015

Erco'sFLTKCheatPage

AtableofFl_Box,Fl_InputandFl_Float_Inputwidgets.
Youcanchangeboththesizeofthewindow,andinteractively
resizetheindividualcellrowsandcolumns.

AnexampleshowinghowonecancreateatableofcellsusingsimpleFLTKwidgets,withoutneedinganFl_Table.

Example:TableofCells
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Scroll.H>
#include<FL/Fl_Tile.H>
#include<FL/Fl_Box.H>
#include<FL/Fl_Input.H>
#include<FL/Fl_Float_Input.H>
//
//DemonstratecreatingatableofwidgetswithoutFl_Table
//ercoMar82005
#defineCOLS9
#defineROWS20
classRateTable:publicFl_Scroll{
void*w[ROWS][COLS]//widgetpointers
public:
RateTable(intX,intY,intW,intH,constchar*L=0):Fl_Scroll(X,Y,W,H,L){
staticconstchar*header[COLS]={
"Time","InRate","OutRate","CoeffA",
"CoeffB","CoeffC","StdDev","PkgIn","PkgOut"
}
intcellw=80
intcellh=25
intxx=X,yy=Y
Fl_Tile*tile=newFl_Tile(X,Y,cellw*COLS,cellh*ROWS)
//Createwidgets
for(intr=0r<ROWSr++){
for(intc=0c<COLSc++){
if(r==0){
Fl_Box*box=newFl_Box(xx,yy,cellw,cellh,header[c])
box>box(FL_BORDER_BOX)
w[r][c]=(void*)box
}elseif(c==0){
Fl_Input*in=newFl_Input(xx,yy,cellw,cellh)
in>box(FL_BORDER_BOX)
in>value("")
w[r][c]=(void*)in
}else{
Fl_Float_Input*in=newFl_Float_Input(xx,yy,cellw,cellh)
in>box(FL_BORDER_BOX)
in>value("0.00")
w[r][c]=(void*)in
}
xx+=cellw
}
xx=X
yy+=cellh
}
tile>end()
end()
}
}
intmain(){
Fl_Double_Windowwin(720,486)
RateTablerate(10,10,72020,48620)
win.resizable(win)
win.show()
return(Fl::run())
}

http://seriss.com/people/erco/fltk/

22/88

8/11/2015

Erco'sFLTKCheatPage

DraggableBoxesonScrollableDesk

Ascrollable'desk'containingboxestheusercanclicktodragaround.

Demonstrateshowtomakeboxes(containingimages)thattheusercanclicktodragaroundonascrollabledesktop.
Justclickanddragthecatboxesaround..notethatwhenyoudragaboxofftheedgeofthe'desktop',scrollbarsappear,soyou
canscrollaroundthedesktoptoviewalltheboxes.
AlloftheworkisdonebyFLTK..onlyafewlinesofcustomcode(showninred)areneededtomaketheboxes'draggable'.

Example:DraggableBoxesonaScrollableDesk
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Scroll.H>
#include<FL/Fl_Box.H>
#include<FL/Fl_Pixmap.H>
#include<stdio.h>
//
//Demonstrateusermovableboxesinascrollregion
//erco@netcom.com08/06/02
//erco@3dsite.com01/06/05addedcalltoFl_Box::handle()
//
staticchar*cat_xpm[]={//XPM
"503441",
"cblack",
"oc#ff9900",
"@c#ffffff",
"#cNone",
"##################################################",
"#####################################",
"###ooooo###########################ooooo####",
"###oooo#########################oooo####",
"###oooo#######################oooo####",
"###oooo#####################oooo####",
"###oooo###################oooo####",
"###oooooooo####",
"###ooooooooooooooooooooooo####",
"###ooooooooooooooooooooooooo####",
"###oooooooooooooooooooooooooooooooo####",
"####ooooooooooooooooooooooooooooooo#####",
"####ooooooooooooooooooooooooooooooooo#####",
"#####ooooooooooooooooooooooooooooooooo######",
"#####ooooooooooooooooooooooooooooooooo######",
"######ooooooooooooooooooooooooooooooooooo#######",
"#####ooooooooooooooooooooooooooo######",
"#####oooooooo@@@ooooooo@@@oooooooo######",
"#####oooooooo@@@@@ooooooo@@@@@oooooooo######",
"#####oooooooo@@@@@ooooooo@@@@@oooooooo######",
"#####oooooooo@@@ooooooo@@@oooooooo######",
"#####ooooooooooooooooooooooooooo######",
"######oooooooooooooooooooooooooooo#######",
"######oooooooo@@@@@@@@@@@@@@oooooooo#######",
"######ooooooo@@@@@@@@@@@@@@@@@@ooooooo#######",
"#######ooooo@@@@@@@@@@@@@@@@@@@@@@ooooo########",
"#########oo@@@@@@@@@@@@@@@@@@@@@@@@oo##########",
"##########o@@@@@@@@@@@@@@@@@@@@@@o###########",
"###########@@@@@@@@@@@@@@@############",
"############@@@@@@@@@@@@@@@@@@@@@#############",
"##############@@@@@@@@@@@@@@@@@###############",
"################@@@@@@@@@#################",
"#########################################",
"##################################################",
}
Fl_Double_Window*G_win=NULL
Fl_Scroll*G_scroll=NULL
staticFl_PixmapG_cat(cat_xpm)
#defineBOXWIDTH80
#defineBOXHEIGHT50
//A'MOVABLE'BOX
classBox:publicFl_Box{

http://seriss.com/people/erco/fltk/

23/88

8/11/2015

Erco'sFLTKCheatPage
protected:
inthandle(inte){
staticintoffset[2]={0,0}
intret=Fl_Box::handle(e)
switch(e){
caseFL_PUSH:
offset[0]=x()Fl::event_x()//savewhereuserclickedfordragging
offset[1]=y()Fl::event_y()
return(1)
caseFL_RELEASE:
return(1)
caseFL_DRAG:
position(offset[0]+Fl::event_x(),offset[1]+Fl::event_y())//handledragging
G_win>redraw()
return(1)
}
return(ret)
}
public:
Box(intX,intY,intW,intH,constchar*L=0):Fl_Box(X,Y,W,H,L){
image(G_cat)
box(FL_UP_BOX)
color(FL_GRAY)
}
Box(intX,intY):Fl_Box(X,Y,BOXWIDTH,BOXHEIGHT,0){
image(G_cat)
box(FL_UP_BOX)
color(FL_GRAY)
}
}
///MAIN
intmain(){
G_win=newFl_Double_Window(420,300)
G_scroll=newFl_Scroll(10,10,42020,30020)
G_scroll>box(FL_FLAT_BOX)
G_scroll>color(Fl_Color(46))
G_scroll>begin()
{
//CREATENEWBOXESONTHESCROLLABLE'DESK'
for(intx=20x<=G_scroll>w()BOXWIDTHx+=BOXWIDTH+20)
for(inty=20y<=G_scroll>h()BOXHEIGHTy+=BOXHEIGHT+20)
newBox(x,y)
}
G_scroll>end()
G_win>resizable(G_win)
G_win>show()
return(Fl::run())
}

PopupMenuExample
Demonstrateshowtomakeapopupmenuappear,sotheusercanchooseanitem,andcauseacallbackandreturnthe
menuitem.
Twoexamplesbelowshowingdoingapopupmenuwith,andwithoutcallbacks.Sometimespopupmenusaresimpleenough
thatallthefunctionscanbedonewithinasingleprocedure,avoidingtheneedforseparatecallbacks.

Example:PopupMenu(withcallbacks)
//Popupmenuusingcallbackserco
#include<FL/Fl.H>
#include<FL/fl_ask.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Menu.H>
#include<stdio.h>
//Callbackinvokedwhenmenuitemselected
voidhandle_menu(Fl_Widget*w,void*v){
if(!w||!v)return
switch((int)v){
case1:fl_choice("Thing1happened","OK",NULL,NULL)break
case2:fl_choice("Thing2happened","OK",NULL,NULL)break
case3:fl_choice("Thing3happened","OK",NULL,NULL)break
}
}
//Callbackinvokedwhenbuttonpushed
voidpush_cb(Fl_Widget*w,void*){
Fl_Menu_Itemrclick_menu[]={
{"DoThing1",0,handle_menu,(void*)1},
{"DoThing2",0,handle_menu,(void*)2},
{"DoThing3",0,handle_menu,(void*)3},
{0}
}
constFl_Menu_Item*m=rclick_menu>popup(Fl::event_x(),Fl::event_y(),0,0,0)
if(m)m>do_callback(w,m>user_data())
return
}
intmain(){
Fl_Windowwin(140,45,"SimplePopupMenu(usingcallbacks)")
Fl_Buttonbutt(10,10,120,25,"PushForMenu")
butt.callback(push_cb)
win.show()
return(Fl::run())
}

http://seriss.com/people/erco/fltk/

24/88

8/11/2015

Erco'sFLTKCheatPage

Example:PopupMenu(WITHOUTcallbacks)
//PopupmenuWITHOUTcallbackserco09/07/09
#include<FL/Fl.H>
#include<FL/fl_ask.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Menu.H>
#include<stdio.h>
//Callbackinvokedwhenbuttonpushed
voidpush_cb(Fl_Widget*w,void*){
Fl_Menu_Itemrclick_menu[]={
{"DoThing1"},
{"DoThing2"},
{"DoThing3"},
{0}
}
constFl_Menu_Item*m=rclick_menu>popup(Fl::event_x(),Fl::event_y(),0,0,0)
if(!m){
return
}elseif(strcmp(m>label(),"DoThing1")==0){
fl_choice("Thing1happened","OK",NULL,NULL)
}elseif(strcmp(m>label(),"DoThing2")==0){
fl_choice("Thing2happened","OK",NULL,NULL)
}elseif(strcmp(m>label(),"DoThing3")==0){
fl_choice("Thing3happened","OK",NULL,NULL)
}
return
}
intmain(){
Fl_Windowwin(140,45,"SimplePopupMenu(Nocallbacks)")
Fl_Buttonbutt(10,10,120,25,"PushForMenu")
butt.callback(push_cb)
win.show()
return(Fl::run())
}

RightClickPopupCopy/PasteMenuforFl_Input

Demonstrateshowtomakeapopupcopy/pastemenuappearoveranFl_Inputwidget.
There'sprobablyalotofwaystodothisthisisprobablythemostexplicit.

Example:RightClickPopupCopy/PasteMenuforFl_Input
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Input.H>
#include<FL/Fl_Menu.H>
#include<stdio.h>//printf
//
//Howtoimplementacopy/pastemenuforFl_Inputerco02/04/09
//
classMyInput:publicFl_Input{
staticvoidCopy_CB(Fl_Widget*,void*userdata){
printf("***COPY***\n")
MyInput*in=(MyInput*)userdata
in>copy(0)//textselectionclipboard
in>copy(1)//copy/pasteclipboard
}
staticvoidPaste_CB(Fl_Widget*,void*userdata){
printf("***PASTE***\n")
MyInput*in=(MyInput*)userdata
Fl::paste(*in,1)//09/03/2013fix:added",1"tohelppastefrome.g.notepad
}
public:
inthandle(inte){
switch(e){
caseFL_PUSH:
//RIGHTMOUSEPUSHED?Popupmenuonrightclick
if(Fl::event_button()==FL_RIGHT_MOUSE){
Fl_Menu_Itemrclick_menu[]={
{"Copy",0,Copy_CB,(void*)this},
{"Paste",0,Paste_CB,(void*)this},
{0}
}
constFl_Menu_Item*m=rclick_menu>popup(Fl::event_x(),Fl::event_y(),0,0,0)
if(m)m>do_callback(0,m>user_data())
return(1)//(tellscallerwehandledthisevent)
}
break
caseFL_RELEASE:
//RIGHTMOUSERELEASED?MaskitfromFl_Input
if(Fl::event_button()==FL_RIGHT_MOUSE){

http://seriss.com/people/erco/fltk/

25/88

8/11/2015

Erco'sFLTKCheatPage
return(1)//(tellscallerwehandledthisevent)
}
break
}
return(Fl_Input::handle(e))//letFl_Inputhandleallotherevents
}
MyInput(intX,intY,intW,intH,constchar*L=0):Fl_Input(X,Y,W,H,L){
}
}
intmain(){
Fl_Windowwin(200,45,"Test")
MyInputinput(50,10,120,25,"Text:")
win.show()
return(Fl::run())
}

PopupTextWindow

Demonstrateshowtopopupaborderlesstextmessagewindowwhenuserclicksanywhereinthewindow.

Example:PopupTextWindow
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Box.H>
#include<FL/Fl_Menu_Window.H>
#include<FL/fl_draw.H>
#include<stdio.h>
//
//Demonstratehowtopopupasimplewindowofinformation
//erco1.101/04/06
//
classPopupWindow:publicFl_Menu_Window{
Fl_Box*output
//Sizewindowtojustfitoutput'slabeltext
voidSizeToText(){
intW=0,H=0
fl_font(output>labelfont(),output>labelsize())
fl_measure(output>label(),W,H,0)
resize(x(),y(),W+10,H+10)//+10:leaves+5marginonallsides
output>resize(0,0,W+10,H+10)
}
public:
PopupWindow():Fl_Menu_Window(10,10){
output=newFl_Box(0,0,w(),h())//boxwillhavethetextofuser'smsg
output>box(FL_UP_BOX)//popupwindowwillhavean'UpBox'border
end()
hide()
border(0)//popupwillbeborderless
output>align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)//textshouldbeleftaligned
output>label("Notextdefined")//(defaultmsgifnonedefined)
SizeToText()
}
//Changetextinbox
voidtext(constchar*s){
output>label(s)//setmessagetext
SizeToText()//resizewindowtosizeoftext
}
//Popupwindowatcurrentmouseposition
voidpopup(){
position(Fl::event_x_root(),Fl::event_y_root())//positionwindowatcursor
show()
}
}
//Awindowwheremouseeventspopsopentextmessages
classMyWindow:publicFl_Window{
PopupWindow*popup

http://seriss.com/people/erco/fltk/

26/88

8/11/2015

Erco'sFLTKCheatPage
inthandle(inte){
intret=Fl_Window::handle(e)
switch(e){
caseFL_PUSH:popup>popup()return(1)
caseFL_RELEASE:popup>hide()return(1)
}
return(ret)
}
public:
MyWindow(intw,inth):Fl_Window(w,h){
popup=newPopupWindow()
popup>text("Thisisatest\nSoisthis,amuchlongerlineoftext.")
end()
}
}
intmain(intargc,char**argv){
MyWindowwin(300,300)
win.show()
return(Fl::run())
}

DrawMouseCoordinatesExample

Screenshowsx/ycoordsofmouseinupperleft,whilelargefontshowsthefull
screen'sredrawcounttoshowthattheentirescreenisnotbeingredrawnasthe
mouseismoved.

Demonstrateshowtodrawthecoordinatesofamouseintoawindowwithoutcausingtheentirescreentoredraw,withoutusing
overlayplanes,separatewidgetsorwindowsforthecoordinates.
IlikedHartmut'sideaofonlydrawingthecoordsoverthegraphic,avoidingoverlaysandcompleteredraws,whilestillupdating
thecoordsINthescreenarea,anddoingitfast.
Here'sacutetechniqueabusingdamage(FL_DAMAGE_USER1),toavoidthewholeproblemofkeepingaseparate'flag'.This
worksintheknowledgethatsettingthedamageflagalsocausesaredraw,andtheflaggetsORedwithotherbitsifotherkinds
ofdamageoccur.
Notethatthemainscreengraphiccountstheredraws,soyoucanseewhenevertheentirescreenisredrawn.Whilemoving
aroundthemouse,/only/thecoordswillchange,showingentireredrawsarebeingavoided.
Togetthescreentofullyredraw,youcanresizethescreen,oronsomewindowmanagers,overlayingthenrevealingagainwill
countitup.

Example:DrawingMouseCoordinatesWithoutRedrawingEntireScreen
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Group.H>
#include<FL/fl_draw.H>
#include<stdio.h>
//Demonstratedrawingmousecoords:
//ow/outredrawingentirescreen
//ow/outusingoverlayplanesorwindows
//ow/outusingXORmode
classMyDesk:publicFl_Group{
protected:
inthandle(inte){
intret=Fl_Group::handle(e)
switch(e){
caseFL_ENTER:
ret=1//FL_ENTER:mustreturn(1)toreceiveFL_MOVE
break

http://seriss.com/people/erco/fltk/

27/88

8/11/2015

Erco'sFLTKCheatPage
caseFL_MOVE://FL_MOVE:mousemovementcauses'userdamage'andredraw..
damage(FL_DAMAGE_USER1)
ret=1
break
}
return(ret)
}
//Drawmousecoordsinsmallblackrectangle
voiddraw_coords(){
//Coordinatesasastring
chars[80]
sprintf(s,"x=%dy=%d",(int)Fl::event_x(),(int)Fl::event_y())
//Blackrect
fl_color(FL_BLACK)
fl_rectf(10,10,200,25)
//Whitetext
fl_color(FL_WHITE)
fl_font(FL_HELVETICA,18)
fl_draw(s,15,25)
}
voiddraw(){
//UserdamageONLY?justdrawcoordsanddone
if(damage()==FL_DAMAGE_USER1){
draw_coords()
return
}
//Letgroupdrawitself
Fl_Group::draw()
{
//Showredrawcount,sowecantellwhenfullredrawsoccur.
staticintredraws=0
chars[80]sprintf(s,"redraw#%d",++redraws)
fl_color(FL_BLACK)
fl_font(FL_COURIER,80)
fl_draw(s,50,h()/2)
}
//Drawcoordslast
draw_coords()
}
public:
MyDesk(intX,intY,intW,intH,constchar*L=0):Fl_Group(X,Y,W,H,L){
color(48)
}
}
///MAIN
intmain(){
Fl_Windowwin(720,486)
MyDeskdesk(10,10,700,466)
win.resizable(win)
win.show()
return(Fl::run())
}

ProgressBarExample

Progressbar

Demonstrateshowtoupdateaprogressbarwithinacpuintensiveoperation.

Example:ProgressBarDemonstration
#include<stdio.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Progress.H>
//Demonstrateprogressbarinappwindow(windows|linux)
//erco05/02/05
#ifdef_WIN32
//WINDOWS
#include<windows.h>
#defineusleep(v)Sleep(v/1000)
#else
//UNIX
#include<unistd.h>//usleep
#endif
//Buttoncallback
voidbutt_cb(Fl_Widget*butt,void*data){

http://seriss.com/people/erco/fltk/

28/88

8/11/2015

Erco'sFLTKCheatPage
//Deactivatethebutton
butt>deactivate()//preventbuttonfrombeingpressedagain
Fl::check()//givefltksomecputograyoutbutton
//Maketheprogressbar
Fl_Window*w=(Fl_Window*)data//accessparentwindow
w>begin()//addprogressbartoit..
Fl_Progress*progress=newFl_Progress(10,50,200,30)
progress>minimum(0)//setprogressrangetobe0.0~1.0
progress>maximum(1)
progress>color(0x88888800)//backgroundcolor
progress>selection_color(0x4444ff00)//progressbarcolor
progress>labelcolor(FL_WHITE)//percenttextcolor
w>end()//endaddingtowindow
//Computationloop..
for(intt=1t<=500t++){
progress>value(t/500.0)//updateprogressbarwith0.0~1.0value
charpercent[10]
sprintf(percent,"%d%%",int((t/500.0)*100.0))
progress>label(percent)//updateprogressbar'slabel
Fl::check()//givefltksomecputoupdatethescreen
usleep(1000)//'yourstuff'that'scomputeintensive
}
//Cleanup
w>remove(progress)//removeprogressbarfromwindow
delete(progress)//deallocateit
butt>activate()//reactivatebutton
w>redraw()//tellwindowtoredrawnowthatprogressremoved
}
//Main
intmain(){
Fl_Windowwin(220,90)
Fl_Buttonbutt(10,10,100,25,"Press")
butt.callback(butt_cb,&win)
win.resizable(win)
win.show()
return(Fl::run())
}

ScrollableImageViewer
Demonstrateshowtodisplayanimageinascrollablewindow.

Example:ScrollableImageViewer
#include<stdio.h>
#include<stdlib.h>
#include<FL/Fl.H>
#include<FL/Fl_Shared_Image.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Scroll.H>
#include<FL/Fl_JPEG_Image.H>
#include<FL/Fl_Box.H>
#defineJPGFILE"/var/tmp/foo.jpg"
//Showajpgimageinascrolledwindowerco05/07/2005
intmain(){
fl_register_images()
Fl_Double_Windowwin(720,486)
Fl_Scrollscr(0,0,720,486)
Fl_JPEG_Imagejpg(JPGFILE)
if(jpg.h()==0){perror(JPGFILE)exit(1)}//errorcheck
Fl_Boxbox(0,0,jpg.w(),jpg.h())
box.image(jpg)
win.resizable(win)
win.show()
return(Fl::run())
}

ScrollableWidgetBrowser
Demonstrateshowtomakeascrollablebrowserofwidgetswherechildrenofthescrollfollowachangeinsizeofthescroller.

Example:Scrollablewidget'browser'
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Group.H>
#include<FL/Fl_Scroll.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Box.H>
//demonstrateascrollablebrowserofwidgetswherechildrenfollowsize
//erco05/20/05

http://seriss.com/people/erco/fltk/

29/88

8/11/2015

Erco'sFLTKCheatPage
//
//dialog
//
//|scroll|
//||
//||fixed|stretch|^||
//||_________|________________________|||
//||fixed|stretch|||
//||_________|________________________|||
//||fixed|stretch|||
//||_________|________________________|||
//||fixed|stretch|||
//||_________|________________________|__||
//||__________________________________|v||
//||
//|_______|
//||ADD||
//||
//|___________________________________________|
//
constintfixedWidth=50
constintdefaultHeight=25
//Combowidgettoappearinthescroll,twoboxes:onefixed,theotherstretches
classScrollItem:publicFl_Group{
Fl_Box*fixedBox
Fl_Box*stretchBox
public:
ScrollItem(intX,intY,intW,intH,constchar*L=0):Fl_Group(X,Y,W,H,L){
begin()
//Fixedwidthbox
fixedBox=newFl_Box(X,Y,fixedWidth,defaultHeight,"Fixed")
fixedBox>box(FL_UP_BOX)
//Stretchybox
stretchBox=newFl_Box(X+fixedWidth,Y,WfixedWidth,defaultHeight,"Stretch")
stretchBox>box(FL_UP_BOX)
resizable(stretchBox)
end()
}
}
//Customscrollthattellschildrentofollowscroll'swidthwhenresized
classMyScroll:publicFl_Scroll{
intnchild
public:
MyScroll(intX,intY,intW,intH,constchar*L=0):Fl_Scroll(X,Y,W,H,L){
nchild=0
}
voidresize(intX,intY,intW,intH){
//Tellchildrentoresizetoournewwidth
for(intt=0t<nchildt++){
Fl_Widget*w=child(t)
w>resize(w>x(),w>y(),W20,w>h())//W20:leaveroomforscrollbar
}
//Tellscrollchildrenchangedinsize
init_sizes()
Fl_Scroll::resize(X,Y,W,H)
}

//Appendnewscrollitemtobottom
//Note:AnFl_Packwouldbeagoodwaytodothis,too
//
voidAddItem(){
intX=x()+1,
Y=y()yposition()+(nchild*defaultHeight)+1,
W=w()20,//20:compensateforvscrollbar
H=defaultHeight
add(newScrollItem(X,Y,W,H))
redraw()
nchild++
}
}
//Callbacktoaddnewitemtoscroll
voidadd_cb(Fl_Widget*,void*data){
MyScroll*scroll=(MyScroll*)data
scroll>AddItem()
}
//Main
intmain(){
Fl_Double_Window*win=newFl_Double_Window(300,300)
MyScroll*scroll=newMyScroll(10,10,win>w()20,win>h()60)
scroll>box(FL_BORDER_BOX)
scroll>end()
Fl_Button*add_butt=newFl_Button(win>w()150,win>h()40,100,25,"Add")
add_butt>callback(add_cb,(void*)scroll)
//Createafewwidgetstostartwith
for(intt=0t<4t++){
scroll>AddItem()
}
win>resizable(scroll)
win>show()
return(Fl::run())
}

HowToGloballyDisable@Symbols
http://seriss.com/people/erco/fltk/

30/88

8/11/2015

Erco'sFLTKCheatPage

DisableSymbolsGlobally

Demonstrateshowtogloballydisablefltk's'@'symbolsthroughoutyourapp.Alsoshowshowtodefineyourowngloballabel
drawingcode.

Example:DisableSymbols
//
//ExampleshowinghowtodisableFLTKsymbolsglobally
//erco05/31/2005
//
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Choice.H>
#include<FL/Fl_Button.H>
#include<FL/fl_draw.H>
staticintG_usesymbols=1
//GlobalFLTKcallbackfordrawingalllabeltext
voidMyDraw(constFl_Label*o,intX,intY,intW,intH,Fl_Aligna){
fl_font(o>font,o>size)
fl_color((Fl_Color)o>color)
fl_draw(o>value,X,Y,W,H,a,o>image,G_usesymbols)
}
//GlobalFLTKcallbackformeasuringalllabels
voidMyMeasure(constFl_Label*o,int&W,int&H){
fl_font(o>font,o>size)
fl_measure(o>value,W,H,G_usesymbols)
}
//Turnsymbolsonoroff
voidFltkUseSymbols(intonoff){
G_usesymbols=onoff
Fl::set_labeltype(FL_NORMAL_LABEL,MyDraw,MyMeasure)//realactionhere
}
//Buttoncallbacktotogglesymbolson/off
voidButton_CB(Fl_Widget*,void*data){
FltkUseSymbols(G_usesymbols?0:1)
Fl_Window*win=(Fl_Window*)datawin>redraw()
}
intmain(){
Fl_Double_Windowwin(0,0,300,100)
Fl_Choicechoice(110,10,120,25,"Email@3Dsite")
choice.add("abc@>")
choice.add("ABC@<")
choice.value(0)
Fl_Buttonbutt(100,45,130,25,"ToggleSymbols")
butt.callback(Button_CB,(void*)&win)
win.resizable(win)
win.show()
return(Fl::run())
}

OpenGLSimpleExample

http://seriss.com/people/erco/fltk/

31/88

8/11/2015

Erco'sFLTKCheatPage

DemonstratesthesimplestOpenGLexample,drawingasimple'X'.

Example:OpenGLSimpleExample
#include<FL/Fl.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/gl.h>
//
//Simpleresizable2DGLwindow
//erco10/08/05
//
classMyGlWindow:publicFl_Gl_Window{
//DRAWMETHOD
//OpenGLwindow:(w,h)isupperright,(w,h)islowerleft,(0,0)iscenter
//
voiddraw(){
//Viewportnotvalid?Initviewport,ortho,etc.
if(!valid()){
glLoadIdentity()
glViewport(0,0,w(),h())
glOrtho(w(),w(),h(),h(),1,1)
}
//Clearscreen
glClear(GL_COLOR_BUFFER_BIT)
//Drawwhite'X'
glColor3f(1.0,1.0,1.0)
glBegin(GL_LINE_STRIP)glVertex2f(w(),h())glVertex2f(w(),h())glEnd()
glBegin(GL_LINE_STRIP)glVertex2f(w(),h())glVertex2f(w(),h())glEnd()
}
public:
//CONSTRUCTOR
MyGlWindow(intX,intY,intW,intH,constchar*L=0):Fl_Gl_Window(X,Y,W,H,L){
}
}
//MAIN
intmain(){
Fl_Windowwin(500,300,"OpenGLX")
MyGlWindowmygl(10,10,win.w()20,win.h()20)
win.end()
win.resizable(mygl)
win.show()
return(Fl::run())
}

OpenGLExamplewithWidgets

http://seriss.com/people/erco/fltk/

32/88

8/11/2015

Erco'sFLTKCheatPage

DemonstratesasimpleOpenGLapplicationthatincludesFLTKwidgetstocontrolthebrightnessoftheOpenGL'scontents(an
'X').

Example:OpenGLApplicationWithWidgets
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Value_Slider.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/gl.h>
//
//OpenGLAppWithFLTKWidgets
//erco11/08/06
//
//OPENGLWINDOWCLASS
classMyGlWindow:publicFl_Gl_Window{
doublefg//foregroundbrightness
doublebg//backgroundbrightness
//FIXOPENGLVIEWPORT
//Dothisoninitorwhenwindow'ssizeischanged
voidFixViewport(intW,intH){
glLoadIdentity()
glViewport(0,0,W,H)
glOrtho(W,W,H,H,1,1)
}
//DRAWMETHOD
voiddraw(){
if(!valid()){valid(1)FixViewport(w(),h())}//firsttime?init
//Clearscreentobgcolor
glClearColor(bg,bg,bg,0.0)
glClear(GL_COLOR_BUFFER_BIT)
//Draw'X'infgcolor
glColor3f(fg,fg,fg)
glBegin(GL_LINE_STRIP)glVertex2f(w(),h())glVertex2f(w(),h())glEnd()
glBegin(GL_LINE_STRIP)glVertex2f(w(),h())glVertex2f(w(),h())glEnd()
}
//HANDLEWINDOWRESIZING
voidresize(intX,intY,intW,intH){
Fl_Gl_Window::resize(X,Y,W,H)
FixViewport(W,H)
redraw()
}
public:
//OPENGLWINDOWCONSTRUCTOR
MyGlWindow(intX,intY,intW,intH,constchar*L=0):Fl_Gl_Window(X,Y,W,H,L){
fg=1.0
bg=0.0
end()
}
voidSetBrightness(doublenew_fg,doublenew_bg)
{fg=new_fgbg=new_bgredraw()}
}
//APPWINDOWCLASS
classMyAppWindow:publicFl_Window{
MyGlWindow*mygl//openglwindow
Fl_Value_Slider*fg_bright//fgbrightnessslider
Fl_Value_Slider*bg_bright//bgbrightnessslider
private:
//Someonechangedoneofthesliders
voidValueChanged_CB2(){
mygl>SetBrightness(fg_bright>value(),bg_bright>value())
}
staticvoidValueChanged_CB(Fl_Widget*,void*userdata){
MyAppWindow*appwin=(MyAppWindow*)userdata
appwin>ValueChanged_CB2()
}
public:
//APPWINDOWCONSTRUCTOR
MyAppWindow(intW,intH,constchar*L=0):Fl_Window(W,H,L){
//OpenGLwindow
mygl=newMyGlWindow(10,10,w()20,h()80)
//Foregroundslider
fg_bright=newFl_Value_Slider(120,h()60,w()/2,20,"FGBright")
fg_bright>align(FL_ALIGN_LEFT)

http://seriss.com/people/erco/fltk/

33/88

8/11/2015

Erco'sFLTKCheatPage
fg_bright>type(FL_HOR_SLIDER)
fg_bright>bounds(0.0,1.0)
fg_bright>value(1.0)
fg_bright>callback(ValueChanged_CB,(void*)this)
//Backgroundslider
bg_bright=newFl_Value_Slider(120,h()30,w()/2,20,"BGBright")
bg_bright>align(FL_ALIGN_LEFT)
bg_bright>type(FL_HOR_SLIDER)
bg_bright>bounds(0.0,1.0)
bg_bright>value(0.0)
bg_bright>callback(ValueChanged_CB,(void*)this)
end()
}
}
//MAIN
intmain(){
MyAppWindowwin(500,300,"OpenGLTestApp")
win.resizable(win)
win.show()
return(Fl::run())
}

OpenGLShapeInterpolation

Demonstrateshowtoanimatesimpleshapeinterpolationinopengl,usinga24fpstimertoruntheanimationsmoothly.(Image
aboveshowsonlyafewframestogivearoughideaofthedemo)

Example:SimpleOpenGLShapeInterpolation
#include<FL/Fl.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/gl.h>
#include<math.h>
//
//Demonstrateinterpolatingshapes
//erco06/10/05
//
classPlayback:publicFl_Gl_Window{
intframe
//Linearinterpolationbetweentwovaluesbasedon'frac'(0.0=a,1.0=b)
floatLinterp(floatfrac,floata,floatb){
return(a+(frac*(ba)))
}
//Sinusoidaleasein/easeoutinterpolationbetweentwovaluesbasedon'frac'(0.0=a,1.0=b)
floatSinInterp(floatfrac,floata,floatb){
floatpi=3.14159
frac=(sin(pi/2+frac*pi)+1.0)/2.0//0~1>0~1
return(Linterp(frac,a,b))
}
//DRAWSIMPLESHAPEINTERPOLATION
//Interpolationisbasedonthecurrentframenumber
//
voidDrawShape(intframe){
//Calculateafractionthatrepresentstheframe#beingshown
floatfrac=(frame%48)/48.0*2
if(frac>1.0)frac=2.0frac//sawtoothwave:"/\/\/\"
staticfloata_xy[9][2]={
{.5,1.},{0.0,.5},{.5,1.},{0.0,.5},
{0.0,0.0},
{0.0,.5},{+.5,1.},{0.0,.5},{+.5,1.},
}
staticfloatb_xy[9][2]={
{.25,1.},{.50,.75},{.75,1.0},{.50,.75},
{0.0,0.0},
{+.50,.75},{+.75,1.0},{+.50,.75},{+.25,1.0}
}
//Linterpaandbtoformnewshapec
floatc_xy[9][2]
for(inti=0i<9i++)
for(intxy=0xy<2xy++)

http://seriss.com/people/erco/fltk/

34/88

8/11/2015

Erco'sFLTKCheatPage
c_xy[i][xy]=SinInterp(frac,a_xy[i][xy],b_xy[i][xy])
//Drawshape
glColor3f(1.0,1.0,1.0)
glBegin(GL_LINE_STRIP)
for(inti=0i<9i++)
glVertex2f(c_xy[i][0],c_xy[i][1])
glEnd()
}
//DRAWTHEWIDGET
//Eachtimewe'recalled,assume
//
voiddraw(){
if(!valid()){
valid(1)
glLoadIdentity()
glViewport(0,0,w(),h())
}
glClear(GL_COLOR_BUFFER_BIT)
//Drawshape4x,rotatedat90degreepositions
glPushMatrix()
DrawShape(frame)glRotatef(90.0,0,0,1)
DrawShape(frame)glRotatef(90.0,0,0,1)
DrawShape(frame)glRotatef(90.0,0,0,1)
DrawShape(frame)
glPopMatrix()
//Advanceframecounter
++frame
}
//24FPSTIMERCALLBACK
//Called24xpersecondtoredrawthewidget
//
staticvoidTimer_CB(void*userdata){
Playback*pb=(Playback*)userdata
pb>redraw()
Fl::repeat_timeout(1.0/24.0,Timer_CB,userdata)
}
public:
//Constructor
Playback(intX,intY,intW,intH,constchar*L=0):Fl_Gl_Window(X,Y,W,H,L){
frame=0
Fl::add_timeout(1.0/24.0,Timer_CB,(void*)this)//24fpstimer
end()
}
}
intmain(){
Fl_Windowwin(500,500)
Playbackplayback(10,10,win.w()20,win.h()20)
win.resizable(&playback)
win.show()
return(Fl::run())
}

OpenGL3DSphereWithLight

Exampleofanopengl3Dsolidspherewithalightandmaterials.
Usesglutforcreatingthesphere.
Update03/15/2011:ThisoldercodeusedanFl_Gl_WindowandworkedwithFLTK1.1.x,butthatnolongerworkscorrectlyin
1.3.x,sothecodehasbeenupdated(below)tousepureglutcodetocreatetheFLTKsubwindow.
Update04/06/2013:Theaboveolderexampleseemstoworkagainin1.3.x..someonemusthavefixedsomething.Workswith
centos5.6+fltk1.3.xcurrentanyway.Iprefertheolderexamplebecauseitusesopengl/FLTKthewayit'sintendedtobeused,
withlittledependenceonglutotherthantocreatethesphere'sgeometry.
http://seriss.com/people/erco/fltk/

35/88

8/11/2015

Erco'sFLTKCheatPage

OpenGLSphereWithLight
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/glut.H>
#include<FL/gl.h>
#defineWIDTH640
#defineHEIGHT480
//
//Renderasimpleopenglshadedspherewithasinglesidelighterco11/28/08
//
//1.1Modstousepureglutcallsforsubwindowerco03/15/11
//
//COMPILE:fltkconfiguseglutcompilesphere.cxx
//
//GLUT:RESHAPETHEVIEWPORT
voidReshape(intW,intH){
//(REFERENCE:SGIlight.cDEMO)
GLfloatratio=(float)W/(float)H
glViewport(0,0,(GLsizei)W,(GLsizei)H)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(1.5*ratio,1.5*ratio,1.5,1.5,10.0,10.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
}
//GLUT:REDRAWTHESCENE
voidRedraw(){
staticintvalid=0
if(!valid){
valid=1
Reshape(WIDTH,HEIGHT)
//(REFERENCE:SGI'light.c'EXAMPLE)
GLfloatmat_ambient[]={1.0,1.0,1.0,1.0}//RGBA
GLfloatmat_diffuse[]={1.0,1.0,1.0,1.0}//RGBA
GLfloatmat_specular[]={1.0,1.0,1.0,1.0}//RGBA
GLfloatlight_position[]={5.0,5.0,0.0,0.0}//XYZ
glClearColor(0.0,0.0,0.4,0.0)//bgcolor
glShadeModel(GL_SMOOTH)
//
glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient)
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse)
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular)
glMaterialf(GL_FRONT,GL_SHININESS,20.0)
glLightfv(GL_LIGHT0,GL_POSITION,light_position)
//
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
}
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glPushMatrix()
glColor3f(0.5,0.5,0.5)
glutSolidSphere(0.5,30,30)
glPopMatrix()
}
intmain(intargc,char*argv[]){
Fl_Windowwin(WIDTH,HEIGHT,"sphere")
win.resizable(win)
win.show(argc,argv)
//Docssaytoaddglutsubwindow/after/callingwin.show()
win.begin()
//glutInit(&argc,argv)//docssaynottocallthisifasubwindow
glutInitWindowSize(WIDTH20,HEIGHT20)
glutInitWindowPosition(10,10)//placeinsideparentwindow
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_MULTISAMPLE)
glutCreateWindow("sphere")
glutReshapeFunc(Reshape)
glutDisplayFunc(Redraw)
win.end()
return(Fl::run())
}

Fl_File_BrowserExample
ThisdemostratesthesimpleandsparseFl_File_BrowserclassthatisusefulforloadinganFl_Browserwidgetwithadirectory
listing.

http://seriss.com/people/erco/fltk/

36/88

8/11/2015

Erco'sFLTKCheatPage

NoteFl_File_Browseris/just/anFl_Browserwithfilenamesloadedintoititdoesn'thavealltheusualadornmentsusersexpect
whenbrowsingfiles,eg.pathnamebar,imagepreviews,filtercontrols.Forthat,useFl_File_Chooserinstead!

Example#1:Fl_File_Browser:Selectiondemo
Showhowtobrowsesomefilesandselectone
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_File_Browser.H>
//
//DemonstratesimpleuseofFl_File_Browserwithselectionerco6/4/11
//
intmain(intargc,char**argv){
Fl_Windowwin(300,400,"Fl_File_Browser")
Fl_File_Browserfbrow(10,10,30020,40020)
fbrow.load(".")//loaddirectorylistingofcurrentdirectory
fbrow.type(FL_HOLD_BROWSER)//useforsingleselection
//fbrow.type(FL_MULTI_BROWSER)//useformultipleselection
win.end()
win.resizable(fbrow)
win.show(argc,argv)
return(Fl::run())
}

Example#2:Fl_File_Browser:Selectionwithcallback
Showsuseofcallbacktodetermineselecteditem.
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_File_Browser.H>
#include<FL/fl_ask.H>
//
//DemonstrateFl_File_Browserwithcallbackerco6/4/11
//
voidBrowserCallback(Fl_Widget*w,void*data){
Fl_File_Browser*fbrow=(Fl_File_Browser*)w
intindex=fbrow>value()//getindexofselecteditem
if(index>0){//validitem?
fl_alert("Selected:%d(%s)\n",index,fbrow>text(index))//showitem'stext
}
}
intmain(intargc,char**argv){
Fl_Windowwin(300,400,"Fl_File_BrowserwithCallback")
Fl_File_Browserfbrow(10,10,30020,40020)
fbrow.load(".")//loaddirectorylistingofcurrentdirectory
fbrow.type(FL_HOLD_BROWSER)//useforsingleselection
//fbrow.type(FL_MULTI_BROWSER)//useformultipleselection
fbrow.callback(BrowserCallback)
win.end()
win.resizable(fbrow)
win.show(argc,argv)
return(Fl::run())
}

Fl_File_ChooserExample
http://seriss.com/people/erco/fltk/

37/88

8/11/2015

Erco'sFLTKCheatPage

Whatfollowsisa/simple/exampleofhowtouseFl_File_Chooser,thetypicalwaytolettheuserselectfilesandbrowse
directories.Or,foramorethoroughexample,seethislargerexample.

Example:Fl_File_ChooserExampleUsage
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Menu_Bar.H>
#include<FL/Fl_File_Chooser.H>
//
//DemonstratehowtouseFl_File_Chooser
//erco08/04/2005
//
//Callback:whenusepicks'File|Open'frommainmenu
voidopen_cb(Fl_Widget*,void*){
//Createthefilechooser,andshowit
Fl_File_Chooserchooser(".",//directory
"*",//filter
Fl_File_Chooser::MULTI,//choosertype
"TitleOfChooser")//title
chooser.show()
//Blockuntiluserpickssomething.
//(Theotherwaytodothisistouseacallback())
//
while(chooser.shown())
{Fl::wait()}
//Userhitcancel?
if(chooser.value()==NULL)
{fprintf(stderr,"(Userhit'Cancel')\n")return}
//Printwhattheuserpicked
fprintf(stderr,"\n")
fprintf(stderr,"DIRECTORY:'%s'\n",chooser.directory())
fprintf(stderr,"VALUE:'%s'\n",chooser.value())
fprintf(stderr,"COUNT:%dfilesselected\n",chooser.count())
//Multiplefiles?Showallofthem
if(chooser.count()>1){
for(intt=1t<=chooser.count()t++){
fprintf(stderr,"VALUE[%d]:'%s'\n",t,chooser.value(t))
}
}
}
//Callback:whenuserpicks'Quit'
voidquit_cb(Fl_Widget*,void*){
exit(0)
}
intmain(){
Fl_Windowwin(300,180,"SimpleExampleofFl_File_Chooser")
Fl_Menu_Barmenubar(0,0,300,25)
menubar.add("File/Open",0,open_cb)
menubar.add("File/Quit",0,quit_cb)
win.show()
return(Fl::run())
}

Getcoordinatesformouseclicksonscrollablebox
Thisexampleshowshowtogetthecoordinatesformouseclickeventsonascrollablebox,thecoordinatesbeingrelativetothe
cornersofthebox.
Thiscanbeusful,forinstance,inanapplicationthatshowslargeimagesinsideascrollallowingtheusertoclickontheimage,
soastoreadbackanddisplaypixeldataandx/ypixelcoordinatesontheimage,takingintoaccountthescrollpositionsofthe
image.
Showshowtousethemouseevents(whicharerelativetothecornerofthefltkwindow)andtheoffsetofthescrollbarsto
calculatewhereinthebox(orimage)theuserclicked.

Example:GettingMouseClicksonaScrollableBox
#include<stdio.h>
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Scroll.H>
#include<FL/Fl_Box.H>
//
//Demonstrategettingmouseclickcoordsonascrollablebox
//erco08/14/2005
//
classScrollBox:publicFl_Box{
Fl_Scroll*scroll

http://seriss.com/people/erco/fltk/

38/88

8/11/2015

Erco'sFLTKCheatPage
public:
inthandle(inte){
if(e==FL_PUSH){
fprintf(stderr,"event_x,event_y:%d,%d,Hitonbox:%d,%d\n",
Fl::event_x(),
Fl::event_y(),
Fl::event_x()scroll>x()+scroll>hscrollbar.value(),
Fl::event_y()scroll>y()+scroll>scrollbar.value())
}
return(Fl_Box::handle(e))
}
voidSetScroll(Fl_Scroll*val){
scroll=val
}
ScrollBox(intx,inty,intw,inth,constchar*l=0):Fl_Box(x,y,w,h,l){
color(FL_BLUE)
box(FL_FLAT_BOX)
}
}
intmain(){
Fl_Double_Windowwin(400,400)
Fl_Scrollscroll(0,0,400,400)
ScrollBoxbox(0,0,1000,1000)//boxisbiggerthanscroll
box.SetScroll(&scroll)
scroll.end()
win.resizable(win)
win.show()
return(Fl::run())
}

UsingFl_Browserwithcolumns

ThisexampleshowshowtousetheFl_Browsercolumn_widths()andcolumn_char()methodsforpresentingdataincolumns
(eveninnonfixedwidthfonts).

Example:UsingFl_Browserwithcolumns
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Browser.H>
//
//DemonstrateFl_Browserwithcolumns
//erco09/16/05
//
intmain(){
Fl_Window*w=newFl_Window(900,300)
Fl_Browser*b=newFl_Browser(10,10,w>w()20,w>h()20)
intwidths[]={50,50,50,70,70,40,40,70,70,50,0}//widthsforeachcolumn
b>column_widths(widths)
b>column_char('\t')//tabsascolumndelimiters
b>type(FL_MULTI_BROWSER)
b>add("USER\tPID\t%CPU\t%MEM\tVSZ\tRSS\tTTY\tSTAT\tSTART\tTIME\tCOMMAND")//linesoftabdelimiteddata
b>add("root\t2888\t0.0\t0.0\t1352\t0\ttty3\tSW\tAug15\t0:00\t@b@f/sbin/mingettytty3")
b>add("erco\t2889\t0.0\t13.0\t221352\t0\ttty3\tR\tAug15\t1:34\t@b@f/usr/local/bin/rendera350004")
b>add("uucp\t2892\t0.0\t0.0\t1352\t0\tttyS0\tSW\tAug15\t0:00\t@b@f/sbin/agettyh19200ttyS0vt100")
b>add("root\t13115\t0.0\t0.0\t1352\t0\ttty2\tSW\tAug30\t0:00\t@b@f/sbin/mingettytty2")
b>add("root\t13464\t0.0\t0.0\t1352\t0\ttty1\tSW\tAug30\t0:00\t@b@f/sbin/mingettytty1noclear")
w>resizable(b)
w>end()
w>show()
return(Fl::run())
}

Fl_BrowserSorting

http://seriss.com/people/erco/fltk/

39/88

8/11/2015

Erco'sFLTKCheatPage

ThisexampleshowshowtosortthelinesinanFl_Browser.

Example:SortinganFl_Browser
#include<string.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Browser.H>
//
//DemosortinganFl_Browserwithbubblesort
//erco09/02/2005
//
voidForwardSort(Fl_Browser*b){
for(intt=1t<=b>size()t++){
for(intr=t+1r<=b>size()r++){
if(strcmp(b>text(t),b>text(r))>0){
b>swap(t,r)
}
}
}
}
voidReverseSort(Fl_Browser*b){
for(intt=1t<=b>size()t++){
for(intr=t+1r<=b>size()r++){
if(strcmp(b>text(t),b>text(r))<0){
b>swap(t,r)
}
}
}
}
voidtogglesort_cb(Fl_Widget*w,void*data){
Fl_Browser*b=(Fl_Browser*)data
if(strcmp(w>label(),"DoFwdSort")==0){
ForwardSort(b)
w>label("DoRevSort")//toggle
}else{
ReverseSort(b)
w>label("DoFwdSort")//toggle
}
}
intmain(){
Fl_Window*win=newFl_Window(300,500,"SortExample")
Fl_Browser*b=newFl_Browser(10,40,win>w()20,win>h()50)
b>type(FL_MULTI_BROWSER)
b>add("Papa")b>add("Delta")b>add("Hotel")
b>add("Charlie")b>add("Echo")b>add("Foxtrot")
b>add("Golf")b>add("Lima")b>add("Victor")
b>add("Alpha")b>add("Xray")b>add("Yankee")
b>add("Oscar")b>add("India")b>add("Juliet")
b>add("Kilo")b>add("Mike")b>add("Sierra")
b>add("November")b>add("Tango")b>add("Quebec")
b>add("Bravo")b>add("Romeo")b>add("Uniform")
b>add("Whisky")b>add("Zulu")
Fl_Button*butt=newFl_Button(10,10,100,28,"DoFwdSort")
butt>callback(togglesort_cb,(void*)b)
win>show()
return(Fl::run())
}

StrikeThroughText
Demonstrateshowtodraw'strikethrough'text.
Asliderisincludedtoshowhowfontsizechangeslookwiththestrikethroughline.
Youcanuncommentthe'DRAWUNDERLINE'codetodounderliningaswell.

Example:DrawingStrikethroughText
#include<FL/Fl.H>
#include<FL/Fl_Window.H>

http://seriss.com/people/erco/fltk/

40/88

8/11/2015

Erco'sFLTKCheatPage
#include<FL/Fl_Box.H>
#include<FL/Fl_Value_Slider.H>
#include<FL/fl_draw.H>
//
//Demonstratestrikethroughtext
//erco10/09/05
//
classMyBox:publicFl_Box{
voiddraw(){
if(label()){
Fl_Box::draw_box()
//DRAWLABELINCENTEROFWIDGET
intlabel_x,label_y,label_w,label_h
fl_font(labelfont(),labelsize())
fl_measure(label(),label_w,label_h,1)
fl_color(labelcolor())
label_x=x()+(w()/2)label_w/2//alwayscentertext
label_y=y()+(h()/2)label_h/2
fl_draw(label(),label_x,label_y+labelsize())
//DRAWSTRIKETHROUGH
fl_line_style(FL_SOLID)
fl_line(label_x,label_y+(labelsize()/3*2),label_x+label_w,label_y+(labelsize()/3*2))
//////DRAWUNDERLINE
////fl_line_style(FL_SOLID)
////fl_line(label_x,label_y+labelsize(),label_x+label_w,label_y+labelsize()+1)
}
}
public:
//CONSTRUCTOR
MyBox(intX,intY,intW,intH,constchar*L=0):Fl_Box(X,Y,W,H,L){
}
}
//HANDLESLIDERCHANGINGFONTSIZE
voidChangeFontsize_CB(Fl_Widget*w,void*data){
Fl_Value_Slider*slider=(Fl_Value_Slider*)w
Fl_Box*box=(Fl_Box*)data
intnewsize=(int)slider>value()
box>labelsize(newsize)
box>redraw()
}
intmain(){
Fl_Windowwin(200,100)
MyBoxbox(10,40,win.w()20,win.h()50,"Testing")
box.labelsize(24)
box.box(FL_FLAT_BOX)
box.color(50)
Fl_Value_Sliderfontsize(10,10,20020,20)
fontsize.callback(ChangeFontsize_CB,(void*)&box)
fontsize.type(FL_HOR_SLIDER)
fontsize.range(8,40)
fontsize.value(box.labelsize())
win.show()
return(Fl::run())
}

ChangingthemousecursorforanFl_GL_Window
DemonstrateshowtochangethecursorforanFl_Gl_Window.
Fl_Gl_WindowisaspecialcaseonWin32withFltkversions1.1.6andolder,becausetherewasabugwherejustsettingthe
cursorwasn'tenough,youhadtosetthecursorfortheparentFl_Window.
Thefollowingcodeshouldworkforallplatformsandallversionsof1.1.x.

ChangingthemousecursorforanFl_GL_Window
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/gl.h>
//
//Test'cross'cursorwhenmouseinGLwindow
//erco11/03/05
//
classMyGlWindow:publicFl_Gl_Window{
inthandle(inte){
intret=Fl_Gl_Window::handle(e)
switch(e){
caseFL_ENTER:
window()>cursor(FL_CURSOR_CROSS)//'window()>cursor()'neededonWIN32for1.1.6andolder.
ret=1//1.1.7andupcanprobablyjustusefl_cursor(..)
break
caseFL_LEAVE:
window()>cursor(FL_CURSOR_DEFAULT)
ret=1
break
}
return(ret)
}
voiddraw(){
if(!valid()){
valid(1)
glViewport(0,0,w(),h())
}
glClear(GL_COLOR_BUFFER_BIT)
}

http://seriss.com/people/erco/fltk/

41/88

8/11/2015

Erco'sFLTKCheatPage
public:
MyGlWindow(intx,inty,intw,inth,constchar*l=0):Fl_Gl_Window(x,y,w,h,l){
}
}
intmain(){
Fl_Windowwin(500,500)
MyGlWindowglwin(10,10,50020,50020)
win.show()
return(Fl::run())
}

ExtendFl_Browsertohaveinteractivelyresizablecolumns

AninteractivelyresizableFl_Browser

DemonstrateshowtoextendthefunctionalityofthestandardFl_Browsertosupportinteractivelyresizablecolumns.
ThefollowingcodetestedonFltk1.1.6

AnInteractivelyResizableFl_Browser
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Browser.H>
#include<FL/fl_draw.H>
//
//DemonstratehowtoderiveaclassextendingFl_Browserwithinteractivelyresizablecolumns
//erco1.1012/09/2005
//
classColResizeBrowser:publicFl_Browser{
Fl_Color_colsepcolor//colorofcolumnseparatorlines
int_showcolsep//flagtoenabledrawingcolumnseparators
Fl_Cursor_last_cursor//savedcursorstateinfo
int_dragging//1=userdraggingacolumn
int_dragcol//col#useriscurrentlydragging
int*_widths//pointertouser'swidth[]array
int_nowidths[1]//defaultwidtharray(nonconst)
//CHANGECURSOR
//Doesnothingifcursoralreadysettovaluespecified.
//
voidchange_cursor(Fl_Cursornewcursor){
if(newcursor!=_last_cursor){
fl_cursor(newcursor,FL_BLACK,FL_WHITE)
_last_cursor=newcursor
}
}
//RETURNTHECOLUMNMOUSEIS'NEAR'
//Returns1ifnone.
//
intwhich_col_near_mouse(){
intX,Y,W,H
Fl_Browser::bbox(X,Y,W,H)//areainsidebrowser'sbox()
//EVENTNOTINSIDEBROWSERAREA?(eg.onascrollbar)
if(!Fl::event_inside(X,Y,W,H)){
return(1)
}
intmousex=Fl::event_x()+hposition()
intcolx=this>x()
for(intt=0_widths[t]t++){
colx+=_widths[t]
intdiff=mousexcolx
//MOUSE'NEAR'ACOLUMN?
//Returncolumn#
//
if(diff>=4&&diff<=4){
return(t)
}
}
return(1)
}
protected:
//MANAGEEVENTSTOHANDLECOLUMNRESIZING
inthandle(inte){
//Notshowingcolumnseparators?UsedefaultFl_Browser::handle()logic
if(!showcolsep())return(Fl_Browser::handle(e))
//Handlecolumnresizing
intret=0
switch(e){
caseFL_ENTER:{
ret=1
break
}
caseFL_MOVE:{
if(which_col_near_mouse()>=0){

http://seriss.com/people/erco/fltk/

42/88

8/11/2015

Erco'sFLTKCheatPage
change_cursor(FL_CURSOR_WE)
}else{
change_cursor(FL_CURSOR_DEFAULT)
}
ret=1
break
}
caseFL_PUSH:{
intwhichcol=which_col_near_mouse()
if(whichcol>=0){
//CLICKEDONRESIZER?STARTDRAGGING
ret=1
_dragging=1
_dragcol=whichcol
change_cursor(FL_CURSOR_DEFAULT)
}
break
}
caseFL_DRAG:{
if(_dragging){
ret=1
//Sumupcolumnwidthstodetermineposition
intmousex=Fl::event_x()+hposition()
intnewwidth=mousexx()
for(intt=0_widths[t]&&t<_dragcolt++){
newwidth=_widths[t]
}
if(newwidth>0){
//Applynewwidth,redrawinterface
_widths[_dragcol]=newwidth
if(_widths[_dragcol]<2){
_widths[_dragcol]=2
}
redraw()
}
}
break
}
caseFL_LEAVE:
caseFL_RELEASE:{
_dragging=0//disabledragmode
change_cursor(FL_CURSOR_DEFAULT)//ensurenormalcursor
ret=1
break
}
}
if(_dragging)return(1)//dragging?don'tpasseventtoFl_Browser
return(Fl_Browser::handle(e)?1:ret)
}
voiddraw(){
//DRAWBROWSER
Fl_Browser::draw()
if(_showcolsep){
//DRAWCOLUMNSEPARATORS
intcolx=this>x()hposition()
intX,Y,W,H
Fl_Browser::bbox(X,Y,W,H)
fl_color(_colsepcolor)
for(intt=0_widths[t]t++){
colx+=_widths[t]
if(colx>X&&colx<(X+W)){
fl_line(colx,Y,colx,Y+H1)
}
}
}
}
public:
//CTOR
ColResizeBrowser(intX,intY,intW,intH,constchar*L=0):Fl_Browser(X,Y,W,H,L){
_colsepcolor=Fl_Color(FL_GRAY)
_last_cursor=FL_CURSOR_DEFAULT
_showcolsep=0
_dragging=0
_nowidths[0]=0
_widths=_nowidths
}
//GET/SETCOLUMNSEPARATORLINECOLOR
Fl_Colorcolsepcolor()const{
return(_colsepcolor)
}
voidcolsepcolor(Fl_Colorval){
_colsepcolor=val
}
//GET/SETDISPLAYOFCOLUMNSEPARATORLINES
//1:showlines,0:don'tshowlines
//
intshowcolsep()const{
return(_showcolsep)
}
voidshowcolsep(intval){
_showcolsep=val
}
//GET/SETCOLUMNWIDTHSARRAY
//Justlikefltkmethod,butarrayisnonconst.
//
int*column_widths()const{
return(_widths)
}
voidcolumn_widths(int*val){
_widths=val
Fl_Browser::column_widths(val)
}
}
intmain(){
Fl_Double_Window*w=newFl_Double_Window(900,300)
intwidths[]={50,50,50,70,70,40,40,70,70,50,0}//widthsforeachcolumn
ColResizeBrowser*b=newColResizeBrowser(10,10,w>w()20,w>h()20)
b>column_widths(widths)
b>showcolsep(1)
//b>colsepcolor(FL_RED)

http://seriss.com/people/erco/fltk/

43/88

8/11/2015

Erco'sFLTKCheatPage
b>column_char('\t')//tabsascolumndelimiters
b>type(FL_MULTI_BROWSER)
////SIMPLEUNCOLOREDHEADING
////b>add("USER\tPID\t%CPU\t%MEM\tVSZ\tRSS\tTTY\tSTAT\tSTART\tTIME\tCOMMAND")
//NICERCOLOREDHEADING
b>add("@B12@C7@b@.USER\t@B12@C7@b@.PID\t@B12@C7@b@.%CPU\t"//tabdelimitedcolumnswithcolors
"@B12@C7@b@.%MEM\t@B12@C7@b@.VSZ\t@B12@C7@b@.RSS\t"
"@B12@C7@b@.TTY\t@B12@C7@b@.STAT\t@B12@C7@b@.START\t"
"@B12@C7@b@.TIME\t@B12@C7@b@.COMMAND")
//COLUMNSOFDATA
b>add("root\t2888\t0.0\t0.0\t1352\t0\ttty3\tSW\tAug15\t0:00\t@b@f/sbin/mingettytty3")
b>add("erco\t2889\t0.0\t13.0\t221352\t0\ttty3\tR\tAug15\t1:34\t@b@f/usr/local/bin/rendera350004")
b>add("uucp\t2892\t0.0\t0.0\t1352\t0\tttyS0\tSW\tAug15\t0:00\t@b@f/sbin/agettyh19200ttyS0vt100")
b>add("root\t13115\t0.0\t0.0\t1352\t0\ttty2\tSW\tAug30\t0:00\t@b@f/sbin/mingettytty2")
b>add("root\t13464\t0.0\t0.0\t1352\t0\ttty1\tSW\tAug30\t0:00\t@b@f/sbin/mingettytty1noclear")
w>resizable(b)
w>end()
w>show()
return(Fl::run())
}

Howtomakea4portproportionallyresizableOpenGLwindowusingFl_Tile

Aninteractivelyresizable4PortOpenGLwindow

Demonstrateshowtocreate4separateOpenGLwindowsinone,allproportionallyresizableusingFl_Tile,andinteractively
resizable.
ThefollowingcodetestedonFltk1.1.6

Fl_Tile4portOpenGLWindow
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Tile.H>
#include<FL/Fl_Group.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/gl.h>
//
//Exampleofhowtomakea4porttiledGLwindow
//ting/erco1.0
//
classViewport:publicFl_Gl_Window{
voidRectLine(intx1,inty1,intx2,inty2){
glBegin(GL_LINE_LOOP)
glVertex2s(x1,y1)glVertex2s(x2,y1)
glVertex2s(x2,y2)glVertex2s(x1,y2)
glEnd()
}
protected:
voiddraw(){
if(!valid()){
//Firsttime?initviewport,etc.
valid(1)
glLoadIdentity()
glViewport(0,0,w(),h())
glOrtho(w(),w(),h(),h(),1,1)
}
//Clearscreen
glClear(GL_COLOR_BUFFER_BIT)
//Drawwhite'X'
glColor3f(1.0,1.0,1.0)
glBegin(GL_LINE_STRIP)glVertex2f(w(),h())glVertex2f(w(),h())glEnd()
glBegin(GL_LINE_STRIP)glVertex2f(w(),h())glVertex2f(w(),h())glEnd()
//Drawyellowborderlast,aroundtheouteredge
glColor3f(1.0,1.0,0.0)
RectLine(w()+1,h()+1,w()1,h()1)
}
public:
Viewport(intx,inty,intw,inth,char*l=0):Fl_Gl_Window(x,y,w,h,l){
end()
}

http://seriss.com/people/erco/fltk/

44/88

8/11/2015

Erco'sFLTKCheatPage
}
classLayout:publicFl_Tile{
private:
Viewport*toplft,*toprig,*botlft,*botrig
protected:
//Customresizebehavior:keepviewportsproportionalduringresize
voidresize(intX,intY,intW,intH){
//Getoldproportionssowecanpreservethroughresize
floatdw=(float)toplft>w()/w()
floatdh=(float)toplft>h()/h()
//Carefullyconstructnewedgesofports,keepingproportions
intxlef=0,xmid=(int)(W*dw+0.5),xrig=W
intytop=0,ymid=(int)(H*dh+0.5),ybot=H
intwlef=xmidxlef,wrig=xrigxmid
inthtop=ymidytop,hbot=ybotymid
//ResizeourwidgetviaFl_Widget(topreventchildrenresizing)
Fl_Widget::resize(X,Y,W,H)
//Resizechildrenwithcustomcomputations
toplft>resize(xlef,ytop,wlef,htop)
toprig>resize(xmid,ytop,wrig,htop)
botlft>resize(xlef,ymid,wlef,hbot)
botrig>resize(xmid,ymid,wrig,hbot)
}
public:
Layout(intx,inty,intw,inth):Fl_Tile(x,y,w,h){
box(FL_BORDER_BOX)
color(FL_RED)//(shouldn'tbeseen)
//Carefullyconstructedgesofports
intxlef=0,xmid=w/2,xrig=w
intytop=0,ymid=h/2,ybot=h
intwlef=xmidxlef,wrig=xrigxmid
inthtop=ymidytop,hbot=ybotymid
//Createthe4ports
toplft=newViewport(xlef,ytop,wlef,htop)
toprig=newViewport(xmid,ytop,wrig,htop)
botlft=newViewport(xlef,ymid,wlef,hbot)
botrig=newViewport(xmid,ymid,wrig,hbot)
end()
}
}
intmain(){
Fl_Double_Window*win=newFl_Double_Window(800,500)
Layout*layout=newLayout(0,0,win>w(),win>h())
win>resizable(layout)
win>end()
win>show()
return(Fl::run())
}

AnOpenGLWindowwithaDynamicPopupMenu
DemonstrateshowtocreateadynamicpopupmenuoveranOpenGLwindow.(Probablyworksforregularwindowstoo)
ThefollowingcodetestedwithFltk1.1.6onOSX/Linux/Windows.

OpenGL+DynamicPopupMenu
#include<stdio.h>
#include<time.h>
#include<FL/Fl.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/Fl_Menu_Button.H>
#include<FL/gl.h>
//
//SimpleGLwindowwithdynamicpopupmenu
//erco01/25/06
//
classMyGlWindow:publicFl_Gl_Window{
voiddraw(){
if(!valid()){
glLoadIdentity()
glViewport(0,0,w(),h())
glOrtho(w(),w(),h(),h(),1,1)
}
glClear(GL_COLOR_BUFFER_BIT)
}
staticvoidMenu_CB(Fl_Widget*,void*data){
charname[80]
((Fl_Menu_Button*)data)>item_pathname(name,sizeof(name)1)
fprintf(stderr,"MenuCallback:%s\n",name)
}
inthandle(inte){
intret=Fl_Gl_Window::handle(e)
switch(e){
caseFL_PUSH:
if(Fl::event_button()==3){
chartmp[80]
time_tt=time(NULL)
sprintf(tmp,"Timeis%s",ctime(&t))
//Dynamicallycreatemenu,popitup
Fl_Menu_Buttonmenu(Fl::event_x_root(),Fl::event_y_root(),80,1)
menu.add(tmp)//dynamicchangeseachtimepopupopens..
menu.add("Edit/Copy",0,Menu_CB,(void*)&menu)
menu.add("Edit/Paste",0,Menu_CB,(void*)&menu)

http://seriss.com/people/erco/fltk/

45/88

8/11/2015

Erco'sFLTKCheatPage
menu.add("Quit",0,Menu_CB,(void*)&menu)
menu.popup()
}
}
return(ret)
}
public:
//CONSTRUCTOR
MyGlWindow(intX,intY,intW,intH,constchar*L=0):Fl_Gl_Window(X,Y,W,H,L){
}
}
//MAIN
intmain(){
Fl_Windowwin(500,300)
MyGlWindowmygl(10,10,win.w()20,win.h()20)
win.show()
return(Fl::run())
}

DropShadowEffectExample

Aclockwiththedropshadoweffect.
Demonstrateshowtomakeadropshadoweffectwithtext.Createsa'DropShadowBox'widget,anddemonstratesitsusewith
asimpleclockapplication.
TestedwithFltk1.1.6onLinux,probablyworksonallplatforms+allrevsof1.1.x.
Update04/06/2013:Workswithfltk1.3.xonlinuxaswell.

DropShadowEffect
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Box.H>
#include<FL/fl_draw.H>
#include<stdio.h>
#include<time.h>
//
//Dropshadowexamplewidget
//1.0erco02/11/06
//
classDropShadowBox:publicFl_Box{
int_levels
voiddraw(){
Fl_Box::draw_box()
if(label()){
//Drawlabelw/dropshadoweffect
fl_font(labelfont(),labelsize())
intX=x()+Fl::box_dx(box())
intY=y()+Fl::box_dy(box())
for(inti=_levelsi>0i){//loopthroughshadesofcolor
fl_color(fl_color_average(color(),//bgcolor(widget'sbg)
labelcolor(),//fgcolor(label)
(i/(float)_levels)))//weightbetweenbgandfgcolor
fl_draw(label(),X+i,Y+i,w(),h(),align())
}
}
}
public:
DropShadowBox(intX,intY,intW,intH,constchar*L=0):Fl_Box(X,Y,W,H,L){
_levels=5
}
voidlevels(intval){_levels=val}
intlevels(){return(_levels)}
}

//Timercallbacktoupdatelabel
voidUpdate_CB(void*userdata){
DropShadowBox*box=(DropShadowBox*)userdata
time_tlt=time(NULL)
box>label(ctime(&lt))
Fl::repeat_timeout(1.0,Update_CB,(void*)box)
}

intmain(){
Fl_Double_Window*win=newFl_Double_Window(400,100,"DropShadowClock")
DropShadowBox*box=newDropShadowBox(10,10,win>w()20,win>h()20)
box>labelsize(28)
box>levels(8)
Fl::add_timeout(1.0,Update_CB,(void*)box)
win>show()
Update_CB((void*)box)//forceupdateimmediately
return(Fl::run())

http://seriss.com/people/erco/fltk/

46/88

8/11/2015

Erco'sFLTKCheatPage
}

OpenGL2DTextona3DObject

Textonaspinning3DOpenGLobject
Demonstrateshowtoshowtextona3Dobject.
TestedwithFltk1.1.6onLinux,probablyworksonallplatforms+allrevsof1.1.x.
Update04/06/2013:Workswithfltk1.3.xonlinuxaswell.

OpenGL2DTexton3DObject
//
//OpenGLexampleshowingtextonarotating3Dobject.
//erco03/03/06
//
#include<FL/Fl.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/gl.h>
#include<GL/glu.h>
#include<string.h>
#include<stdio.h>
//Tetrahedronpoints
#defineTOP0,1,0
#defineRIGHT1,1,1
#defineLEFT1,1,1
#defineBACK0,1,1
classMyGlWindow:publicFl_Gl_Window{
floatrotangle
voiddraw(){
//Firsttime?initviewport,etc.
if(!valid()){
valid(1)
//InitializeGL
glClearColor(0.0,0.0,0.0,0.0)
glClearDepth(1.0)
glDepthFunc(GL_LESS)
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_FLAT)
}
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
//Positioncamera/viewportinit
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glViewport(0,0,w(),h())
gluPerspective(45.0,(float)w()/(float)h(),1.0,10.0)
glTranslatef(0.0,0.0,5.0)
//Positionobject
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glRotatef(rotangle,1,0,1)
glRotatef(rotangle,0,1,0)
glRotatef(rotangle,1,1,1)
//Drawtetrahedron
glColor3f(1.0,0.0,0.0)glBegin(GL_POLYGON)glVertex3f(TOP)glVertex3f(RIGHT)glVertex3f(LEFT)glEnd()
glColor3f(0.0,1.0,0.0)glBegin(GL_POLYGON)glVertex3f(TOP)glVertex3f(BACK)glVertex3f(RIGHT)glEnd()
glColor3f(0.0,0.0,1.0)glBegin(GL_POLYGON)glVertex3f(TOP)glVertex3f(LEFT)glVertex3f(BACK)glEnd()
glColor3f(0.5,0.5,0.5)glBegin(GL_POLYGON)glVertex3f(RIGHT)glVertex3f(BACK)glVertex3f(LEFT)glEnd()
//Printtetrahedron'spointsonobject
//Disabledepthbufferwhiledrawingtext,
//sotextdraws/over/object.
//
glDisable(GL_DEPTH_TEST)
{
constchar*p
gl_font(1,12)
glColor3f(1.0,1.0,1.0)
glRasterPos3f(TOP)p="+top"gl_draw(p,strlen(p))
glRasterPos3f(LEFT)p="+left"gl_draw(p,strlen(p))
glRasterPos3f(RIGHT)p="+right"gl_draw(p,strlen(p))
glRasterPos3f(BACK)p="+back"gl_draw(p,strlen(p))
}
glEnable(GL_DEPTH_TEST)

http://seriss.com/people/erco/fltk/

47/88

8/11/2015

Erco'sFLTKCheatPage
//Printrotanglevalueatfixedpositionatlowerleft
chars[40]
sprintf(s,"ROT=%.2f",rotangle)
glLoadIdentity()glRasterPos2f(3,2)gl_draw(s,strlen(s))
}
staticvoidTimer_CB(void*userdata){
MyGlWindow*o=(MyGlWindow*)userdata
o>rotangle+=1.0
o>redraw()
Fl::repeat_timeout(1.0/24.0,Timer_CB,userdata)//24fps
}
public:
//CONSTRUCTOR
MyGlWindow(intX,intY,intW,intH,constchar*L=0):Fl_Gl_Window(X,Y,W,H,L){
rotangle=0
Fl::add_timeout(3.0,Timer_CB,(void*)this)//wait3secsbeforeanimationbegins
}
}
//MAIN
intmain(){
Fl_Windowwin(500,300)
MyGlWindowmygl(10,10,win.w()20,win.h()20)
win.show()
return(Fl::run())
}

SimpleTabsExample

TabsExample
DemonstrateshowtousetheFl_Tabswidget.

Fl_TabsExample
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Tabs.H>
#include<FL/Fl_Group.H>
#include<FL/Fl_Button.H>
//
//Simpletabsexample
//__________
//__/Aaa\/Bbb\______________________
//|_______|
//||_______||
//|_______|
//||_______||
//|_______|
//||_______||
//|______________________________________|
//
intmain(intargc,char*argv[]){
Fl_Window*win=newFl_Window(500,200,"TabsExample")
{
Fl_Tabs*tabs=newFl_Tabs(10,10,50020,20020)
{
//Aaatab
Fl_Group*aaa=newFl_Group(10,35,50020,20045,"Aaa")
{
Fl_Button*b1=newFl_Button(50,60,90,25,"ButtonA1")b1>color(88+1)
Fl_Button*b2=newFl_Button(50,90,90,25,"ButtonA2")b2>color(88+2)
Fl_Button*b3=newFl_Button(50,120,90,25,"ButtonA3")b3>color(88+3)
}
aaa>end()
//Bbbtab
Fl_Group*bbb=newFl_Group(10,35,50010,20035,"Bbb")
{
Fl_Button*b1=newFl_Button(50,60,90,25,"ButtonB1")b1>color(88+1)
Fl_Button*b2=newFl_Button(150,60,90,25,"ButtonB2")b2>color(88+3)
Fl_Button*b3=newFl_Button(250,60,90,25,"ButtonB3")b3>color(88+5)
Fl_Button*b4=newFl_Button(50,90,90,25,"ButtonB4")b4>color(88+2)
Fl_Button*b5=newFl_Button(150,90,90,25,"ButtonB5")b5>color(88+4)
Fl_Button*b6=newFl_Button(250,90,90,25,"ButtonB6")b6>color(88+6)
}
bbb>end()
}
tabs>end()

http://seriss.com/people/erco/fltk/

48/88

8/11/2015

Erco'sFLTKCheatPage
}
win>end()
win>show()
return(Fl::run())
}

HowtoturnaMacFLTKapplicationintoan".appbundle"
OnOSX,GUIapplicationsmusthaveafew'resources'inordertomaketheapplicationruncorrectly.InthepreOSXdays,this
wasdonebyaddingamagical'resourcefork'and'dataforks'totheexecutable.
ThesedaysAppleis(rightfully)tryingtogetawayfromthis'magicdata'approach,sinceApplehasnowadoptedUnixasits
baseoperatingsystem,whichlikestothinkofallfilesasastreamofbytes,andno'magicdata'.
Todothis,Appledecidedtoseparatethefileandthemagicdataintoseparatefiles,andputthemallintoadirectoryhierarchy
knownasa'bundle'.Fromaunixpointofview,a'bundle'issimplyadirectoryoffiles,sowhenonewantstoruntheapplication
fromtheFinderorwiththeopen(1)command,onereferstothesubdirectory,notthefileswithinit.
Forinstance,ifyouhaveanapplicationcalled'foo',thenthe'bundle'(ordirectoryhierarchy)mightlooklikethis:
%findfoo.appprint
foo.app/<thetopleveldirectory(bundle)
foo.app/Contents/Info.plist
foo.app/Contents/MacOS
foo.app/Contents/MacOS/foo<theexecutable
foo.app/Contents/PkgInfo
foo.app/Contents/Resources
foo.app/Contents/Resources/icon.icns<theiconforthisprogram

Soifyouhavejusta'foo'executablelyingaround,youcancreateabundleforitviatheseunixcommands:
mkdirfoo.app
mkdirfoo.app/Contents
mkdirfoo.app/Contents/Resources
mkdirfoo.app/Contents/MacOS
echoAPPLnone>foo.app/Contents/PkgInfo
cp/some/where/yourapp/foofoo.app/Contents/MacOS
chmod755foo.app/Contents/MacOS/foo
cat<<EOF>foo.app/Contents/info.plist
<?xmlversion="1.0"encoding="UTF8"?>
<!DOCTYPEplistSYSTEM"file://localhost/System/Library/DTDs/PropertyList.dtd">
<plistversion="0.9">
<dict>
<key>CFBundleName</key>
<string>foo</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>59</string>
<key>CFBundleShortVersionString</key>
<string>1.1</string>
<key>CFBundleSignature</key>
<string>none</string>
</dict>
</plist>
EOF

That'saboutassimpleasitcangetnoiconsorotherfrills.(Tosetupicons,seethenextsection)
Foradifferentexecutablename,justchangealltheinstancesof'foo'intheabovetothenameofyouractualapplication.
Youdon'thavetoworryabouttheabove'cp'commandstrippingoffyourexecutable'sresourcefork,asOSXwilllookatthe
otherfilestodeterminetheresourceinformation,assumingyouinvoketheapplicationbyeither:
open/path/to/foo.app
..orbybrowsingtheFindertothedirectoryinwhichthefoo.appsubdirectorylives.TheFinderwillshowthe"foo.app"directory
asanapplication,notadirectory.Whenyoudoubleclickonit,theFinderwillopenyourapp.Therewillbenoindicationit'sa
directory.OnlytheUnixcommandlinetools(likecd,ls,etc)willshowfoo.appasadirectory.TheFindertreatesthe".app"
extensionasaspecialentity,andlooksintothedirectorytoseeiftheContentsandContents/MacOSsubdirsexisttodetermine
whatkindof'bundle'thisis..inthiscase,an'executablebundle'.
Togetyourapplicationtorunfromtheunixcommandline,youcanputashellscriptinyourbindirectorythatrunstheapp
usingthe'open'command(above).
ForactualOSXexamplesofbundles,lookinyourmachine's/Applicationsdirectoryifyousniffaroundwith'lsla',you'llsee
http://seriss.com/people/erco/fltk/

49/88

8/11/2015

Erco'sFLTKCheatPage

mostOSXapplicationsareimplementedas'bundles'(eg."Terminal.app","Mail.app",etc)

HowtomakeiconsforyourFLTKbundle
UnderOSX,GUIapplicationsshouldbe'released'asbundles,soyoucaneasilyassignresourcestoit,suchasicons.
OnceyouhaveyourMacBundleworking,youcanassociateaniconwithit,usingthesesteps.
1)Createanice128x128squareiconimage.
Makesureitisoptimizedforviewingat128x128pixels,andisconsistentwithApple'sartisticrecommendations.
Usean8bitalphachannelinyourimage,sothatpartsofyouriconcanbe'seethrough'.I'vefoundGIMPworks
perfectlywellforgeneratingMaciconswithalphachannels.
Whenfinished,saveyouriconasaPNGfilewiththealphachannelintact.
Ifneedbe,makeseparate32x32and16x16versionsoftheiconifitdoesn'totherwisescalewell.Inmostcasesthis
isn'tneeded,asmosticonsdrawnat128x128willbeautomaticallyscaledbyApple'sIconComposer(inthe
followingsteps)andlookfine.Butifyourimage/doesn't/scalewell,makingseparate32x32and16x16images
manuallyoptimizedwillhelpOSXbettershowyouriconwhenitneedstoanimatetheiconssizefortheDock,or
whentheusersetsasmalliconviewingsizeintheFinder.
2)Run"IconComposer"toimporttheapplication'sicon:
OSX10.3.x:open'/Developer/Applications/IconComposer.app'
OSX10.4.x:open'/Developer/Applications/Utilities/IconComposer.app/'

3)InIconComposer,useFile>ImporttoloadyourPNGicon(s).
Or,Ibelieveyoucansimply'draganddrop'yourimageintooneoftheappropriateboxesintheIconComposer
interface.
Theprogramletsyouloadmultipleicons,andintheImportfilebrowser,letsyouchoosewhatthedestination
resolutionwillbeforeachfileyouimport.
Ifthefileisn'talreadythecorrectsize,IconComposerwillrescaleitforyou(afterfirstpostingawarningdialog).
4)Importyour128x128pngimage.
At/minimum/giveita128x128icon,sothedockcanscaleitdown.
However,Irecommendusinga16x16,32x32and128x128icon,asthatiswhatMacOSX'sownTerminalprogram
uses.
DIGRESSION:YoucanprovethistoyourselfbybrowsingtheTerminalapplication'siconsfileusingthe"icns
Browser"[sic]utility:
OSX10.3.x:open'/Developer/Applications/icnsBrowser.app/'
OSX10.4.x:open'/Developer/Applications/Utilities/icnsBrowser.app/'

UseFile>OpentoopentheTerminal'siconfile:
/Applications/Utilities/Terminal.app/Contents/Resources/icon.icns
5)File>Savetheresultasfoo.app/Contents/Resources/icons.icns
6)Adda"CFBundleIconFile"tagtoyourfoo.app/Contents/info.plistfile.
Edityourinfo.plistfiletoincludethetexthighlighedinred:
<?xmlversion="1.0"encoding="UTF8"?>
<!DOCTYPEplistSYSTEM"file://localhost/System/Library/DTDs/PropertyList.dtd">
<plistversion="0.9">
<dict>
<key>CFBundleName</key>
<string>foo</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>59</string>
<key>CFBundleShortVersionString</key>
<string>1.1</string>
<key>CFBundleIconFile</key>

http://seriss.com/people/erco/fltk/

50/88

8/11/2015

Erco'sFLTKCheatPage
<string>icons.icns</string>
<key>CFBundleSignature</key>
<string>none</string>
</dict>
</plist>

FormoreinfoontheInfo.plistfile,ifyou'rereallycurious,seeAppleTechNote2013,andApple'sreleasenoteson
Info.Plistfile.(Sorryifeitherofthosetwolinksgostale..blameApple,whoisconstantlymovingthingsaround.)
7)That'sit.
Whenyou'redone,youshouldendupwithsomethinglike:
rwrr1rootwheel575Jun52008foo.app/Contents/Info.plist<shouldhavethiscontents
rwrr1rootwheel9Jun52008foo.app/Contents/PkgInfo<shouldcontain'APPLnone'
rwxrxrx1rootwheel1637196Jun52008foo.app/Contents/MacOS/foo<yourexecutable
rwrr1rootwheel26978Jun52008foo.app/Contents/Resources/icon.icns<theiconsfilesavedfromIconComposer

The'foo.app'directoryshouldshowupinthefinderas'foo',withyouricononit,andyoushouldbeableto:
Doubleclickon'foo'torunyourapp.
Drag'foo'ontothedesktop.
Drag'foo'ontotheDock,andwatchitanimatethesize..!
IftheFinder/doesn't/showyourfoo.appdirectoryas'foo'withyouricon,thenyoumightneedto'wakeup'thefinder
byrestartingit.Ifoundthatjust'kill'ingtheFinderprocessworksfine:
1)FindthepidoftheFinder:
[root@yourhost]#psaxww|grepFinder
8125??S0:03.72/System/Library/[..]acOS/Finderpsn_0_4325377
8141stdUV+0:00.84grepFinder

2)Killit:
[root@yourhost]#kill8125
(Findergoesaway,thencomesback)

..thiswillcausethefindertodefinitelyreloadyouricon.
IftheFindershowsyourappasafolder,thenyoudidsomethingwrongwhenyoucreatedthedirectorytree,orthe
filesinit.Checkfilenamecase,permissions,andcontentsforerrors.
CAVEATS
OfinterestyoucanmaketheGUIsaccessablefromtheterminalcommandlinebymakingasmallwrapperscriptthat
invokesyourappwithopen(1):
#!/usr/bin/perl
exec("open/some/path/foo.app")

Ifyoumakethatanexecutablescriptandputitintheuser'sPATH,userscaninvoketheprogramfromashellpromptjust
likeanyotherunixprogram,ie.withoutneedingtotype'open'andanabsolutepath.
NOTE:Idon'tthinkthere'scurrentlyanywaytopasscommandlineargumentsthrough'open',whenusedasabove.This
will(hopefully)changeinfuturereleasesofOSX.Bewaretoo:OSXmaypassaweird"psn"commandlineargumentto
yourappwheninvokedvia'open',eg.'foopsn_0_12345',somakesurethatifyourappparsesthecommandlinefor
arguments,thatitignorethispsnXXXXstuff.

Howtomakeapopupnumerickeypadfortouchscreens
Demonstrateshowtocreateaninputwidgetfortouchscreenapplications,sothatyoucantouchonaninputwidget,andenter
datausingthetouchscreen.Thisexampleshowsenteringofnumericdataonly,butamoreelaborateexamplecanbederived
toemulateafullkeyboardaswell.

http://seriss.com/people/erco/fltk/

51/88

8/11/2015

Erco'sFLTKCheatPage

SimpleNumericKeypadforTouchScreenApplications
//DemonstratehowtouseFl_Inputinatouchscreenapplicationerco08/25/06
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Input.H>
#include<FL/Fl_Button.H>
classMyNumPad:publicFl_Window{
Fl_Input*in//inputpreview
Fl_Callback*enter_cb//callbackwhenuserhits'enter'
void*enter_data
//Handlenumerickeypadbuttonspressed
voidButton_CB2(Fl_Widget*w){
Fl_Button*b=(Fl_Button*)w
if(strcmp(b>label(),"Del")==0){//handleDelete
//Delete
if(in>mark()!=in>position())in>cut()
elsein>cut(1)
}
elseif(strcmp(b>label(),"Ent")==0){//handleenterkey
//Do'Enter'callback
if(enter_cb)(*enter_cb)(in,enter_data)
}
else{//handleallotherkeys
//Appendslabelofbutton
in>replace(in>position(),in>mark(),b>label(),1)
}
}
staticvoidButton_CB(Fl_Widget*w,void*data){
MyNumPad*numpad=(MyNumPad*)data
numpad>Button_CB2(w)
}
public:
MyNumPad(intX,intY,intW=100,intH=140,constchar*L=0):Fl_Window(X,Y,W,H,L){
constintbsize=20
//Previewinput
in=newFl_Input(X+10,Y+10,W20,20)
//Numerickeypad
Fl_Button*b
intcolstart=10,
col=colstart,
row=in>y()+in>h()+10
b=newFl_Button(col,row,bsize,bsize,"7")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"8")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"9")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"Del")b>callback(Button_CB,(void*)this)b>labelsize(10)
col=colstartrow+=b>h()
b=newFl_Button(col,row,bsize,bsize,"4")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"5")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"6")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"")b>callback(Button_CB,(void*)this)col=colstartrow+=b>h()
b=newFl_Button(col,row,bsize,bsize,"1")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"2")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"3")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"+")b>callback(Button_CB,(void*)this)col=colstartrow+=b>h()
b=newFl_Button(col,row,bsize,bsize,".")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize,bsize,"0")b>callback(Button_CB,(void*)this)col+=b>w()
b=newFl_Button(col,row,bsize*2,bsize,"Ent")b>callback(Button_CB,(void*)this)col+=b>w()b>color(10)
end()
enter_cb=0
enter_data=0
}
//Returncurrentvalue
constchar*value(){
return(in>value())
}
//Clearcurrentvalue
voidclear(){
in>value("")
}
//SetcallbackforwhenEnterispressed
voidSetEnterCallback(Fl_Callback*cb,void*data){
enter_cb=cb
enter_data=data
}
}
classMyInput:publicFl_Input{
MyNumPad*numpad//localinstanceofnumerickeypadwidget
//Calledwhenuserfinishesenteringdatawithnumerickeypad
voidSetNumPadValue_CB2(){
value(numpad>value())//passvaluefromnumpadtoourinput
numpad>hide()//hidenumpad
}
staticvoidSetNumPadValue_CB(Fl_Widget*,void*data){
MyInput*in=(MyInput*)data
in>SetNumPadValue_CB2()
}
//Handlewhenuserrightclicksonourinputwidget

http://seriss.com/people/erco/fltk/

52/88

8/11/2015

Erco'sFLTKCheatPage
inthandle(inte){
intret=0
switch(e){
//Mouseclickoninputfield?Opennumpaddialog..
caseFL_PUSH:
if(Fl::event_button()==FL_LEFT_MOUSE){ret=1}
break
caseFL_RELEASE:
if(Fl::event_button()==FL_LEFT_MOUSE){
ret=1
if(!numpad)numpad=newMyNumPad(0,0)
numpad>SetEnterCallback(SetNumPadValue_CB,(void*)this)
numpad>position(parent()>x(),parent()>y())
numpad>clear()
numpad>show()
}
break
}
return(Fl_Input::handle(e)?1:ret)
}
public:
MyInput(intX,intY,intW,intH,constchar*L=0):Fl_Input(X,Y,W,H,L){
numpad=0
}
}
intmain(intargc,char**argv){
Fl_Windowwin(400,50)
MyInputin(150,10,200,30,"Value:")
in.value("clickhere")
win.end()
win.resizable(win)
win.show()
return(Fl::run())
}

Drawingintooverlayplanes
Ifyou'rejustdrawingrectanglesintotheoverlayplane,youcanjustusefl_overlay_rect(x,y,w,h).
Butformorecomplexgraphics,orgraphicswherethechildwidgetswanttodefinetheoverlaydrawingbehavior,here'san
examplethatshowshowtoregisteranarrayofcallbackstotheparentFl_Overlay_Windowsothatitcancallthechildrenwhen
drawingneedstobedone.
Inthefollowingexample,resizethewindowtocausetheoverlaystoredraw.Youwoulduseyourownmechanism(Timer,
events)tochangetheoverlays.TheexampledrawsarandomcoloredXovereachofthefourinstancesofthecustom
Fl_Group's.(Theuseofrandomcolorsmakesitclearwhentheoverlayisredrawn.)

HowChildWidgetsCanDrawIntoOverlayPlanes
//Demonstrateusingcallbackstodrawintooverlayserco8/23/06
#include<stdlib.h>
#include<vector>
usingnamespacestd
#include<FL/Fl.H>
#include<FL/Fl_Overlay_Window.H>
#include<FL/Fl_Group.H>
#include<FL/fl_draw.H>
typedefvoid(OverlayCallback)(void*)
classMyOverlayWindow:publicFl_Overlay_Window{
vector<OverlayCallback*>oly_callbacks//arrayofchildcallbackstodrawoverlays
vector<void*>oly_data//arrayofchilduserdata
public:
MyOverlayWindow(intW,intH,constchar*L=0):Fl_Overlay_Window(W,H,L){
}
//SETUPANOVERLAYDRAWINGCALLBACK
//Calledbychildwidgetstoarrangecallbacktodrawintooverlayplane.
//
voidAddOverlayCallback(OverlayCallback*cb,void*data){
oly_callbacks.push_back(cb)//addcallbacktoarray
oly_data.push_back(data)//adduserdatatoarray
}
//INVOKECHILDREN'SCALLBACKSTODRAWOVERLAYS
voiddraw_overlay(){
//Invokeallthechildren'soverlaycallbacks
for(unsignedintt=0t<oly_callbacks.size()t++){
(*oly_callbacks[t])(oly_data[t])
}
}
}
classMyGroup:publicFl_Group{
MyOverlayWindow*oly
//DRAWTHEOVERLAYGRAPHICFORTHISINSTANCEOFCHILD
staticvoidOverlayCallback(void*data){
MyGroup*o=(MyGroup*)data
//Drawarandomcolored'x'
fl_color(rand()%8)
fl_line(o>x(),o>y(),o>x()+o>w(),o>y()+o>h())
fl_line(o>x(),o>y()+o>h(),o>x()+o>w(),o>y())
}
public:

http://seriss.com/people/erco/fltk/

53/88

8/11/2015

Erco'sFLTKCheatPage
MyGroup(MyOverlayWindow*win,intX,intY,intW,intH,constchar*L=0):Fl_Group(X,Y,W,H,L){
oly=win
win>AddOverlayCallback(OverlayCallback,(void*)this)
end()
}
voiddraw(){
Fl_Group::draw()
oly>redraw_overlay()//tellparenttoredrawchildoverlays
}
}
intmain(intargc,char**argv){
//Createoverlaywindow
MyOverlayWindowwin(400,400)
//Createfourchildgroups,eachwithitsownoverlaygraphic
MyGroupg1(&win,0,0,200,200)
MyGroupg2(&win,200,0,200,200)
MyGroupg3(&win,0,200,200,200)
MyGroupg4(&win,200,200,200,200)
win.end()
win.resizable(win)
win.show()
return(Fl::run())
}

ThumbnailScrollerWithLabels
Someoneaskedabouttheissueofhowtodrawthumbnailimagesinsideascrollerwithlabels,becausewhenthelabelswere
drawnoutsidethethumbnailwidget,thetoprowoflabelswouldtruncateoff,duetohowthescrollerclips.
Here'sonewaytodoitbyderivingaclassfromFl_Box,anddrawingtheimageandlabelinacustomdrawroutine.Theresult
oftheabovecodeexamplecreatesawindowthatlookslikethis:

DemoofDrag+Drop(DND)withFLTK
Here'sasimpledemoofdrag+dropwithFLTK.
Whenyouruntheprogram,justdragtheredsquareovertothegreensquaretoshowa'draganddrop'sequence.
Credit:ThankstoMichaelSephton'soriginalexamplepostedtofltk.generalsomecodecleanupandeventhandle()er
modificationswereadded.

DragAndDrop
#include<stdio.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Box.H>
//
//DemoofDrag+Drop(DND)fromredsendertogreenreceiver
//

//SENDERCLASS
classSender:publicFl_Box{
public:
//SenderCtor
Sender(intx,inty,intw,inth):Fl_Box(x,y,w,h){
box(FL_FLAT_BOX)color(9)label("Dragfromhere")

http://seriss.com/people/erco/fltk/

54/88

8/11/2015

Erco'sFLTKCheatPage
}
//Sendereventhandler
inthandle(intevent){
intret=Fl_Box::handle(event)
switch(event){
caseFL_PUSH://do'copy/dnd'whensomeoneclicksonbox
Fl::copy("message",7,0)
Fl::dnd()
ret=1
break
}
return(ret)
}
}
//RECEIVERCLASS
classReceiver:publicFl_Box{
public:
//ReceiverCtor
Receiver(intx,inty,intw,inth):Fl_Box(x,y,w,h){
box(FL_FLAT_BOX)color(10)label("tohere")
}
//Receivereventhandler
inthandle(intevent){
intret=Fl_Box::handle(event)
switch(event){
caseFL_DND_ENTER://return(1)fortheseeventsto'accept'dnd
caseFL_DND_DRAG:
caseFL_DND_RELEASE:
ret=1
break
caseFL_PASTE://handleactualdrop(paste)operation
label(Fl::event_text())
fprintf(stderr,"PASTE:%s\n",Fl::event_text())
ret=1
break
}
return(ret)
}
}
intmain(intargc,char**argv){
//Createsenderwindowandwidget
Fl_Windowwin_a(0,0,200,100,"Sender")
Sendera(0,0,100,100)
win_a.end()
win_a.show()
//Createreceiverwindowandwidget
Fl_Windowwin_b(400,0,200,100,"Receiver")
Receiverb(100,0,100,100)
win_b.end()
win_b.show()
return(Fl::run())
}

Howtousefl_draw_image()todisplayapixelbuffer

Freezeframefromanimatingdemothatdrawsintoanimagebuffer,anddisplaystheresultingimage20xpersecond.

Thisisasimpleanimateddemoofhowtodrawpixelsintoapixelbuffer,andthendisplaythatbufferinFLTKusingthe
fl_draw_image()function.

DisplayPixelBufferinFLTK
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/fl_draw.H>

http://seriss.com/people/erco/fltk/

55/88

8/11/2015

Erco'sFLTKCheatPage
#include<stdio.h>
#include<time.h>
#defineXSIZE500
#defineYSIZE500
#defineUPDATE_RATE0.05//updaterateinseconds
//DemonstratehowtodisplayapixelbufferinFLTK
//WINDOWCLASSTOHANDLEDRAWINGIMAGE
classMyWindow:publicFl_Double_Window{
unsignedcharpixbuf[YSIZE][XSIZE][3]//imagebuffer
//FLTKDRAWMETHOD
voiddraw(){
fl_draw_image((constuchar*)&pixbuf,0,0,XSIZE,YSIZE,3,XSIZE*3)
}
//TIMERCALLBACK:CALLEDTOUPDATETHEDRAWING
staticvoidRenderImage_CB(void*userdata){
MyWindow*win=(MyWindow*)userdata
win>RenderImage()
Fl::repeat_timeout(UPDATE_RATE,RenderImage_CB,userdata)
}
public:
//CTOR
MyWindow(intw,inth,constchar*name=0):Fl_Double_Window(w,h,name){
end()
RenderImage()//showfirstdrawing
//Starttimerupdating
Fl::add_timeout(UPDATE_RATE,RenderImage_CB,(void*)this)
}
//PLOTAPIXELASANRGBCOLORINTOTHEPIXELBUFFER
voidPlotPixel(intx,inty,unsignedcharr,unsignedcharg,unsignedcharb){
pixbuf[y][x][0]=r
pixbuf[y][x][1]=g
pixbuf[y][x][2]=b
}
//MAKEANEWPICTUREINTHEPIXELBUFFER,SCHEDULEFLTKTODRAWIT
voidRenderImage(){
staticunsignedchardrawcount=0
for(intx=0x<XSIZEx++)
for(inty=0y<YSIZEy++)
PlotPixel(x,y,x+drawcount,y+drawcount,x+y+drawcount)
++drawcount
redraw()
}
}
intmain(intargc,char**argv){
Fl::visual(FL_RGB)//preventsditheringonsomesystems
MyWindow*win=newMyWindow(XSIZE,YSIZE)
win>show()
return(Fl::run())
}

OpeningWIN32FileChooserfromFLTK

SimpledemonstrationofopeningaWIN32filechooserfromwithinFLTK.AllthevariousWIN32filechoosers(Open,Save,
Directory,Mutliselect,etc)canbeaccessedfromFLTKusingsimilarWIN32specifictechniques.
(Or,justusetheFl_Native_File_Chooserwidget,toavoidWIN32specificcodeinyourapp.)
http://seriss.com/people/erco/fltk/

56/88

8/11/2015

Erco'sFLTKCheatPage

FLTK+WIN32FileChooser
#include<windows.h>
#include<commdlg.h>//OPENFILENAME,GetOpenFileName()
#include<stdio.h>
#include<string.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
//HOWTOMIXTHEWINDOWSFILEBROWSERWITHFLTK
OPENFILENAMEofn//global
voidBrowse_CB(Fl_Widget*,void*){
//OPENWINDOWSFILEBROWSER
//ThefollowingisWIN32specificcode,andthereforenotprettyand'nonfltkish')
//
if(ofn.lpstrFile){delete[]ofn.lpstrFile}
if(ofn.lpstrInitialDir){delete[]ofn.lpstrInitialDir}
memset((void*)&ofn,0,sizeof(ofn))
ofn.lStructSize=sizeof(OPENFILENAME)
ofn.Flags|=OFN_NOVALIDATE//preventdisablingoffrontslashes
ofn.Flags|=OFN_HIDEREADONLY//hidereadonlyflag
ofn.Flags|=OFN_EXPLORER//use'newer'explorerwindows
ofn.Flags|=OFN_ENABLESIZING//allowwindowtoberesized
ofn.Flags|=OFN_NOCHANGEDIR//preventdialogformessingupthecwd
ofn.nMaxFile=40961
ofn.lpstrFile=newchar[4096]
ofn.lpstrFile[0]=0
ofn.hwndOwner=GetForegroundWindow()
ofn.lpstrTitle="Opensomefile"
interr=GetOpenFileName(&ofn)
if(err==0){
err=CommDlgExtendedError()//extendederrorcheck
if(err==0)return//userhit'cancel'
fprintf(stderr,"CommDlgExtendedError()code=%d",err)
return
}
printf("Userpicked'%s'\n",ofn.lpstrFile)
}
intmain(){
Fl_Windowwin(200,200)
Fl_Buttonbut(10,10,100,25,"Browse")
but.callback(Browse_CB)
win.end()
win.show()
memset((void*)&ofn,0,sizeof(OPENFILENAME))
return(Fl::run())
}

Fl_Groupclipschildrenofevents,butnotgraphics
DemonstrationofacommonproblemwherechildrenofanFl_Groupwon'treceivemouseeventsonareasofthewidgetsthat
layoutsidetheparentgroup'sxywharea,eventhoughthechildrenwillstilldrawcorrectly(ie.eventswillbeclipped,butnotthe
drawingofchildren'sgraphicelements)
Bydefault,Fl_Groupdoesnotclipdrawingofchildren.Thisismainlyforspeedefficiency,tokeeptheclippingstacksizesmall
indeepgrouphierarchies.
Butduetohoweventsaredelivered,childrenthatlayoutsidetheparentgroup'sboundingareawillnotreceivemouseevents.
Forchildrenthatarepartiallyoutsidetheparent'sxywharea,onlythepartsofthechildinsidetheparent'sperimeterwillbe
sensitivetomouseevents.

Fl_GroupEventvs.VisualClipping
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
//
//Demonstrateclippingproblemwithwidgetsoutsidetheirparent'sxywhextents
//erco04/20/08
//
Fl_Window*win=0
Fl_Group*grp=0
voidWhy_CB(Fl_Widget*,void*){
grp>box(FL_FLAT_BOX)
grp>color(FL_RED)
win>redraw()
}
intmain(){
win=newFl_Window(500,500)
grp=newFl_Group(5,5,100,155)
newFl_Button(10,10,40,40,"7")newFl_Button(60,10,40,40,"8")newFl_Button(110,10,40,40,"9")
newFl_Button(10,60,40,40,"4")newFl_Button(60,60,40,40,"5")newFl_Button(110,60,40,40,"6")
newFl_Button(10,110,40,40,"1")newFl_Button(60,110,40,40,"2")newFl_Button(110,110,40,40,"3")
grp>end()
Fl_Button*but=newFl_Button(100,400,300,25,"Whydoesn't9,6,3work?")
but>callback(Why_CB)
win>end()
win>show()
return(Fl::run())

http://seriss.com/people/erco/fltk/

57/88

8/11/2015

Erco'sFLTKCheatPage

UsingFl_Browsertomakea'verticaltabbed'dialog

DemonstrationofhowtouseanFl_Browsertoimplementa'verticaltab'styledialog.
Thisisagoodalternativetousing'tabs',sincetabshavelimitsontheamountoftextandthenumberofitems.Fl_Browser
offersscrollbarsiflistsarelarge.

VerticalTabDemo
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Hold_Browser.H>
#include<FL/Fl_Group.H>
#include<FL/Fl_Input.H>
//Demonstratea"verticaltabbed"windowdialog
//erco05/09/08
Fl_Window*win=0
Fl_Hold_Browser*bro=0
Fl_Group*grp[3]={0,0,0}
//CALLBACKFORSOMEONECLICKINGONABROWSERTAB
voidSelectGroup_CB(Fl_Widget*,void*){
//Showthe'selected'group
for(intt=0t<3t++){
if(t==(bro>value()1)){grp[t]>show()}
else{grp[t]>hide()}
}
}
intmain(){
win=newFl_Window(600,400)
//Browsertoactas"tabselector"
bro=newFl_Hold_Browser(10,10,150,40020)
bro>add("TabOne")
bro>add("TabTwo")
bro>add("TabThree")
//Makethreegroupswithdifferentcontents
grp[0]=newFl_Group(170,10,45030,40020,"EmployeeName")
grp[0]>box(FL_ENGRAVED_BOX)grp[0]>align(FL_ALIGN_INSIDE|FL_ALIGN_TOP)grp[0]>labelsize(24)
newFl_Input(170+140,160+00,200,20,"First:")
newFl_Input(170+140,160+30,200,20,"Last:")
newFl_Input(170+140,160+60,200,20,"Title:")
grp[0]>end()
grp[1]=newFl_Group(170,10,45030,40020,"EmployeeHome")
grp[1]>box(FL_ENGRAVED_BOX)grp[1]>align(FL_ALIGN_INSIDE|FL_ALIGN_TOP)grp[1]>labelsize(24)
newFl_Input(170+140,160+00,200,20,"Street:")
newFl_Input(170+140,160+30,200,20,"City:")
newFl_Input(170+140,160+60,200,20,"State:")
newFl_Input(170+140,160+90,200,20,"ZIP:")
grp[1]>end()
grp[2]=newFl_Group(170,10,45030,40020,"EmployeeContact")
grp[2]>box(FL_ENGRAVED_BOX)grp[2]>align(FL_ALIGN_INSIDE|FL_ALIGN_TOP)grp[2]>labelsize(24)
newFl_Input(170+140,160+00,200,20,"Email:")
newFl_Input(170+140,160+30,200,20,"Extension:")
newFl_Input(170+140,160+60,200,20,"ParkingSpace:")
newFl_Input(170+140,160+90,200,20,"Cell/Pager:")
grp[2]>end()
//Setacallbackforthebrowser,initializefirstselection

http://seriss.com/people/erco/fltk/

58/88

8/11/2015

Erco'sFLTKCheatPage
bro>callback(SelectGroup_CB)
bro>select(2)
SelectGroup_CB(0,0)//(updatesvisiblegroupbasedonourselect()tion)
win>show()
return(Fl::run())
}

HowtouseFl_Chart

DemonstrationofhowtouseFl_Chart.

Fl_ChartDemo
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Chart.H>
#include<math.h>
//DemonstrationofhowtouseFl_Charterco11/20/08
intmain(){
Fl_Window*win=newFl_Window(1000,480)
Fl_Chart*chart=newFl_Chart(20,20,win>w()40,win>h()40,"Chart")
chart>bounds(125.0,125.0)
for(doublet=0t<15t+=0.5){
doubleval=sin(t)*125.0
staticcharval_str[20]
sprintf(val_str,"%.0lf",val)
chart>add(val,val_str,(val<0)?FL_RED:FL_GREEN)
}
win>resizable(win)
win>show()
return(Fl::run())
}

HowtouseFl_Scrollbar

http://seriss.com/people/erco/fltk/

59/88

8/11/2015

Erco'sFLTKCheatPage

DemonstrationofhowtouseFl_Scrollbar.

Fl_ScrollbarDemo
#include<stdio.h>
#include<string.h>
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Scrollbar.H>
#include<FL/Fl_Output.H>
//
//DemonstrateFl_Scrollbarerco02/18/09
//
Fl_Double_Window*win=0
Fl_Output*out=0
Fl_Scrollbar*scrollbar=0
//Scrollbarchanged:showscrollbar'svaluewhenchanged
voidScrollbar_CB(Fl_Widget*,void*){
chars[20]
sprintf(s,"%d",scrollbar>value())
out>value(s)
}
intmain(intargc,char**argv){
win=newFl_Double_Window(500,300,"Fl_ScrollbarDemo")
{
//Createscrollbar
scrollbar=newFl_Scrollbar(0,50,500,25,"Scrollbar")
scrollbar>type(FL_HORIZONTAL)
scrollbar>slider_size(.5)//thefractionalsizeofthescrollbar'stab,1/2scollbar'ssize
scrollbar>bounds(100,200)//min/maxvalueoftheslider'spositions
((Fl_Valuator*)scrollbar)>value(150.0)//theinitialvalue(infltk1.3+youcanusescrollbar>value(150)
scrollbar>step(10)//forcesteprateto10(slidermovechangesvalue:100,110,120..)
scrollbar>callback(Scrollbar_CB,(void*)&out)
//Createoutputtoshowscrollbar'svalue
out=newFl_Output(200,150,100,40,"ScrollbarValue:")
out>textsize(24)
}
win>end()
win>show()
Scrollbar_CB(0,0)//showscrollbar'sinitialposition
return(Fl::run())
}

Howtodrawtextoveranimage
Demonstrationofderivingaclassthatdrawstextoveranimage.
NewinFLTK1.3.x:There'sanewalign()optioncalledFL_ALIGN_IMAGE_BACKDROPthatapparentlywillletyou
assignanimagetoe.g.abutton,andthetextwilldrawoverit.Thefirstexamplebelowshowshowtodothisit'scertainly
mucheasierthantheothertwoexamplesthatareneededfortheolder1.1.xreleases.
FirstexampleshowsthesimplestexampleofhowtodrawtextoveranimageusingtheFL_ALIGN_IMAGE_BACKDROPalign()
flag(newinFLTK1.3.0)toallowanimagetobeassignedtoawidget,inthiscaseabutton,suchthattheimageappears
underneaththetext.TheexampleimageisanXPMgrayscalegradientcompiledintothebinary,butcouldalsobeanimage
fromdiskloadedatruntimetoo,ifthecodeismodified.
SecondexampleusestheoldertechniquethatworkswithallversionsofFLTKthatinvolvesderivinganewwidgetthatfrom
Fl_Buttonthatdefinesacustomdraw()methodtomaketextdrawoverthexpmimageofagrayscalegradient(loadedat
compiletime,andbuiltintothebinary).
ThirdexampleshowshowtoderivefromFl_Widgettomaketextdrawoverajpegimageofcolorbarsloadedatruntime
displaysthejpegimagewithnotextuntilthebuttonispushed.Thistechniquewillalsoworkonbothold1.1.xandnew1.3.x
http://seriss.com/people/erco/fltk/

60/88

8/11/2015

Erco'sFLTKCheatPage

versionsofFLTK.
Theseexamplesshowseveralthings:howtoloadanddisplayanimage,howabuttoncallbackcanchangeawidget'slabel(),
andhowacustomwidgetcandisplayanimagewithitslabeltextovertheimage.
NoteallexamplescanbechangedtoeitheruseXPMimages(compiledintothecode),orloadfromexternalimages(fromdisk
atruntime).TheexamplesseparatelyshowJPGvs.XPMjusttoshowthedifferenttechniques.

Textoverimagedemo#1
UsingFL_ALIGN_IMAGE_BACKDROP
ThisonlyworksinFLTK1.3.xandup
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Pixmap.H>
#include"gradient.xpm"
//
//DemonstratehowtodrawtextoveranimageusingnewFLTK1.3.x"FL_ALIGN_IMAGE_BACKDROP"featureerco10/25/10
//Fortheexample'gradient.xpm'image,see:http://seriss.com/people/erco/fltk/gradient.xpm
//
intmain(intargc,char**argv){
Fl_Pixmapgradient(gradient_xpm)//see"gradient.xpm"
Fl_Window*win=newFl_Window(160,75,"test")//createwindow
Fl_Button*but1=newFl_Button(10,10,140,25,"Button1")//createcustombutton
but1>image(&gradient)//assignimagetobutton
but1>align(FL_ALIGN_IMAGE_BACKDROP|but1>align())//enablealigntouseimageasa'backdrop'
Fl_Button*but2=newFl_Button(10,40,140,25,"Button2")//createsecondinstanceofcustombutton
but2>image(&gradient)//assignsameimagetosecondinstance
but2>align(FL_ALIGN_IMAGE_BACKDROP|but2>align())//enablealigntouseimageasa'backdrop'
win>end()
win>show(argc,argv)
return(Fl::run())
}

Textoverimagedemo#2
DerivingfromFl_Button
Functionallysimilartoexample#1,butcompatiblewithFLTK1.1.xand1.3.x.Derivesacustomwidget.
Ifyou'reusing1.3.x,youcanusethesimplerFL_ALIGN_IMAGE_BACKDROPtechnique.
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Pixmap.H>
#include<FL/fl_draw.H>
#include"gradient.xpm"
//
//Demonstratehowtodrawtextoveranimageinabuttonerco10/25/10
//Fortheexample'gradient.xpm'image,see:http://seriss.com/people/erco/fltk/gradient.xpm
//
classMyButton:publicFl_Button{//CreateacustomwidgetderivedfromFl_Button
Fl_Pixmap*img//willcontaintheimage(inthiscase,anxpm)
voiddraw(){//Takefullcontrolofdrawingourwidget
Fl_Button::draw()//tellbuttontodrawitselffirst
if(img){
//Handleimageoffsetstobeinsidebutton'sborder
intX=x()+Fl::box_dx(box())
intY=y()+Fl::box_dy(box())
intW=w()Fl::box_dw(box())
intH=h()Fl::box_dh(box())
img>draw(X,Y,W,H)//drawimageoverbutton
}
if(label()){//anylabelassigned?
fl_font(labelfont(),labelsize())//setfont/size
fl_color(labelcolor())//setcolor
fl_draw(label(),x(),y(),w(),h(),align())//drawtextoverimageandbackground
}
}
public:
MyButton(intX,intY,intW,intH,constchar*L):Fl_Button(X,Y,W,H,L){//ctor

http://seriss.com/people/erco/fltk/

61/88

8/11/2015

Erco'sFLTKCheatPage
img=0
}
voidimage(Fl_Pixmap*val){
img=val
}
}
intmain(intargc,char**argv){
Fl_Pixmapgradient(gradient_xpm)//see"gradient.xpm"
Fl_Window*win=newFl_Window(160,75,"test")//createwindow
MyButton*but1=newMyButton(10,10,140,25,"Button1")//createcustombutton
but1>image(&gradient)//assignimagetobutton
MyButton*but2=newMyButton(10,40,140,25,"Button2")//createsecondinstanceofcustombutton
but2>image(&gradient)//assignsameimagetosecondinstance
win>end()
win>show(argc,argv)
return(Fl::run())
}

Textoverimagedemo#3
DerivingfromFl_Widget
CompatiblewithFLTK1.1.xand1.3.x.Derivesacustomwidget.
Ifyou'reusing1.3.x,youcanusethesimplerFL_ALIGN_IMAGE_BACKDROPtechnique
usinganFl_BoxinsteadofFl_Widget.
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_JPEG_Image.H>
#include<FL/fl_draw.H>
//
//Demonstratehowtodrawtextoveranimageerco02/20/09
//Fortheexample'colorbars.jpg'image,see:http://seriss.com/people/erco/fltk/colorbars.jpg
//
classMyImage:publicFl_Widget{//Createacustomwidget
Fl_JPEG_Image*jpg//willcontainthejpegimage
voiddraw(){//Takefullcontrolofdrawingourwidget
fl_color(FL_RED)fl_rectf(x(),y(),w(),h())//drawredfilledrectangleasbackground
jpg>draw(x(),y(),w(),h())//drawimageoverbackground
if(label()){//anylabelassigned?
fl_font(labelfont(),labelsize())//setfont/size
fl_color(labelcolor())//setcolor
fl_draw(label(),x(),y(),w(),h(),align())//drawtextoverimageandbackground
}
}
public:
MyImage(intX,intY,intW,intH):Fl_Widget(X,Y,W,H){//ctor
jpg=newFl_JPEG_Image("/tmp/colorbars.jpg")//loadjpegimage(changefilenameasneeded)
}
}
//Globals
Fl_Window*win=0
Fl_Button*but=0
MyImage*img=0
voidButtonCallback(Fl_Widget*,void*){//callbackinvokedwhenbuttonpressed
img>label("Yourtextgoeshere.")//labeltoshowtext
img>align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)//labeldraws'center'and'inside'thewidget
img>labelcolor(FL_WHITE)//labelcolor
img>labelsize(30)//labelsize

http://seriss.com/people/erco/fltk/

62/88

8/11/2015

Erco'sFLTKCheatPage
}
intmain(intargc,char**argv){
win=newFl_Window(660,540,"test")//createwindow
img=newMyImage(10,10,640,480)//createourcustomwidget
but=newFl_Button(300,500,120,25,"Push")//create'Push'button
but>callback(ButtonCallback)//assigncallbacktobutton
win>end()
win>show(argc,argv)
return(Fl::run())
}

OpenGLTexturemappedCube
GL_MODULATE

GL_DECAL

Demonstrationofcheckerboardtexturemappedrotatingcubewithlightsandperspectivefrustum.UsesFLTKtimertohandle
rotation,andproceduralgenerationoftexturemapped'checkerboard'image.
Cuberotatesshowingallsides.Texturemapisawhitecheckerboardthatbydefaultinheritscolorsfromthecube'spolygons,
duetoopengl'sdefaultforglTexEnv()defaultingtoGL_MODULATE.Tohavethetextureshowninitsowncolor(purewhite),
addacalltoglTexEnv()settingtheGL_DECALparameter.
Cuberotatesshowingallsides.
ThankstoLoicforcommentedcubeobjectpostedonfltk.opengl(03/17/09).

TextureMappedCube
#include<stdio.h>
#include<math.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Gl_Window.H>
#include<FL/gl.h>
//
//OpenGLspinningcubewithcheckertexturemaperco/loic03/17/09
//
#defineWIN_W400//windowwidth
#defineWIN_H400//windowheight
#defineTEX_W64//texturemapwidth
#defineTEX_H64//texturemapheight
#defineFPS(1.0/24.0)//framespersecondplayback
//
//OpenGLclasstoshowtexturemappedcube
//
classMyGlWindow:publicFl_Gl_Window{
doublespin
GLuintTexID
//TIMERCALLBACK
//Handlesrotationtheobject
//
staticvoidTimer_CB(void*userdata){
MyGlWindow*mygl=(MyGlWindow*)userdata
mygl>spin+=2.0//spin
mygl>redraw()
Fl::repeat_timeout(FPS,Timer_CB,userdata)
}

http://seriss.com/people/erco/fltk/

63/88

8/11/2015

Erco'sFLTKCheatPage
public:
//CTOR
MyGlWindow(intx,inty,intw,inth,constchar*l=0):Fl_Gl_Window(x,y,w,h,l){
spin=0.0
Fl::add_timeout(FPS,Timer_CB,(void*)this)//24fpstimer
}
//PERSPECTIVEVIEW
//SameasgluPerspective()..
//
voidPerspective(GLdoublefovy,GLdoubleaspect,GLdoublezNear,GLdoublezFar){
GLdoublexmin,xmax,ymin,ymax
ymax=zNear*tan(fovy*M_PI/360.0)
ymin=ymax
xmin=ymin*aspect
xmax=ymax*aspect
glFrustum(xmin,xmax,ymin,ymax,zNear,zFar)
}
//RESHAPEDVIEWPORT
//OpenGLstufftodowheneverwindowchangessize
//
voidReshapeViewport(){
//Viewport
glViewport(0,0,w(),h())
//Projection
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
GLfloatratio=w()/h()
Perspective(30.0,1.0*ratio,1.0,30.0)
glTranslatef(0.0,0.0,8.0)
//Modelview
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
}
//OPENGLINITIALIZATION
//OpenGLstufftodo*onlyonce*onstartup.
//
voidGlInit(){
//Makesureweonlydothisonce
staticintfirst_time=1
if(first_time){
first_time=0
//TextureMapInit
GLubyteimg[TEX_W][TEX_H][3]//afterglTexImage2D(),arrayisnolongerneeded
glGenTextures(1,&TexID)
glBindTexture(GL_TEXTURE_2D,TexID)

/***TextureMappingMode
***Uncommentoneofthefollowinglines:GL_DECALorGL_MODULATE
***/
//glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL)//useactualtexturecolors
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE)//texturecolorsaffectedbypoly'scolor

for(intx=0x<TEX_Wx++){
for(inty=0y<TEX_Hy++){
/***TexturePattern
***Uncommentoneofthefollowinglines:checkboardorbasketweave
***/
//GLubytec=((x&16)^(y&16))?((x%16)<<4):(((x%16)^15)<<4)//basketweave
GLubytec=((x&16)^(y&16))?255:0//checkerboard
img[x][y][0]=c
img[x][y][1]=c
img[x][y][2]=c
}
}
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_W,TEX_H,0,GL_RGB,GL_UNSIGNED_BYTE,&img[0][0][0])
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
glEnable(GL_TEXTURE_2D)
//MiscOpenGLsettings
glShadeModel(GL_FLAT)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
}
}
//FLTKDRAW
//CalledbyFLTKtodrawthescene.
//
voiddraw(){
//Initialize/handlereshapedviewport
if(!valid()){
valid(1)
GlInit()
ReshapeViewport()
}
//Clear
glClearColor(.5,.5,.5,0.0)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
//Setupmodelmatrix
glLoadIdentity()
glRotatef(spin,0.5,1.0,0.0)//showallsidesofcube
//Drawcubewithtextureassignedtoeachface
glBegin(GL_QUADS)
//FrontFace
glColor3f(1.0,0.0,0.0)//red
glTexCoord2f(0.0,1.0)glVertex3f(1.0,1.0,1.0)//TopLeftOfTheTextureandQuad
glTexCoord2f(1.0,1.0)glVertex3f(1.0,1.0,1.0)//TopRightOfTheTextureandQuad
glTexCoord2f(1.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomRightOfTheTextureandQuad
glTexCoord2f(0.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomLeftOfTheTextureandQuad
//BackFace
glColor3f(0.0,1.0,1.0)//cyn
glTexCoord2f(0.0,1.0)glVertex3f(1.0,1.0,1.0)//TopLeftOfTheTextureandQuad
glTexCoord2f(1.0,1.0)glVertex3f(1.0,1.0,1.0)//TopRightOfTheTextureandQuad
glTexCoord2f(1.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomRightOfTheTextureandQuad
glTexCoord2f(0.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomLeftOfTheTextureandQuad
//TopFace
glColor3f(0.0,1.0,0.0)//grn
glTexCoord2f(0.0,1.0)glVertex3f(1.0,1.0,1.0)//TopLeftOfTheTextureandQuad

http://seriss.com/people/erco/fltk/

64/88

8/11/2015

Erco'sFLTKCheatPage
glTexCoord2f(1.0,1.0)glVertex3f(1.0,1.0,1.0)//TopRightOfTheTextureandQuad
glTexCoord2f(1.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomRightOfTheTextureandQuad
glTexCoord2f(0.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomLeftOfTheTextureandQuad
//BottomFace
glColor3f(1.0,0.0,1.0)//mag
glTexCoord2f(0.0,1.0)glVertex3f(1.0,1.0,1.0)//TopLeftOfTheTextureandQuad
glTexCoord2f(1.0,1.0)glVertex3f(1.0,1.0,1.0)//TopRightOfTheTextureandQuad
glTexCoord2f(1.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomRightOfTheTextureandQuad
glTexCoord2f(0.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomLeftOfTheTextureandQuad
//Rightface
glColor3f(0.0,0.0,1.0)//blu
glTexCoord2f(0.0,1.0)glVertex3f(1.0,1.0,1.0)//TopLeftOfTheTextureandQuad
glTexCoord2f(1.0,1.0)glVertex3f(1.0,1.0,1.0)//TopRightOfTheTextureandQuad
glTexCoord2f(1.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomRightOfTheTextureandQuad
glTexCoord2f(0.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomLeftOfTheTextureandQuad
//LeftFace
glColor3f(1.0,1.0,0.0)//yel
glTexCoord2f(0.0,1.0)glVertex3f(1.0,1.0,1.0)//TopLeftOfTheTextureandQuad
glTexCoord2f(1.0,1.0)glVertex3f(1.0,1.0,1.0)//TopRightOfTheTextureandQuad
glTexCoord2f(1.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomRightOfTheTextureandQuad
glTexCoord2f(0.0,0.0)glVertex3f(1.0,1.0,1.0)//BottomLeftOfTheTextureandQuad
glEnd()
//DEBUG:CHECKFORERRORS
GLenumerr=glGetError()
if(err!=GL_NO_ERROR){
fprintf(stderr,"GLGETERROR=%d\n",(int)err)
}
}
}
intmain(intargc,char*argv[]){
MyGlWindow*mygl=newMyGlWindow(10,10,WIN_W20,WIN_H20,"TextureTest")
mygl>end()
mygl>resizable(mygl)
mygl>show()
return(Fl::run())
}

OpenGLTextureMappedImageWithLighting
SpinningcubedemonstrationwithaPNGimagetexturemappedontothecube,withasimplelightingmodelandmaterials
applied.
ShowshowFLTK'sFl_Shared_ImageclasscanbeusedtoloadanyoftheimagetypesthatFLTKsupports,andassignthe
imageasatexturemap.
ThankstoIanMacArthurforapointertotheFl_Shared_Imageclass(whichI'dneverusedbeforeIwasgoinggoingtopost
anexamplewithFl_PNG_Imageinstead,butFl_Shared_Imageismoreflexible).
CubeobjectandnormalsnabbedfromanSGIOpenGLexamplecalledscubes.cbyMarkJ.Kilgard.

Screenshotofthisimagetexturemappedcube.cxxdemoprogram.
Iaddedalightingmodelandmaterialssothatthetexturereactstolighting.
Fortunately,Fl_Shared_Image'sinternalimageformatfor3channeldepthimagesisfullycompatiblewithopengl's
glTexImage2D()call,sono'conversion'stepisnecessarytheimagecanbeappliedwithalmosttwolinesofcode:
snip
Fl_Shared_Image*img=Fl_Shared_Image::get(filename)
/*..errorcheckingsnipped..*/

http://seriss.com/people/erco/fltk/

65/88

8/11/2015

Erco'sFLTKCheatPage

glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,img>w(),img>h(),0,GL_RGB,GL_UNSIGNED_BYTE,img>data()[0])
snip

..whichloadstheimageandassignsthetexture.Togetthelightingmodeltowork,Iusedacubeobjectandnormalsfromone
ofSGI'sexampleprogramsthatincludedprecomputednormals.(Withoutthecorrectnormalsonthecube,itlookedlikethe
lightwasmovingaroundeventhoughitwasstationary..!)

UTF8JapaneseTest
DemonstrationofJapaneseUTF8textdisplay.

ThisisascreenshotunderUbuntuofthisutf8japanesesongs.cxxdemoprogram.
UnderUbuntu,IhadtomakesureJapanesefontswereinstalled,eg:
aptgetinstallxfontsintljapanese

..andinmycase,Ineededtomakesurethefollowinglinewasuncommented:
Fl::set_font(FL_HELVETICA,"KochiGothic")//uncommentforlinux

..forthetexttodisplayusingKochiGothic.YoumayneedtocommentoutthislineorchangeitforyourspecificOS.

AlphaBlendingwithPNGfiles
DemonstrationofalphablendingthesetwoPNGfilesoverawidget:

http://seriss.com/people/erco/fltk/

66/88

8/11/2015

Erco'sFLTKCheatPage

leftalpha.png

rightalpha.png

Whatfollowsisthecodethatcombinesthetwoaboveimages(whichyoucandownloadbyrightclickingtosaveonyour
machine),anddisplaysthemoverthetopofthewindowwithatextstringunderneath.
Thisisonewaytodoit..inthiscaseshowingtwoimagesoveroneanother.Icouldhavealsojustassignedanimage()tothe
widgetusingthistechnique,butinthiscaseIwantedfullcontrolovertheorderinwhichthetextandimagesaredrawn.

AlphaBlendingPNGimages
#include<stdio.h>
#include<string.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Shared_Image.H>
#include<FL/Fl_PNG_Image.H>
#include<FL/fl_draw.H>
//
//Demonstrateoverlappingalphablendedimageserco06/09/09
//
classMyWindow:publicFl_Window{
Fl_PNG_Image*left
Fl_PNG_Image*right
voidGetFLTKVersion(char*s){//getfltkversioninfofordemooptional
sprintf(s,"FLTK%d.%d.%d",FL_MAJOR_VERSION,FL_MINOR_VERSION,FL_PATCH_VERSION)
}
public:
voiddraw(){
Fl_Window::draw()//Drawwindowwidgetfirst
fl_font(FL_HELVETICA,40)//setfont
fl_color(FL_BLACK)//setcolor
fl_draw("Thisisatest",10,150)//drawatextstring
left>draw(0,0)//drawleftalphaimageovertheabove
right>draw(0,0)//drawrightalphaimageovertheabove
}
MyWindow(intW,intH):Fl_Window(W,H){
chars[80]GetFLTKVersion(s)copy_label(s)//(showfltkversionoptional)
left=newFl_PNG_Image("./leftalpha.png")//assumesimagesincwd
right=newFl_PNG_Image("./rightalpha.png")//assumesimagesincwd
show()
}
}

http://seriss.com/people/erco/fltk/

67/88

8/11/2015

Erco'sFLTKCheatPage
intmain(){
fl_register_images()
MyWindowwin(256,256)
win.show()
return(Fl::run())
}

DumbTerminalEmulator

LinuxExample

WindowsExample
DemonstrateshowtomakeasimpleterminalthatletstheusertypecommandsandseetheoutputinascrollingFLTKtext
editorwidget.Inthisexampletheusercantypecommandsthatarerunintheshell[viapopen()],butyoucanchangethistorun
yourowncommands.
Update:here'salinktoaunixonlyversionthatletsyouinteractwithaunixshell.IthandlesasynchronousI/O.This
exampleisabitmorecomplicatedthanthebelow,becauseitusingthreadstoachieveasyncI/O,andusesbidirectional
pipestohandlebothstdinandstdout/err.

DumbTerminalEmulator
http://seriss.com/people/erco/fltk/

68/88

8/11/2015

Erco'sFLTKCheatPage
#include<string.h>
#include<stdio.h>
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Text_Editor.H>
#ifdef_WIN32
#definepopen_popen
#definepclose_pclose
#endif
//
//Simpleterminalsimulator(PROOFOFCONCEPT)
//1.00erco07/30/2009initialimplementation
//1.10erco09/06/2009useFl::event_text()tohandlenonasciicodes
//
classMyTerminal:publicFl_Text_Editor{
Fl_Text_Buffer*buff
charcmd[1024]
public:
MyTerminal(intX,intY,intW,intH,constchar*L=0):Fl_Text_Editor(X,Y,W,H,L){
buff=newFl_Text_Buffer()
buffer(buff)
textfont(FL_COURIER)
textsize(12)
cmd[0]=0
}
//Appendtobuffer,keepcursoratend
voidappend(constchar*s){
buff>append(s)
//Gotoendofline
insert_position(buffer()>length())
scroll(count_lines(0,buffer()>length(),1),0)
}
//Runthespecifiedcommandintheshell,appendoutputtoterminal
voidRunCommand(constchar*command){
append("\n")
fprintf(stderr,"EXECUTING:'%s'\n",command)
FILE*fp=popen(command,"r")
if(fp==0){
append("Failedtoexecute:'")
append(command)
append("'\n")
}else{
chars[1024]
while(fgets(s,sizeof(s)1,fp)){
append(s)
}
pclose(fp)
}
}
//HandleeventsintheFl_Text_Editor
inthandle(inte){
switch(e){
caseFL_KEYUP:{
intkey=Fl::event_key()
if(key==FL_Enter)return(1)//hideEnterfromeditor
if(key==FL_BackSpace&&cmd[0]==0)return(0)
break
}
caseFL_KEYDOWN:{
intkey=Fl::event_key()
//Enterkey?Executethecommand,clearcommandbuffer
if(key==FL_Enter){
//Executeyourcommandshere
strcat(cmd,"2>&1")//stderr+stdout
RunCommand(cmd)
cmd[0]=0
append("\nEnterashellcommand:")
return(1)//hide'Enter'fromtextwidget
}
if(key==FL_BackSpace){
//Removeacharacterfromendofcommandbuffer
if(cmd[0]){
cmd[strlen(cmd)1]=0
break
}else{
return(0)
}
}else{
//Appendtexttoour'command'buffer
strncat(cmd,Fl::event_text(),sizeof(cmd)1)
cmd[sizeof(cmd)1]=0
}
break
}
}
return(Fl_Text_Editor::handle(e))
}

http://seriss.com/people/erco/fltk/

69/88

8/11/2015

Erco'sFLTKCheatPage
}
intmain(){
Fl_Double_Windowwin(620,520,"TerminalTest")
MyTerminaledit(10,10,win.w()20,win.h()20)
edit.append("Lineone\nLineTwo\nEnterashellcommand:")
win.resizable(win)
win.show()
return(Fl::run())
}

ToolbarWidgetwithFl_Pack

DemonstrateshowtomakeasimpletoolbaroutofanFl_PackandFl_Button.YoucanexpandtheMyToolbarclasstoadd
morefunctionality,suchasallowingtheusertographicallymoveorremoveicons..
Theiconsusedhereareforexamplepurposesonly.TheseiconswerescreengrabbedfromthetoolbarofLinux"OpenOffice"
usingGimp,thensavedasanxpm.Thenthexpmcontentswaspasteddirectlyintothecodebelow.Foryourownapplication,
toavoidcopyrightinfringement,makeyourownicons,oruseiconsthatarereleasedunderopensourceorcreativecommons.

ToolbarWidget
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Pack.H>
#include<FL/Fl_Button.H>
#include<FL/Fl_Pixmap.H>
//
//Exampleofhowtomakeatoolbarwidgetwithicons
//erco1.005/24/10
//
staticconstchar*open_xpm[]={//XPM
"2525161",
"c#766E67",".c#817C78","+c#B18563","@c#E97E25",
"#c#D28445","$c#9D9791","%c#F4882A","ac#F1963B",
"*c#AFAAA3","=c#F4AB6E","c#C8C5C1","c#F2C092",
"xc#F7CCA4",",c#DEDDDA","'c#F3DECD",")cNone",
")))))))))))))))))))))))))",//openicon(nabbedfromlinuxstarofficeuseyourown!)
")))))))..........)))))))",
"))))))).)))))))),,*))))))",
"))))))).)))))))),,)*)))))",
"))))))).)))))))),))*))))",
"))))))).)),,))),*,*)))",
"),$$$$$))))))))*$$*))",
")*))))).)),,,,,,$$*.))",
")*)x===+)),,,,,,,*,.))",
")*))))).),,,,,,,,,,.))",
")*))))).),,,,*$$$$$**)",
")*)),..$$$$$*x'''''''=*)",
")*),+'''''''''====#)",
")$)====xxxxxxx+,)",
")$)*=====+))",
")$)+===========aaaaaa.))",
")$,#===#=aaaaaaaaaaaa#.))",
")$#a%%@aaaaaaaaaaaaa+.))",
")$+@%@%@aaaaaaaaaaaaa*.))",
")$#%%%%%%%%%%%%%%%%%a.*))",
").#@@@@@@aaaaaaaaaaa#)))",
").$,))",
")),,,,,,,,,,,,,,,,,,,,)))",
")))))))))))))))))))))))))",
")))))))))))))))))))))))))"
}
staticconstchar*save_xpm[]={//XPM
"2525161",
"c#684467",".c#7A5279","+c#626461","@c#757172",
"#c#9D6D9C","$c#888382","%c#969499","ac#ACA7AC",
"*c#BABAC4","=c#CACBD4","c#D2D3DD","c#E5E3E8",
"xc#E9E9F3",",cNone","'c#F7F6FA",")c#FEFFFC",
",,,,,,,,,,,,,,,,,,,,,,,,,",
",,,,,,,,,,,,,,,,,,,,,,,,,",//saveicon(nabbedfromlinuxstarofficeuseyourown!)

http://seriss.com/people/erco/fltk/

70/88

8/11/2015

Erco'sFLTKCheatPage

",a$$$$$$$@$$$$$$$$@$$$=,,",
",$'xxxxx%))))))))%$,,",
",$x=****%xxxx%%%'%**x$,,",
",$x=****%xxxx%*%'a**x$,,",
",$x=****%xxxx%*%'a**x$,,",
",$x=****%xxxx%*%%**x$,,",
",$x=****%xx%%%%**x$,,",
",$x****%x)))%==x$,,",
",$x****%%%%%%%%%%==x$,,",
",$x==x$,,",
",$x**************==x$,,",
",$x''''''''''''''==x$,,",
",$x''''''''''''''==x$,,",
",$x''==x$,,",
",$x''''''''''''''==x$,,",
",$x''==x$,,",
",$x==''''''''''''''==x$,,",
",$x==''==x$,,",
",$x==''''''''''''''==x$,,",
",$aaa###########...**x$,,",
",$xxx.........xxx$,,",
",a@++++++++++++++++++@a,,",
",,,,,,,,,,,,,,,,,,,,,,,,,"
}
classMyToolbar:publicFl_Pack{
public:
//CTOR
MyToolbar(intX,intY,intW,intH):Fl_Pack(X,Y,W,H){
type(Fl_Pack::HORIZONTAL)//horizontalpackingofbuttons
box(FL_UP_FRAME)
spacing(4)//spacingbetweenbuttons
end()
}
//ADDATOOLBARBUTTONTOTHEPACK
voidAddButton(constchar*name,Fl_Pixmap*img=0,Fl_Callback*cb=0,void*data=0){
begin()
Fl_Button*b=newFl_Button(0,0,30,30)
b>box(FL_FLAT_BOX)//buttonswon'thave'edges'
b>clear_visible_focus()
if(name)b>tooltip(name)
if(img)b>image(img)
if(cb)b>callback(cb,data)
end()
}
}
voidOpen_CB(Fl_Widget*,void*){
printf("Open..\n")
}
voidSave_CB(Fl_Widget*,void*){
printf("Save..\n")
}
intmain(){
//CREATEMAINWINDOW
Fl_Windowwin(720,486,"toolbardemo")
win.begin()
//CREATETOOLBAR
Fl_Pixmap*open_pixmap=newFl_Pixmap(open_xpm)
Fl_Pixmap*save_pixmap=newFl_Pixmap(save_xpm)
MyToolbartoolbar(0,0,win.w(),30)
toolbar.AddButton(0,open_pixmap,Open_CB)
toolbar.AddButton(0,save_pixmap,Save_CB)
toolbar.AddButton(0,open_pixmap,Open_CB)//(repeatedtosimulateseveralicons)
toolbar.AddButton(0,save_pixmap,Save_CB)
toolbar.AddButton(0,open_pixmap,Open_CB)
toolbar.AddButton(0,save_pixmap,Save_CB)
win.end()
win.show()
return(Fl::run())
}

Demonstratekeyboardpress/release

http://seriss.com/people/erco/fltk/

71/88

8/11/2015

Erco'sFLTKCheatPage

Demonstrateshowtovisualizekeyboardup/downstates.
Whenyouruntheapp,typingtheq/w/ekeysonthekeyboardshouldmaketheappropriateq/w/ebuttonsgoupanddown,
shouldshiftfocustothecorrectbuttonthatchangedstate,andthecallbackshouldprintthebuttonpressedanditsup/down
state.
Thetrickyparthereisgettingbuttonstoshowtheup/downstatewhenkeyboardkeysarepressed/released.Usingshortcuts
doesn'tgetwhatyouwant,becauseshortcutsonlyinvokethecallbackonce,youdon'tgetseparatecallbacksforup/down
events,andthebuttondoesn'treflectthekey'sup/downstate.
Thetechniqueusedhereistoderiveacustomgrouptoparentthebuttons,andhavethegroup'shandle()methodtakeover
keyup/downevents,controllingtheappropriatebuttonvalue()basedonthekeypushed/released.Italsomanagesinvokingthe
button'scallback,andforcingthecorrectbuttontotakefocus.

KeyPress/ReleaseDemo
#include<stdio.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Button.H>
//Agroupofbuttons,'q','w','e'..
classMyButtonGroup:publicFl_Group{
Fl_Button*butts[3]//forsakeofexample,3buttons
staticvoidButton_CB(Fl_Widget*w,void*data){
Fl_Button*b=(Fl_Button*)w
fprintf(stderr,"Button'%s'was%s\n",b>label(),b>value()?"Pushed":"Released")
}
public:
MyButtonGroup(intX,intY,intW,intH,constchar*L=0):Fl_Group(X,Y,W,H,L){
//Createthethree'q','w','e'buttons
//Thebutton'slabel()determineswhichwillkeyboardkeyinvokesitscallback
//
box(FL_BORDER_BOX)color(46)//darkbgcolorforgroup
Fl_Button*b
inti=0
b=newFl_Button(x()+10+0,y()+10,25,25,"q")b>callback(Button_CB)butts[i++]=b
b=newFl_Button(x()+10+50,y()+10,25,25,"w")b>callback(Button_CB)butts[i++]=b
b=newFl_Button(x()+10+100,y()+10,25,25,"e")b>callback(Button_CB)butts[i++]=b
end()
}
inthandle(inte){
intret=Fl_Group::handle(e)//assumethebuttonswon'thandlethekeyboardevents
switch(e){
caseFL_FOCUS:
caseFL_UNFOCUS:
ret=1//enablesreceivingkeyboardevents
break
caseFL_SHORTCUT://incasewidgetthatisn'tourshasfocus
caseFL_KEYDOWN://keyboardkeypushed
caseFL_KEYUP://keyboardkeyreleased
{
//Walkbuttonarray,tryingtomatchbutton'slabelwiththekeyboardevent.
//Iffound,setthatbutton'svalue()basedonup/downevent,
//andinvokethatbutton'scallback()
//
for(intt=0t<3t++){
Fl_Button*b=butts[t]
if(Fl::event_key()==b>label()[0]){//eventmatchesbutton'slabel?
b>take_focus()//movefocustothisbutton
b>value((e==FL_KEYDOWN||e==FL_SHORTCUT)?1:0)//changethebutton'sstate
b>do_callback()//invokethebutton'scallback
ret=1//indicatewehandledit
}
}
break
}
}

http://seriss.com/people/erco/fltk/

72/88

8/11/2015

Erco'sFLTKCheatPage

return(ret)
}
}
intmain(intargc,char*argv[]){
Fl_Window*win=newFl_Window(200,200,"Example")
newMyButtonGroup(10,50,20020,20060)
win>begin()
(newFl_Button(10,10,25,25,"X"))>tooltip("Thisisanextrabuttonoutsidegroup"
"totestfocustakenfromotherbuttons")
win>end()
win>show()
return(Fl::run())
}

DemonstratemultipleselectioninFl_Table

DemonstrateshowtoimplementsecondaryselectioninanFl_Table.
Whenyouruntheapp,youcandragoutagreen'primaryrowselection',thenclickthe"SecondarySelection"checkbuttonin
thelowerleftcornertotoggleablue'secondaryrow/columnselection'thatcanoverlaptheprimary.

MultipleselectionsinFl_Table
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Table_Row.H>
#include<FL/Fl_Check_Button.H>
#include<FL/fl_draw.H>
//
//DemonstrateFl_Table_Rowwithmultipleselectionserco04/14/11
//(Startedwithexamples/table_simple.cxx)
//
#defineMAX_ROWS100
#defineMAX_COLS100
//DeriveaclassfromFl_Table_Row
classMyTable:publicFl_Table_Row{
intsecondary_selection[4]//secondaryselectionleft/right/top/bottomvalues
//(left/rightarecolumn#'s,top/botarerow#'s)
//Drawtherow/colheadings
//Makethisadarkthinupboxwiththetextinside.
//
voidDrawHeader(constchar*s,intX,intY,intW,intH){
fl_push_clip(X,Y,W,H)
fl_draw_box(FL_THIN_UP_BOX,X,Y,W,H,row_header_color())
fl_color(FL_BLACK)
fl_draw(s,X,Y,W,H,FL_ALIGN_CENTER)
fl_pop_clip()
}
//Handledrawingtable'scells
//Fl_Tablecallsthisfunctiontodraweachvisiblecellinthetable.
//It'suptoustouseFLTK'sdrawingfunctionstodrawthecellsthewaywewant.
//
voiddraw_cell(TableContextcontext,intROW=0,intCOL=0,intX=0,intY=0,intW=0,intH=0){
staticchars[40]
switch(context){
caseCONTEXT_STARTPAGE://beforepageisdrawn..
fl_font(FL_HELVETICA,16)//setthefontforourdrawingoperations

http://seriss.com/people/erco/fltk/

73/88

8/11/2015

Erco'sFLTKCheatPage
return
caseCONTEXT_COL_HEADER://Drawcolumnheaders
sprintf(s,"%c",'A'+COL)//"A","B","C",etc.
DrawHeader(s,X,Y,W,H)
return
caseCONTEXT_ROW_HEADER://Drawrowheaders
sprintf(s,"%03d:",ROW)//"001:","002:",etc
DrawHeader(s,X,Y,W,H)
return
caseCONTEXT_CELL:{//Drawdataincells
sprintf(s,"%d",ROW*MAX_COLS+COL)//whatever..
//Handlecoloringofcells
intfgcol=FL_BLACK
intbgcol=FL_WHITE
if(row_selected(ROW)){
fgcol=FL_WHITE
bgcol=0xaa4444//ltblue
}
////Handlesecondaryselection
if(COL>=secondary_selection[0]&&COL<=secondary_selection[1]&&
ROW>=secondary_selection[2]&&ROW<=secondary_selection[3]){
fgcol=FL_WHITE
bgcol=0x44aa44//ltgreen
}
fl_draw_box(FL_THIN_UP_BOX,X,Y,W,H,bgcol)
fl_color(fgcol)
fl_draw(s,X,Y,W,H,FL_ALIGN_CENTER)
return
}
default:
return
}
}
public:
//Constructor
//Makeourdataarray,andinitializethetableoptions.
//
MyTable(intX,intY,intW,intH,constchar*L=0):Fl_Table_Row(X,Y,W,H,L){
//Initsecondaryselectionoff
SetSecondarySelection(1,1,1,1)//disablesecondaryselection
//Rows
rows(MAX_ROWS)//howmanyrows
row_header(1)//enablerowheaders(alongleft)
row_height_all(20)//defaultheightofrows
row_resize(0)//disablerowresizing
//Cols
cols(MAX_COLS)//howmanycolumns
col_header(1)//enablecolumnheaders(alongtop)
col_width_all(80)//defaultwidthofcolumns
col_resize(1)//enablecolumnresizing
end()//endtheFl_Tablegroup
}
~MyTable(){}
//Letcallerdefineasecondaryselectionrectangle
voidSetSecondarySelection(intcol_left,intcol_right,introw_top,introw_bot){
secondary_selection[0]=col_left
secondary_selection[1]=col_right
secondary_selection[2]=row_top
secondary_selection[3]=row_bot
redraw()
}
}
voidButton_CB(Fl_Widget*w,void*data){
Fl_Check_Button*but=(Fl_Check_Button*)w
MyTable*table=(MyTable*)data
if(but>value()){
table>SetSecondarySelection(4,8,4,8)//on
}else{
table>SetSecondarySelection(1,1,1,1)//off
}
}
intmain(intargc,char**argv){
Fl_Double_Windowwin(900,400,"MultiselectTable")
//Table
MyTabletable(10,10,win.w()20,win.h()50)
//Togglebuttonfor'fixed'secondaryselection
Fl_Check_Buttonbut(10,win.h()35,220,25,"SecondarySelection")
but.callback(Button_CB,(void*)&table)
win.end()
win.resizable(table)
win.show(argc,argv)
return(Fl::run())
}

http://seriss.com/people/erco/fltk/

74/88

8/11/2015

Erco'sFLTKCheatPage

DemonstrateasimpleMultilanguageApp

DemonstratesonewaytomanangeamultilingualFLTKapplicationwhosemenubar'slanguagecanbechangedinteractively.
Demonstrateshowtoarrangeeachmenuitemsothatitcanhavemultilanguagelabelsdisplayedwhilestillbeingableto
internallyoperateonafixedlanguage.
Thegoalofthisexampleisnottodependonexternallibraries(likegettext(3)),andtoonlyshowthewidgetmechanics,nothow
tocreate'languagefiles'.
The"secret"hereistomakeasmallclass("ItemData",showningreen)thatisusedfortheuserdata()ofeachmenuitem.This
classkeepstrackofboththe'this'pointerthecallbacksneed,andan'internalmenuname'foreachitem.Thisinternal
menunameneverchanges,regardlessofwhatlanguageisselected,soitcanbeusedinternallybytheapptoe.g.checkwhich
menuitemwasselected,ortodosearcheson.(Ordinarilyonemightusethemenuitem'slabel()sforthis,butinamultilingual
app,thelabels()canhavedifferentvalues,makingthemuselessforsuchuse)
Gointothe'Language"menu,andclickoneither"English"or"French"toseetheapplicationdisplayedinthatlanguage.
Forsimplicity,thisexampleassumeonlyEnglish+French.Anactualappwouldsurelywanttouseexternaltextfiles(or
'languagefiles')todefinethedifferentmenunames,whichshouldbearelativelyeasyexercisetothereadertoaddthattothe
techniquesshownhere.Perhapsinafollowupexample,I'llshowanexampleofhowtohandlethat.

MultilanguageApplicationchangabledynamically
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Menu_Bar.H>
#include<iostream>
#include<string>
//
//Demonstratemultilanguageapplicationmenu
//Asimpleappexampledemonstratingamultilingualmenubar
//e.g.clickLanguage>Frenchtoseethemenubar'slanguagechange.erco11/27/2011
//
//Aclasswepointtheuser_dataofeachitemtowhichkeepstrackof'this'
//and'internalmenuitemnames'(whichareuniqueinternalnamesforeachitem
//thatforeignlanguagelabelscanbemappedto).Otherappdatacanbeaddedtotheclassasneeded.
//
classItemData{
std::stringmenuname//useforkeepingtrackofthe'internalmenuname'
void*data//useforkeepingtrackof'this'
public:
ItemData(constchar*menuname,void*data){
this>menuname=menuname
this>data=data
}
void*GetData()const{return(data)}
constchar*GetMenuName()const{return(menuname.c_str())}
}
//The'applicationclass'whichkeepstrackofallthewidgetsandmenus.
//TheSetLanguage()methodhandleschangingthelanguageofallwidgets.
//
classApp{
Fl_Window*win
Fl_Menu_Bar*menubar

//Changethelanguageinourcase,justthemenubar
//Changesthedisplayedlabel()s,butleavestheinternalmenunamesunchanged
//sothatthelanguagecanbeswitchedbackandforth.
//
voidSetLanguage(std::stringlang){
for(intt=0t<menubar>size()t++){
Fl_Menu_Item*item=(Fl_Menu_Item*)&(menubar>menu()[t])
if(item&&item>label()&&item>user_data()){
ItemData*id=(ItemData*)item>user_data()
//std::cout<<"SetLanguage("<<lang<<"):WORKINGON"<<id>GetMenuName()<<",label="<<item>label()<<std::endl
if(strcmp(id>GetMenuName(),"File")==0)item>label((lang=="English")?"File":"Fichier")
if(strcmp(id>GetMenuName(),"File/New")==0)item>label((lang=="English")?"New":"Nouveau")
if(strcmp(id>GetMenuName(),"File/Open")==0)item>label((lang=="English")?"Open":"Ouvrir")
if(strcmp(id>GetMenuName(),"File/Quit")==0)item>label((lang=="English")?"Quit":"Quitter")
if(strcmp(id>GetMenuName(),"Language")==0)item>label((lang=="English")?"Language":"Langue")
if(strcmp(id>GetMenuName(),"Language/English")==0)item>label((lang=="English")?"English":"Anglaise")
if(strcmp(id>GetMenuName(),"Language/French")==0)item>label((lang=="English")?"French":"Francaise")
}
}
if(lang=="English")win>label("MultilanguageTestApplication")
elsewin>label("ApplicationdeTestMultilangue")

http://seriss.com/people/erco/fltk/

75/88

8/11/2015

Erco'sFLTKCheatPage

win>redraw()
}
//Handleapickedmenuitem
//Usesinternalnames(inenglish)tokeeptrackofwhichitemwaspicked.
//
voidMenu_CB2(ItemData*id){
constchar*picked=id>GetMenuName()//getthe'fixedmenuname'forthisitem
if(strcmp(picked,"File/New")==0){std::cout<<"Newpicked"<<std::endl}
elseif(strcmp(picked,"File/Open")==0){std::cout<<"Openpicked"<<std::endl}
elseif(strcmp(picked,"File/Quit")==0){exit(0)}
elseif(strcmp(picked,"Language/English")==0){SetLanguage("English")}
elseif(strcmp(picked,"Language/French")==0){SetLanguage("French")}
}
staticvoidMenu_CB(Fl_Widget*,void*userdata){
ItemData*id=(ItemData*)userdata//resolvetheItemData()
App*app=(App*)id>GetData()//getapppointer('this')fromitemdata
app>Menu_CB2(id)//invokeclassinstance'smethod
}
voidAddItem(constchar*realname,//logicalnameforitem,eg."Operators/Add"
constchar*langname,//languagespecificname,eg."&Operateur/&Plus"
constchar*shortcut=0,//shortcutforthisitem,eg,"^N"
intflags=0){//FL_MENU_INACTIVE,0,etc..
ItemData*id=newItemData(realname,(void*)this)//createnewItemDatainstanceforeachmenuitem
menubar>add(langname,shortcut,Menu_CB,(void*)id,flags)//addtheitem
}
public:
App(){
win=newFl_Window(600,200,"MultilanguageTestApplication")
win>begin()
menubar=newFl_Menu_Bar(0,0,win>w(),25)
//INTERNALMENUNAMEDEFAULTLABELSHORTCUTMENUFLAGS
//========================================================
AddItem("File","&File",0,FL_SUBMENU)
AddItem("File/New","&File/&New","^n")
AddItem("File/Open","&File/&Open","^o")
AddItem("File/Quit","&File/&Quit","^q")
AddItem("Language","&Language",0,FL_SUBMENU)
AddItem("Language/English","&Language/&English")
AddItem("Language/French","&Language/&French")
win>end()
win>resizable(win)
win>show()
}
}
intmain(){
newApp()
return(Fl::run())
}

Howtomakeanapplicationicon
Itisactuallyuptothewindowmanagersonhowiconsaredisplayed.Assuch,it'snotreallyanFLTKissue,butmoreofa
generalGUIprogrammingissuenotspecifictoFLTK.Eachplatformisabitdifferentabouthowiconsforappsaremanaged.
InWindowstheiconislinkedintotheexecutable.
InOSXtheiconbecomespartofthe.appbundle.
InLinuxtheiconisaseparatefilethatisaddedintoadirectorywherethewindowmanagerlooksforappiconsbasedona
matchintheexecutable'sfilename.
Detailsforeachplatformonhowtomakeaniconforappsarehere:
Windows
Mac
Linux

Howtodetectdoubleclicksseparatelyfromsingleclicks
Normallyit'seasytodetectdoubleclicksjustreadthevalueofFl::event_clicks()whenyoureceiveFL_PUSH.Duringadouble
click,thiswillreturn0forthefirstclick,and1forthesecond.Soifyougeta1,adoubleclickhasoccurred.
Butwhatifyouwanttodetectadoubleclickwithoutprocessingthefirstofthetwoclicksasasingleclick?Thisiswhat
someonewantedinathreadstartedonfltk.generalonMarch72012.
It'strickytodothis:IanMacArthuraddedsomecodetomysimplecountingexamplethatdelaysdetectingsingleclickinguntil
enoughtimepassedthatforsureadoubleclickhasn'toccurred,andthiswilldetectadoubleclickwithoutinterpretingthefirst
ofthetwoclicksasasingle.
Thishasthesideeffectofcreatinga1/4seconddelayintheprocessingofsingleclickbuttonpresses,butit'sunavoidable
giventhetemporalnatureofdoubleclicking.
Ianaddedthesecaveatsregardingthistimerapproach:

http://seriss.com/people/erco/fltk/

76/88

8/11/2015

Erco'sFLTKCheatPage

OnOSXandX11Ican(fairlyreliably)getittoreportupto15clicks,ifI*reallytry*,butonWinXX(winXPspecifically,in
caseitmakesadifference)Icannevergetittoreportmorethan2,soI*assume*there'ssomethingspecificabouthow
WinXXcountsclicks
Thecodeaswrittenwouldn'tbethreadsafe,thoughthatshouldnotmattersinceallthefltkcontextoughttobeinthe
samethreadanyway.
I'vehardcodedadelaytimeof250ms,whichseemstoworkOKforme,butIhavenoideahow"portable"thatis.In
particular,iftheclickdetectiondelaybeingusedbythehostsystemissubstantiallylongerthanthat,thenthismaymean
thatthecountdoesnot"reset"properlybetweenburstsofclicking.

Howtodomutuallyexclusivechecksfordoubleandsingleclicks
//
//Example:Howtodomutuallyexclusivechecksfordoubleandsingleclicks03/07/12
//1.0GregErcolanoshowedhowtocountclicks
//2.0IanMacArthuraddedtimertouniquelyidentifydoubleclicksfromsingleclicks.
//
#include<stdio.h>
#include<stdint.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
//Timercallback:determinethenumberofclicks
staticvoidwait_click(void*v){
intptr_tcc=(intptr_t)v
intic=(int)(cc&0x0F)+1
//Ifit'sasingleclick,print1.
//Ifit'sadoubleclick,print2*without*printingthefirstclick!
printf("Numberofclicks:%d\n",ic)
}
//Setupatimertodifferentiatesingleanddoubleclicks
staticvoidtimer_extend(intcc){
if(cc)Fl::remove_timeout(wait_click)
Fl::add_timeout(0.25,wait_click,(void*)cc)
}
classMyWindow:publicFl_Window{
public:
MyWindow(intW,intH,constchar*L=0):Fl_Window(W,H,L){
}
inthandle(inte){
switch(e){
caseFL_PUSH:
//Setatimertocountclicks
timer_extend(Fl::event_clicks())
break
}
return(Fl_Window::handle(e))
}
}
intmain(){
MyWindowwin(300,200,"Identifysingleanddoubleclicks")
win.show()
returnFl::run()
}

DemonstrateFl_RGB_Imageshowinginlinedata
HowtouseFl_RGB_Imagetoshowanimagedefinedinyourcodeasastaticarray.
UsuallyonewoulduseanXPMimagetouseinlineimages,butXPMshavelimitations(suchasonly1bitalpha).With
Fl_RGB_ImageyouhaveaccesstofullRGBAimagedata.
HerewecreateasimplesmallgrayscaleusingFl_RGB_Imagetoshowitonthescreen.Weuseagrayscaletokeepthe
examplesimple,butonecouldjustaseasilyusefullRGBAdatabychangingthedepthvalueto4andsupplyingalargerdata
arrayof4bytesperpixel.

InlineGrayscaleImageusingFl_RGB_Image.
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Box.H>
#include<FL/Fl_Shared_Image.H>
#include<FL/Fl_RGB_Image.H>
//
//DemonstrateusingtheFl_RGB_ImageclasstodisplayinlineimagedatainFLTK.
//erco6/13/12
//
//Grayscaleimagedata,width=16,height=10,depth=1
unsignedchargray_data[16*10*1]={
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#1
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#2

http://seriss.com/people/erco/fltk/

77/88

8/11/2015

Erco'sFLTKCheatPage

0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#3
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#4
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#5
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#6
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#7
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#8
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#9
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,//line#10
}

intmain(){
fl_register_images()//initializeimagelibrary
Fl_Windowwin(200,200)//makeawindow
Fl_Boxbox(10,10,20020,20020)//makeaboxinsidethewindow
Fl_RGB_Imagegray(gray_data,16,10,1)//createthergbimageasagrayscale
box.image(gray)//attachimagetobox
win.show()
return(Fl::run())
}

DemonstratehowtomakeahexdumpofPNGimagedatainhex
Sometimesit'susefultogetahexdumpofaPNGimagesothatitcanbeincludedwithinaprogram,insteadofhavingtobe
loadedoffdisk.
Normallyonewouldusea.pixmap,buttheyarelimtedtoonebitalpha.PNGssupportfull8bitalpha,allowingonetomake
antialiased,smoothoverlays.
Justrunthisprogramwiththepngfilenameastheonlyargument,eg:
./png2hex/tmp/foo.png>foo.cxx

..anditwilldumpaC++styleprogramthatdeclaresanunsignedchararraywiththeentireimage'srawpixelcontentsasa'hex
dump',eg:

SamplePNGHexDumpOutput
constunsignedchara_png[]={
/*W=18H=13D=4*/
/*Y=0*/
0x3f,0x3f,0x3f,0x4b,0x3f,0x3f,0x3f,0x4b,0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,/*X=03*/
0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,/*X=47*/
0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,/*X=811*/
0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,/*X=1215*/
0x3f,0x3f,0x3f,0x29,0x3f,0x3f,0x3f,0x29,/*X=1617*/
/*Y=1*/
0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,/*X=03*/
0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,/*X=47*/
0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,/*X=811*/
0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,/*X=1215*/
0x2a,0x2a,0x2a,0xff,0x2a,0x2a,0x2a,0xff,/*X=1617*/
/*Y=2*/
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,/*X=03*/
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,/*X=47*/
[..]
0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0xff,/*X=1215*/
0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0xff,/*X=1617*/
/*Y=12*/
0x3f,0x3f,0x3f,0x0c,0x3f,0x3f,0x3f,0x0c,0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,/*X=03*/
0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,/*X=47*/
0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,/*X=811*/
0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,/*X=1215*/
0x3f,0x3f,0x3f,0x06,0x3f,0x3f,0x3f,0x06,/*X=1617*/
}

Theoutputincludesacommentshowingthewidth/height/depth,andwillincludealphachanneldata,ifanywaspresentinthe
inputimage.
Theresultingcodecaneitherbe#include'edintoanapplication,similartoa.pixmap,orcopy/pastedintoanexistingC/C++
program.

DumpaPNGfileinhex.
#include<stdio.h>
#include<string.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Shared_Image.H>
#include<FL/Fl_PNG_Image.H>
//
//DumpthepixeldataofaPNGimageinC/C++parsablehexerco1.0007/12/2012
//

http://seriss.com/people/erco/fltk/

78/88

8/11/2015

Erco'sFLTKCheatPage

intmain(intargc,char*argv[]){
if(argc<2){
printf("Usage:%sfile.png\n",argv[0])
return(1)
}
constchar*filename=argv[1]
fl_register_images()
Fl_PNG_Imageimg(filename)
//Makea'safe'filenametoshowastheCvariable
char*safe_filename=strdup(filename)
for(char*s=safe_filename*ss++)if(strchr("_.",*s))*s='_'
//PrintC/C++stylevariabledeclaration
printf("constunsignedchar%s[]={\n",safe_filename)
printf("/*W=%dH=%dD=%d*/\n",img.w(),img.h(),img.d())
constunsignedchar*p=img.array
intmod=img.d()==1?16:
img.d()==2?8:4
//Walkthescanlines
for(intY=0Y<img.h()Y++){
printf("/*Y=%d*/\n",Y)
//Walkthepixels
intX
for(X=0X<img.w()X++){
if(X%mod==0)printf("\t")
//Walkthechannels
for(intD=0D<img.d()D++){
printf("0x%02x,",*p++)
}
if((X%mod)==(mod1))printf("/*X=%d%d*/\n",X(mod1),X)
elseprintf("")
}
if((X%mod)!=(mod1))printf("/*X=%d%d*/\n",((X/mod)*mod),X)
}
printf("}\n")
return(0)
}

Amulticoloredbargraphwidget

Demonstratehowtouseinlinerepresentationsofalphachannelimagestodrawnicewidgetswithantialiasedcurvedlineswith
simpleFLTKdrawingtechniques.Inthiscase,amulticoloredbargraphwidget.
Thisshowsseveralthingsinoneexamplehowtoconstructasimpleshapeusinganimageoffixedcolorwithjustthealpha
channeltodefinetheshape(inthiscaseadisk,butitcouldbeanything).Also,howtomakea'modernlookingwidget'using
simpleimagemanipulationtechniquestogetantialiased'seethrough'edges.Andfinally,howtomakeamultiplebargraph
widgetwithoverlappingbars.
Ourgoalistodrawabargraphthatcanhavemultipleoverlappingbars,similartoaCPUusagebarthatshowsseparate'user'
and'system'cpuuseinthesamebargraph,butusingroundended'bars'insteadofflatrectangles.Thisisdonebytakingjust
thealphachannelofacircleordisk(savedfromapaintprogram,e.g.Gimp),encodingthedataasinlinecode.

Multicoloredbargraphwidgetexample
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Box.H>
#include<FL/Fl_Shared_Image.H>
#include<FL/Fl_RGB_Image.H>
#include<FL/fl_draw.H>
#include<vector>
//DEMONSTRATEHOWTOMAKEAMULTICOLORBARGRAPH
//v1.002/27/13erco@seriss.com

http://seriss.com/people/erco/fltk/

79/88

8/11/2015

Erco'sFLTKCheatPage
//
//COMPILE:fltkconfiguseimagescompilemulticolorbargraph.cxx
//
//CLASSFORAMULTICOLOREDBARGRAPHWIDGET
//Example:
//_______________________________
//(______________)_____)__)_______)
//||||
//Bar#0||Trough
//Bar#1|
//Bar#2
//
classMulticolorBarGraph:publicFl_Box{
//APRIVATECLASSTOHANDLEDRAWINGAPROGRESSMETER
classProgressBarDraw{
std::vector<uchar*>bufs//imagedatabuffer
std::vector<Fl_RGB_Image*>disks//preallocatedcoloreddisks
std::vector<Fl_Color>colors//differentcolors
//RETURNTHEFl_RGB_ImageFORCOLOR'c'
//ReturnsNULLifnotfound.
//
Fl_RGB_Image*FindImage(Fl_Colorc){
for(intt=0t<colors.size()t++)
if(colors[t]==c)
returndisks[t]
return(0)
}
public:
ProgressBarDraw(){}
~ProgressBarDraw(){Clear()}
//Clearallbufferedbars
voidClear(){
intt
for(t=0t<disks.size()t++)deletedisks[t]
for(t=0t<bufs.size()t++)free((void*)bufs[t])
bufs.clear()
disks.clear()
colors.clear()
}
//ADDANEWCOLOR
//Eachcolorbarhastobepreallocated.
//Returntheallocatedimageforthiscolor.
//
Fl_RGB_Image*AddColorBar(Fl_Colorc){
//
//Thealphachannelfora10x10pixeldiskshape.Thiswaywecan
//filltheentire10x10squareofRGBvalueswiththecolorvalue,
//andthealphachannelhandlesdefiningthediskwithanicefalloff
//attheedgesforantialiasing.Weusethisasthe'brush'for
//drawingtheantialiasedbarsinthegraph.Thiswassavedfrom
//gimpstartedwithanemptyalphaimage,plottedasingledot
//usinggimp'santialiased10pixeldiskbrush,thenisolatedjust
//thealphachannelinhex.(Ifyousquintyoureyesatthehex
//below,youcanseethe'disk'inthe0xff's)
//
staticunsignedchardisk[10*10]={
0x00,0x13,0x5f,0xcc,0xff,0xff,0xcc,0x5f,0x13,0x00,
0x0c,0x72,0xe5,0xff,0xff,0xff,0xff,0xe5,0x72,0x0c,
0x4c,0xcc,0xff,0xff,0xff,0xff,0xff,0xff,0xcc,0x4c,
0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x73,0xf3,0xff,0xff,0xff,0xff,0xff,0xff,0xf3,0x73,
0x4c,0xcc,0xff,0xff,0xff,0xff,0xff,0xff,0xcc,0x4c,
0x0c,0x72,0xe5,0xff,0xff,0xff,0xff,0xe5,0x72,0x0c,
0x00,0x13,0x5f,0xcc,0xff,0xff,0xcc,0x5f,0x13,0x00,
}
//IsolatetheRGBvalues
ucharr=(c>>24)&0xff
ucharg=(c>>16)&0xff
ucharb=(c>>8)&0xff
//FilltheRGBvaluesofcolorintothediskimage.
//Leavetheopacitiesalone,asthesedefinethedisk.
//
uchar*buf=(uchar*)malloc(10*10*4)//makenewRGBAimagebuffer
uchar*out=buf
//Fillthebuffer:
//Insertthergbvalues,andcopyjustthealphafrmothedisk[]buffer.
//
for(intt=0t<10*10t++)
{*out++=r*out++=g*out++=b*out++=disk[t]}
//Makeaninstanceofnewcoloreddisk
Fl_RGB_Image*img=newFl_RGB_Image(buf,10,10,4)
bufs.push_back(buf)
disks.push_back(img)//addmodifiedimagetodisks[]
colors.push_back(c)//addcolortocolors[]
return(img)
}
//DRAWPROGRESSBARINCOLOR'c'ATPOSITIONX,YOFWIDTHW
voidDrawBar(Fl_Colorc,intX,intY,intW){
Fl_RGB_Image*img=FindImage(c)
if(!img)img=AddColorBar(c)//defineanimageforthisbar'scolor
if((W2)>0)fl_rectf(X+6,Y,W2,10,c)//drawcenterpartofbar
//Drawbar'sendcaps
img>draw(X,Y)
img>draw(X+W,Y)
}
}
ProgressBarDrawmdraw//instanceofprivateclasstohandledrawingbar(s)
std::vector<float>barvalues//sizeofeachbar(0.0~1.0)
std::vector<Fl_Color>barcolors//arrayofcolorsforeachbar
public:
//CTOR
MulticolorBarGraph(intX,intY,intW,intH,constchar*L=0):Fl_Box(X,Y,W,H,L){
}
//Addanewbarofvalue'val',color'col',returnbarcount.

http://seriss.com/people/erco/fltk/

80/88

8/11/2015

Erco'sFLTKCheatPage

intAddBar(floatval,Fl_Colorcol){
val=(val<0.0)?0.0:(val>1.0)?1.0:val
barvalues.push_back(val)
barcolors.push_back(col)
return(int(barvalues.size()))
}
//Returnthenumberofbarsdefined
intGetTotalBars()const{
returnint(barvalues.size())
}
//Clearallbars
//Deallocatesmemorythatmanagesbarcolors,valuesandicons.
//UseAddBar()tocreatenewones.
//
voidClear(){
barvalues.clear()
barcolors.clear()
mdraw.Clear()
}
//Setthevalueofabarat'index'to'val'
voidSetBarValue(intindex,floatval){
val=(val<0.0)?0.0:(val>1.0)?1.0:val
barvalues[index]=val
}
//Returnthevalueofbarat'index'
floatGetBarValue(intindex)const{
return(barvalues[index])
}
//Setthecolorofabarat'index'tocolor'col'
voidSetBarColor(intindex,Fl_Colorcol){
barcolors[index]=col
}
//Returnthecolorofbarat'index'
Fl_ColorGetBarColor(intindex)const{
return(barcolors[index])
}
//Drawthewidget
//Lettheboxdrawitself,thendrawallthebarsinthegraph
voiddraw(){
Fl_Box::draw()
intbary=y()+(h()/2)5//centerthebarvertically
mdraw.DrawBar(color(),x(),bary,w()10)//drawbar"trough"
//Drawleftjustifiedbars
//Tooverlapproperly,drawthemrighttoleft
//
intt
for(t=barvalues.size()1t>=0t){
intwidth=int(barvalues[t]*w()+.5)10
if(width<0)width=0
mdraw.DrawBar(barcolors[t],x(),bary,width)
}
}
}
///////////////////////////////////////////////////////////////////
//TESTTHEMULTICOLORBARGRAPHWIDGET
//Thefollowingcodeisusedjusttoverifythewidgetworks,
//andshowshowtouseit.
///////////////////////////////////////////////////////////////////
std::vector<MulticolorBarGraph*>G_mbgs
//TIMERCALLBACKTOHANDLECHANGINGTHEBARSIZES
//Werandomlychangethebar'ssizessotheybouncearound..
//
staticvoidUpdateBars(void*){
for(intt=0t<G_mbgs.size()t++){
//Randomizethepositionsofthebars.
//Sizesmustbesetinascendingorder.
//
floatrval=((float)rand()/RAND_MAX)*.80
floatgval=((float)rand()/RAND_MAX)*(1.0rval)+rval
floatbval=((float)rand()/RAND_MAX)*(1.0gval)+gval
if(gval>1.0)gval=1.0
if(bval>1.0)bval=1.0
G_mbgs[t]>SetBarValue(0,rval)
G_mbgs[t]>SetBarValue(1,gval)
G_mbgs[t]>SetBarValue(2,bval)
G_mbgs[t]>redraw()
}
Fl::repeat_timeout(1.0,UpdateBars)
}
#defineWIDTH250
#defineHEIGHT210
intmain(){
fl_register_images()
Fl_Double_Windowwin(WIDTH,HEIGHT,"testMulticolorBarGraph")
win.color(0x3d3e4200)//darkgray
//Makeseveralinstancesofthebargraphwidgetverticallyinwindow.
//Eachinstancewillhavethreebarsred,grnandblu.
//Eachbar's'value'isintherange0.0~1.0.
//Sizesofeachbarmustbeinascendingorder,
//asthebarsaredrawnrighttolefttooverlapproperly.
//
charname[10]
for(intY=10Y<(HEIGHT20)Y+=20){
//CREATEINSTANCEOFMULTICOLORBARGRAPHWIDGET
MulticolorBarGraph*mbg=newMulticolorBarGraph(30,Y,WIDTH40,20)
mbg>color(0x28282800)//troughcolor(verydarkgray)
//Createther/g/bbarswithinbargraph
mbg>AddBar(0.0,0xf0595900)//red
mbg>AddBar(0.0,0x72cc6b00)//grn
mbg>AddBar(0.0,0x10579300)//blu
//Labeleachbar..
sprintf(name,"%d:",int(G_mbgs.size()+1))
mbg>copy_label(name)
mbg>labelcolor(0x79797900)
mbg>align(FL_ALIGN_LEFT)

http://seriss.com/people/erco/fltk/

81/88

8/11/2015

Erco'sFLTKCheatPage

//AddtoglobalarrayforUpdateBars()tomanipulateonatimer
G_mbgs.push_back(mbg)
}
//SETUPATIMERTO"BOUNCE"THEBARSAROUND
Fl::add_timeout(1.0,UpdateBars)
win.resizable(win)
win.show()
return(Fl::run())
}

Showhowtosynchronizetwo(ormore)volumeknobs

Demonstratehowtoderiveaclassthatletsonesynchronizeknobsofthesamename,evenifindifferentwindows.(Likean
audiomixingconsole).
Ourgoalistomakeawidgetthatcanbeinstancedallovertheplace,andanywidgetsnamedthesamearelockedtogether
changingonechangestheothersiftheyhavethesamename.
Thewidgetkeepsaninternalstaticarrayofinstancesofitselfsothatwhenoneischanged,itchangesalltheotherinstances
thathavethesamelabel()name.

Showhowtosynchronizetwo(ormore)volumeknobs
#include<string.h>
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Slider.H>
#include<vector>
//Demonstratehowtoconnectvolumeknobstoeachotherbynameerco1.003/06/13
//CLASSTOHANDLECONNECTINGVOLUMEKNOBS
classVolumeKnob:publicFl_Slider{
staticvoidAdjust_CB(Fl_Widget*w,void*data)
public:
VolumeKnob(intX,intY,intW,intH,constchar*L=0)
~VolumeKnob()
}
staticstd::vector<VolumeKnob*>G_knobs//globalarrayofallvolknobinstances
//HANDLEVOLUMEADJUSTMENT
voidVolumeKnob::Adjust_CB(Fl_Widget*w,void*data){
VolumeKnob*knob=(VolumeKnob*)data
printf("KNOB'%s'CHANGED:%.2f\n",knob>label(),knob>value())
//Realworkhere:causecurrentknob'svaluetoaffectothers
for(unsignedt=0t<G_knobs.size()t++){//walkthruallknobscreatedsofar
if(knob==G_knobs[t])continue//skipourself
if(strcmp(G_knobs[t]>label(),knob>label())!=0)continue//skipknobsofdifferentname
G_knobs[t]>value(knob>value())//adjustotherknobofsamename
}
}
//CTOR
VolumeKnob::VolumeKnob(intX,intY,intW,intH,constchar*L):Fl_Slider(X,Y,W,H,L){
type(FL_VERT_NICE_SLIDER)//typeofslider
align(FL_ALIGN_BOTTOM)//(labelsonbottom)
selection_color(FL_RED)//nicerlookingknob
callback(Adjust_CB,(void*)this)//setupcallback
G_knobs.push_back(this)//savepointertoself
}
//DTOR
VolumeKnob::~VolumeKnob(){
//Removefromourglobalarray
for(unsignedt=0t<G_knobs.size()t++){
if(G_knobs[t]==this){
G_knobs.erase(G_knobs.begin()+t)//stl,whyusofugly
break
}
}
}
intmain(intargc,char*argv[]){
Fl::scheme("gtk+")
Fl_Window*w1=newFl_Window(0,0,100,120,"Win#1")
w1>begin()
newVolumeKnob(10+0,10,20,80,"T1")
newVolumeKnob(10+30,10,20,80,"T2")
newVolumeKnob(10+60,10,20,80,"T3")

http://seriss.com/people/erco/fltk/

82/88

8/11/2015

Erco'sFLTKCheatPage

w1>end()
w1>show()

Fl_Window*w2=newFl_Window(200,0,100,120,"Win#2")
w2>begin()
newVolumeKnob(10+0,10,20,80,"T1")
newVolumeKnob(10+30,10,20,80,"T2")
newVolumeKnob(10+60,10,20,80,"T3")
w2>end()
w2>show()
returnFl::run()
}

Demonstratehowtomakearesizerbarthatcanbedraggedtoresizewidgets
DemonstratehowtomakeahorizontalbarwidgetthatcanbeattachedbelowwidgetsinanFl_Scrollsothattheycanbe
resized,causingotherwidgetsbelowtomovearoundtoaccommodatetheresizedwidget.
TheResizerBarclassiswhatyouwoulduseinyourapp.Themain()belowitshowshowtouseit.
Theexamplemain()creates10Fl_Multiline_Outputwidgetswitharesizerbeloweach.Youcandragtheresizersaroundto
changethesizeofthe'output'widgetabovetheotherwidgetsbelowwillbemovedaroundinsidethescrollertoaccommodate.
Scrollbarswillappearforwidgetsthatareoffscreen.
Here'stheexamplecode.

DemonstratehowtouseFLTKtimers
DemonstratehowtouseFLTKtimercallbacks.
FLTKtimersareusefultohaveeventshappenatcertaintimes,suchasadvancingthesecondhandonaclock,ortoblink
colors,orpollstateofhardwareatvariousintervals,advancethroughanimation,etc.
Thisexampleshowshowtoprint10messagestostdoutat1/2secondintervals,thenturnsthetimeroff.(Underwindows,
compilethisexampleasa/subsystem:consoleapplication,oryouwon'tseeanyoutput)

DemonstrateFLTKtimers
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
//
//DemonstrateFLTKtimerserco10/12/13
//
staticvoidTimer_CB(void*data){//timercallback
staticintcount=0//keepcountoftimerticks
printf("Timer!#%d\n",++count)//printamessageeachtimertick
if(count>=10){
//After10timerticks,turntimeroff
Fl::remove_timeout(Timer_CB,data)
printf("Timerturnedoff.\n")
}else{
//lessthan10timerticks?Keeprunning
Fl::repeat_timeout(.50,Timer_CB,data)
}
}
intmain(){
Fl_Windowwin(200,200,"TimerExample")
win.show()
Fl::add_timeout(.5,Timer_CB)//setupatimer
returnFl::run()
}

Demonstrateaninputwidgetthatsupportsvariousjustifications

http://seriss.com/people/erco/fltk/

83/88

8/11/2015

Erco'sFLTKCheatPage

Demonstratesaninputwidgetthatcansupportvariousjustifications.

DemonstrateanFl_Inputwidgetwithvariousjustifications
#include<FL/Fl.H>
#include<FL/Fl_Window.H>
#include<FL/Fl_Box.H>
#include<FL/Fl_Input.H>
#include<FL/Fl_Button.H>
//
//Demonstrateaninputwidgetthatcansupportvariousjustificationserco12/16/13
//
classFl_Justify_Input:publicFl_Group{
Fl_Input*inp
Fl_Box*box
public:
//Ctor
Fl_Justify_Input(intX,intY,intW,intH,constchar*L=0):Fl_Group(X,Y,W,H,L){
Fl_Group::box(FL_NO_BOX)
box=newFl_Box(X,Y,W,H)
box>color(FL_WHITE)
box>box(FL_DOWN_BOX)
inp=newFl_Input(X,Y,W,H)
inp>hide()
inp>color(FL_WHITE)
end()
}
//Settextjustification.Expectsoneof:
//FL_ALIGN_LEFT,FL_ALIGN_CENTER,FL_ALIGN_RIGHT.
//
voidjustify(Fl_Alignval){
box>align(val|FL_ALIGN_INSIDE)
}
//Returnstextjustification
Fl_Alignjustify()const{
returnbox>align()
}
//Setsthetextvalue
voidvalue(constchar*val){
box>copy_label(val)
inp>value(val)
}
//Getsthetextvalue
constchar*value()const{
returninp>value()
}
inthandle(inte){
switch(e){
caseFL_PUSH:
caseFL_FOCUS:
if(!inp>visible()){
//Makeinputwidget'appear'inplaceofthebox
box>hide()
inp>show()
inp>value(box>label())
redraw()
}
break
caseFL_UNFOCUS:
if(inp>visible()){
//Replaceinputwidgetwithjustifiedbox
box>show()
inp>hide()
box>label(inp>value())
redraw()
}
break
default:
break
}
return(Fl_Group::handle(e))
}
}
//TesttheaboveFl_Justify_Inputwidget
intmain(intargc,char**argv){
Fl::scheme("gtk+")
Fl_Window*win=newFl_Window(220,200,"Fl_Justify_InputWidget")
win>begin()
Fl_Justify_Input*fji
fji=newFl_Justify_Input(10,30,200,25,"Left")
fji>justify(FL_ALIGN_LEFT)
fji>value("123")
fji=newFl_Justify_Input(10,90,200,25,"Center")
fji>justify(FL_ALIGN_CENTER)
fji>value("456")
fji=newFl_Justify_Input(10,150,200,25,"Right")

http://seriss.com/people/erco/fltk/

84/88

8/11/2015

fji>justify(FL_ALIGN_RIGHT)
fji>value("789")
win>end()
win>show()
return(Fl::run())
}

Erco'sFLTKCheatPage

Spreadsheeteditordemoincludeseditingrow/colheaders
Demonstratesasimplespreadsheeteditorthatincludeseditingrow/colheadersaswellastablecells.
Sometrickeryisneededtoeditthecellsintherowandcolumnheaders,becausebydefaultFl_Table(1.3.2andolder,anyway)
parentschildrentoaninternalFl_Scrollthatwillclipwidgetsoutsidethecellarea(e.g.theheaders),sowehavetoreparent
theFl_Inputwidgettotheparentwindowwheneditingtherow/colheaders.
Thisisamodifiedversionofexamples/tablespreadsheet.cxxthatexample'ssumminglogicwasrippedout(tosimplify),and
replacedFl_Int_InputwitharegularFl_Input,andaddedsometextarraystomanagethecellcontent.Madenecessary
changestokeeptrackofthetablecontextforeditingpurposes,sothatonecaneditboththecellsandheaders.
The'XXX'commentmarkersindicatewherethereparentingtrickisused.

Fl_Tablespreadsheetwitheditablerow/colheaders
#include<stdio.h>
#include<stdlib.h>
#include<FL/Fl.H>
#include<FL/Fl_Double_Window.H>
#include<FL/Fl_Table.H>
#include<FL/Fl_Input.H>
#include<FL/fl_draw.H>
//Demonstratesimplespreadsheeteditorthatincludeseditingrow/colheadersaswellastablecells
//erco5/23/14
constintMAX_COLS=10
constintMAX_ROWS=10
classSpreadsheet:publicFl_Table{
Fl_Input*input//singleinstanceofFl_Int_Inputwidget
introw_edit,col_edit//row/colbeingmodified
TableContextcontext_edit//contextbeingedited(rowhead/colhead/cell)
//Bufferforspreadsheetcontent
charrow_values[MAX_ROWS+1][20]//onedimensionalarrayofstrings
charcol_values[MAX_COLS+1][20]//onedimensionalarrayofstrings
charcell_values[MAX_ROWS+1][MAX_COLS+1][20]//twodimensionalarrayofstrings
protected:
voiddraw_cell(TableContextcontext,int=0,int=0,int=0,int=0,int=0,int=0)
voidevent_callback2()//table'seventcallback(instance)
staticvoidevent_callback(Fl_Widget*,void*v){//table'seventcallback(static)
((Spreadsheet*)v)>event_callback2()
}
staticvoidinput_cb(Fl_Widget*,void*v){//inputwidget'scallback
((Spreadsheet*)v)>set_value_hide()
}
public:
Spreadsheet(intX,intY,intW,intH,constchar*L=0):Fl_Table(X,Y,W,H,L){
callback(&event_callback,(void*)this)
when(FL_WHEN_NOT_CHANGED|when())
//Createinputwidgetthatwe'llusewheneveruserclicksonacell
input=newFl_Input(W/2,H/2,0,0)
input>hide()
input>callback(input_cb,(void*)this)
input>when(FL_WHEN_ENTER_KEY_ALWAYS)//callbacktriggeredwhenuserhitsEnter
input>maximum_size(5)
input>color(FL_YELLOW)
end()
context_edit=CONTEXT_NONE
row_edit=col_edit=0
set_selection(0,0,0,0)
intr,c
for(r=0r<=MAX_ROWSr++)
for(c=0c<=MAX_COLSc++)
sprintf(cell_values[r][c],"%d/%d",r,c)
for(r=0r<=MAX_ROWSr++)
sprintf(row_values[r],"%03d",r)
for(c=0c<=MAX_COLSc++)
sprintf(col_values[c],"%c",'A'+c)
}
~Spreadsheet(){}
//Applyvaluefrominputwidgettovalues[row][col]arrayandhide(doneediting)
voidset_value_hide(){
switch(context_edit){
caseCONTEXT_ROW_HEADER:sprintf(row_values[row_edit],"%.19s",input>value())break
caseCONTEXT_COL_HEADER:sprintf(col_values[col_edit],"%.19s",input>value())break
caseCONTEXT_CELL:sprintf(cell_values[row_edit][col_edit],"%.19s",input>value())break
default:break
}
input>hide()
window()>cursor(FL_CURSOR_DEFAULT)//ifwedon'tdothis,cursorcandisappear!
}

http://seriss.com/people/erco/fltk/

85/88

8/11/2015

Erco'sFLTKCheatPage

//Starteditinganewcell:movetheFl_Int_Inputwidgettospecifiedrow/column
//Preloadthewidgetwiththecell'scurrentvalue,
//andmakethewidget'appear'atthecell'slocation.
//IfR==1,indicatescolumnCisbeingedited
//IfC==1,indicatesrowRisbeingedited
//
voidstart_editing(TableContextcontext,intR,intC){
//Keeptrackofcellbeingedited
context_edit=context
row_edit=R
col_edit=C
//Clearanypreviousmulticellselection
if(R<0||C<0)set_selection(0,0,0,0)
elseset_selection(R,C,R,C)
//FindX/Y/W/Hofcell
intX,Y,W,H
find_cell(context,R,C,X,Y,W,H)
input>resize(X,Y,W,H)//MoveFl_Inputwidgetthere
switch(context){
caseCONTEXT_ROW_HEADER:
Fl_Group::add(*input)//XXXparenttononscrollablegroup
input>value(row_values[R])
break
caseCONTEXT_COL_HEADER:
Fl_Group::add(*input)//XXXparenttononscrollablegroup
input>value(col_values[C])
break
caseCONTEXT_CELL:
table>add(*input)//XXXparenttoscrollabletable
input>value(cell_values[R][C])break
default://shouldn'thappen
input>value("?")
break
}
input>position(0,strlen(input>value()))//Selectentireinputfield
input>show()//Showtheinputwidget,nowthatwe'vepositionedit
input>take_focus()
}
//Telltheinputwidgetit'sdoneediting,andto'hide'
voiddone_editing(){
if(input>visible()){//inputwidgetvisible,ie.editinprogress?
set_value_hide()//Transferitscurrentcontentstocellandhide
}
}
}
//Handledrawingallcellsintable
voidSpreadsheet::draw_cell(TableContextcontext,intR,intC,intX,intY,intW,intH){
switch(context){
caseCONTEXT_STARTPAGE://tableabouttoredraw
break
caseCONTEXT_COL_HEADER://tablewantsustodrawacolumnheading(Ciscolumn)
//don'tdrawthiscellifit'sbeingedited
if(context_edit==context&&C==col_edit&&input>visible()){
return
}
fl_font(FL_HELVETICA|FL_BOLD,14)//setfontforheadingtobold
fl_push_clip(X,Y,W,H)//clipregionfortext
{
fl_draw_box(FL_THIN_UP_BOX,X,Y,W,H,col_header_color())
fl_color(FL_BLACK)
fl_draw(col_values[C],X,Y,W,H,FL_ALIGN_CENTER)
}
fl_pop_clip()
return
caseCONTEXT_ROW_HEADER://tablewantsustodrawarowheading(Risrow)
//don'tdrawthiscellifit'sbeingedited
if(context_edit==context&&R==row_edit&&input>visible()){
return
}
fl_font(FL_HELVETICA|FL_BOLD,14)//setfontforrowheadingtobold
fl_push_clip(X,Y,W,H)
{
fl_draw_box(FL_THIN_UP_BOX,X,Y,W,H,row_header_color())
fl_color(FL_BLACK)
fl_draw(row_values[R],X,Y,W,H,FL_ALIGN_CENTER)
}
fl_pop_clip()
return
caseCONTEXT_CELL:{//tablewantsustodrawacell
//don'tdrawthiscellifit'sbeingedited
if(context_edit==context&&R==row_edit&&C==col_edit&&input>visible())
return
//Background
inthighlight=is_selected(R,C)&&context==context_edit
fl_draw_box(FL_THIN_UP_BOX,X,Y,W,H,highlight?FL_YELLOW:FL_WHITE)
//Text
fl_push_clip(X+3,Y+3,W6,H6)
{
fl_color(FL_BLACK)
fl_font(FL_HELVETICA,14)//..inregularfont
fl_draw(cell_values[R][C],X+3,Y+3,W6,H6,FL_ALIGN_RIGHT)
}
fl_pop_clip()
return
}
caseCONTEXT_RC_RESIZE://tableresizingrowsorcolumns
if(input>visible()){
find_cell(context_edit,row_edit,col_edit,X,Y,W,H)
input>resize(X,Y,W,H)
init_sizes()
}
return
default:
return

http://seriss.com/people/erco/fltk/

86/88

8/11/2015

}
}

Erco'sFLTKCheatPage

//Callbackwheneversomeoneclicksondifferentpartsofthetable
voidSpreadsheet::event_callback2(){
intR=callback_row()
intC=callback_col()
TableContextcontext=callback_context()
switch(context){
caseCONTEXT_ROW_HEADER:
caseCONTEXT_COL_HEADER:
caseCONTEXT_CELL:{//Atableeventoccurredonacell
switch(Fl::event()){//seewhatFLTKeventcausedit
caseFL_PUSH://mouseclick?
done_editing()//finisheditingprevious
start_editing(context,R,C)
return
caseFL_KEYBOARD://keypressintable?
if(Fl::event_key()==FL_Escape)exit(0)//ESCclosesapp
done_editing()//finishanypreviousediting
if(C==cols()1||R==rows()1)return//noeditingoftotalscolumn
switch(Fl::e_text[0]){
case'0':case'1':case'2':case'3'://anyoftheseshouldstarteditingnewcell
case'4':case'5':case'6':case'7':
case'8':case'9':case'+':case'':
start_editing(context,R,C)
input>handle(Fl::event())//passtypedchartoinput
break
case'\r':case'\n'://letenterkeyeditthecell
start_editing(context,R,C)
break
}
return
}
return
}
caseCONTEXT_TABLE://Atableeventoccurredondeadzoneintable
done_editing()//doneediting,hide
return

default:
return
}
}
intmain(){
Fl_Double_Window*win=newFl_Double_Window(862,322,"Fl_TableSpreadsheet")
Spreadsheet*table=newSpreadsheet(10,10,win>w()20,win>h()20)
#ifFLTK_ABI_VERSION>=10303
table>tab_cell_nav(1)//enabletabnavigationoftablecells(insteadoffltkwidgets)
#endif
table>tooltip("Usekeyboardtonavigatecells:\n"
"ArrowkeysorTab/ShiftTab")
//Tablerows
table>row_header(1)
table>row_header_width(70)
table>row_resize(1)
table>rows(MAX_ROWS+1)//+1:leavesroomfor'totalrow'
table>row_height_all(25)
//Tablecols
table>col_header(1)
table>col_header_height(25)
table>col_resize(1)
table>cols(MAX_COLS+1)//+1:leavesroomfor'totalcolumn'
table>col_width_all(70)
table>box(FL_THIN_UP_FRAME)
//Showwindow
win>end()
win>resizable(table)
win>show()
returnFl::run()
}

End

http://seriss.com/people/erco/fltk/

87/88

8/11/2015

http://seriss.com/people/erco/fltk/

Erco'sFLTKCheatPage

88/88

Potrebbero piacerti anche