Go home
Go back to other tutorials

Harbour How To - Tutorial


Giovanni Di Maria - calimero22@yahoo.it
since: Apr 06, 2011



Tutorial

Harbour 3.2
This Tutorial:
Rev. [1] - April 06, 2011
Rev. [287] - Feb 8, 2013






Index




Introduction
This tutorial is a brief, continuously updated, of the use of the Harbour language. It is specifically written for beginners that initially encountered some difficulties in using Harbour language, extremely powerful and efficient. The approach of the tutorial is different from other guides that are online. It simply focuses a single problem, so you do not get lost in the maze of the vast files of examples provided with the product. This will easily learn to manage an individual idea, as needed, and, finally, to put "together" the whole.
Giovanni Di Maria




Notes for developers




Compiling in Windows
In order to compile correctly your sources, you must follow this procedure:

  1. Create the file named sample.hbp (or other name) as follow:
  2. Create your source program, named sample.prg (or other name).
  3. Set your path to harbour/bin directory and mingw/bin directory.
  4. Compile with hbmk2 sample.hbp.
  5. The procedure will create the file sample.exe.




Legal Notices
This tutorial is a free document and will remain free. You can view, use, print and redistribute it and/or modify it, without any limitations.




Array - Associative Array
The following example shows how to create an associative array. The index of array is a string and not a number. (by Giovanni Di Maria)



PROCEDURE Main() LOCAL aArray LOCAL k CLEAR SCREEN aArray := { => } aArray["dog"] := "fuffy" aArray["cat"] := 1975 aArray["pig"] := "Giovanni Di Maria" aArray["frog"] := 1234567890 ? aArray["dog"] // -> fuffy ? aArray["cat"] // -> 1975 ? "--------------" FOR EACH k IN aArray ? k NEXT k RETURN




Array - Hash
The following example shows how to create an hash table. (by Giovanni Di Maria)



PROCEDURE Main() LOCAL hVar := { 1 => .T. , "casa" => .F. , 5 => "hola" } LOCAL x CLEAR SCREEN FOR EACH x IN hVar ? x NEXT ? "--------------------" ? hVar[1] ? hVar["casa"] ? hVar[5] RETURN




C Language - C function without parameters
The following example shows how to create a language C function. You can use it in your .PRG sources. You have to create two files: the .PRG file, containing the Harbour program and the .C file, containing the function, in C language. Give the sources different names, otherwise their obj files will collide. In this example, you have test.prg and func.c files. You can compile with:
hbmk2 test.prg func.c. (by Giovanni Di Maria)



// test.prg PROCEDURE Main() CLEAR SCREEN ? "Result=", udf() RETURN
/* func.c */ #include "hbapi.h" HB_FUNC(UDF) { unsigned int a,b,c; a=16; b=5; c=a+b; hb_retni(c); }




C Language - C function with parameters
The following example shows how to create a language C function. You can use it in your .PRG sources. You have to create two files: the .PRG file, containing the Harbour program and the .C file, containing the function, in C language. Give the sources different names, otherwise their obj files will collide. In this example, you have test.prg and func.c files. You can compile with:
hbmk2 test.prg func.c. (by Giovanni Di Maria)



// test.prg PROCEDURE Main() CLEAR SCREEN ? "The result is: ", multiply( 58, 37 ) RETURN
/* func.c */ #include "hbapi.h" HB_FUNC(MULTIPLY) { unsigned int a,b,c; a=hb_parni(1); b=hb_parni(2); c=a*b; hb_retni(c); }




C Language - C function that returns a random number
The following example shows how to create a language C function, returning a random number. You can use it in your .PRG sources. You have to create two files: the .PRG file, containing the Harbour program and the .C file, containing the function, in C language. Give the sources different names, otherwise their obj files will collide. In this example, you have test.prg and func.c files. You can compile with:
hbmk2 test.prg func.c. (by Giovanni Di Maria)



// test.prg PROCEDURE Main() LOCAL k CLEAR SCREEN FOR k = 1 TO 10 ? "A random number between 1 and 6 is: ", rnd( 6 ) NEXT k RETURN
/* func.c */ #include "hbapi.h" HB_FUNC(RND) { hb_retni(rand()%hb_parni(1)+1); }




C Language - C function that returns the sum of a range od numbers
The following example shows how to create a language C function, returning the sum of numbers, from n1 to n2. The function is very fast and uses long long variables. You can use it in your .PRG sources. You have to create two files: the .PRG file, containing the Harbour program and the .C file, containing the function, in C language. Give the sources different names, otherwise their obj files will collide. In this example, you have test.prg and func.c files. You can compile with:
hbmk2 test.prg func.c. (by Giovanni Di Maria)



// test.prg PROCEDURE Main() LOCAL n1, n2 n1 = 1 n2 = 896885789 ? "The Sum from", n1, "to", n2, "is", somma( n1, n2 ) RETURN
/* func.c */ #include "hbapi.h" HB_FUNC(SOMMA) { long long a,b,t,k; a=hb_parnint(1); b=hb_parnint(2); t=0; for(k=a;k<=b;k++) t+=k; hb_retnint(t); }




Mouse - Mouse on Get fields
The following example shows how to enable the mouse over the input fields. You can click on the fields, instead to press Tab key, to navigate through the fields. (by Giovanni Di Maria)



#include "inkey.ch" PROCEDURE MAIN LOCAL GetList := {} LOCAL cVar1, cVar2, cVar3 CLEAR SCREEN cVar1 = Space( 10 ) cVar2 = Space( 10 ) cVar3 = Space( 10 ) SET( _SET_EVENTMASK, INKEY_ALL ) MSetCursor( .T. ) @ 10, 20 SAY "Var 1:" GET cVar1 @ 11, 20 SAY "Var 2:" GET cVar2 @ 12, 20 SAY "Var 3:" GET cVar3 READ RETURN




MDB Database - Reading a table in MDB database
The following example shows how to read data from a MDB database. The name of database is test.mdb. The database has a table, called tab_people. This table has the following fields: first, last, age, mydate. Compile the program with:
hbmk2 test.prg hbwin.hbc -w3. (by Giovanni Di Maria)



#define adOpenForwardOnly 0 #define adOpenKeyset 1 #define adOpenDynamic 2 #define adOpenStatic 3 #define adLockReadOnly 1 #define adLockPessimistic 2 #define adLockOptimistic 3 #define adLockBatchOptimistic 4 #define adUseNone 1 #define adUseServer 2 #define adUseClient 3 PROCEDURE MAIN() LOCAL oRs , cSql, cDb oRs := win_oleCreateObject( "ADODB.Recordset" ) cDb := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb" cSql := "SELECT * FROM tab_people ;" oRs:Open( cSql , cDb , adOpenForwardOnly, adLockReadOnly ) WHILE !oRs:EOF ? oRs:Fields( "First" ):Value ? oRs:Fields( "Last" ):Value ? oRs:Fields( "Age" ):Value ? oRs:Fields( "MyDate" ):Value ? "------------------------------------" oRs:MoveNext() ENDDO oRs:Close() RETURN




Standard Output - Standard Output
If a program with the statement "?" is redirected to a file o printer, it does not work. The following example shows how to write values to the standard output device. In this case, the output of the program ca be redirected to a different device (with > redirector). (by Giovanni Di Maria)



PROCEDURE Main() LOCAL k FOR k = 1 TO 5 OutStd( k, hb_eol() ) NEXT k RETURN




Compiling Info - Compiling Info
The following example shows how to retrieve informations about the compilator used. (by Giovanni Di Maria)



#include "hbver.ch" PROCEDURE Main() LOCAL k ? "Harbour build date: " + hb_Version( HB_VERSION_BUILD_DATE_STR ) ? "Major version number: " , hb_Version( HB_VERSION_MAJOR ) ? "Minor version number: " , hb_Version( HB_VERSION_MINOR ) ? "Revision number: " , hb_Version( HB_VERSION_RELEASE ) ? "Build status: " , hb_Version( HB_VERSION_STATUS ) ? "-------------------------------------------------------------------" for k = 0 TO 25 ? k , hb_Version( k ) next k ? "-------------------------------------------------------------------" ? "Compiler used: " , hb_Version( HB_VERSION_COMPILER ) RETURN




ListBox - Simple ListBox
The following example shows how to create a simple listbox. (by Giovanni Di Maria)



PROCEDURE Main() LOCAL GetList := {} LOCAL cCity SetMode( 25, 80 ) CLEAR SCREEN cCity = "Milano" @ 4, 4, 12, 20 GET cCity LISTBOX { "Milano", "Genova", "Roma", "Pisa", "Torino" } READ @ 14, 10 SAY "You have selected: " + cCity RETURN




Documentation - Building the documentation of Harbour
You can produce the documentation of Harbour, in HTML format. You have to write some command in a window console. (by Massimo Belgrano)



cd \harbour\examples\hbdoc hbmk2 hbdoc.hbp cd \harbour\doc\en \harbour\examples\hbdoc\hbdoc -format=html




OOP, Object Oriented Programming - Rectangle CLASS
The following example shows how to create an object from a class. (by Giovanni Di Maria)



#include "hbclass.ch" #include "inkey.ch" // This program creates the Rectangle CLASS. // It has the following instances: // Top, Left, Bottom, Right, Border // and the following methods: // View() // MoveRight() MoveUp() MoveLeft() MoveDown() // Squeeze() Widen() Crush() Expand() //--------------------------------------------------------------------// PROCEDURE Main() LOCAL oRect := Rectangle():New() LOCAL nKey SetMode( 25, 80 ) CLEAR SCREEN oRect:Top := 5 oRect:Left := 10 oRect:Bottom := 20 oRect:Right := 70 oRect:Border := 2 DO WHILE .T. oRect:View() nKey = Inkey( 0 ) CLEAR SCREEN DO CASE CASE nKey = K_ESC CLEAR SCREEN RETURN .T. CASE nKey = K_RIGHT oRect:MoveRight() CASE nKey = K_UP oRect:MoveUp() CASE nKey = K_LEFT oRect:MoveLeft() CASE nKey = K_DOWN oRect:MoveDown() CASE nKey = K_CTRL_LEFT oRect:Squeeze() CASE nKey = K_CTRL_RIGHT oRect:Widen() CASE nKey = K_CTRL_UP oRect:Crush() CASE nKey = K_CTRL_DOWN oRect:Expand() ENDCASE ENDDO RETURN //--------------------------------------------------------------------// CLASS Rectangle DATA Top, Left, Bottom, Right, Border METHOD View() METHOD MoveRight() METHOD MoveUp() METHOD MoveLeft() METHOD MoveDown() METHOD Squeeze() METHOD Widen() METHOD Crush() METHOD Expand() ENDCLASS METHOD View() CLASS Rectangle DO CASE CASE self:Border = 1 @ self:Top, self:Left TO self:Bottom, self:Right CASE self:Border = 2 @ self:Top, self:Left TO self:Bottom, self:Right DOUBLE ENDCASE RETURN Self METHOD MoveRight() CLASS Rectangle self:Left ++ self:Right ++ self:View() RETURN Self METHOD MoveUp() CLASS Rectangle self:Top -- self:Bottom -- self:View() RETURN Self METHOD MoveLeft() CLASS Rectangle self:Left -- self:Right -- self:View() RETURN Self METHOD MoveDown() CLASS Rectangle self:Top ++ self:Bottom ++ self:View() RETURN Self METHOD Squeeze() CLASS Rectangle self:Right -- self:View() RETURN Self METHOD Widen() CLASS Rectangle self:Right ++ self:View() RETURN Self METHOD Crush() CLASS Rectangle self:Bottom -- self:View() RETURN Self METHOD Expand() CLASS Rectangle self:Bottom ++ self:View() RETURN Self




WAV files - How to play a wav file
The following example shows how to play a wav file. Compile the program with:
hbmk2 test.prg hbwin.hbc -w3. (by Giovanni Di Maria)



PROCEDURE Main() Wapi_PlaySound( "dog.wav" ) RETURN




Debugger - How to call the debugger
The following example shows how to call the debugger. The debugger starts when the value of variable 'a' is equal to 5. Compile the program with:
hbmk2 test.prg -w3 -b. (by Giovanni Di Maria)



PROCEDURE main() LOCAL a, b, c, d, e SetMode( 25, 80 ) cls for a = 1 TO 10 b = a ^ 2 c = b * 5 d = c * 44 + 1 e = d ^ 3 + 22 IF a = 5 AltD() ENDIF next a RETURN




Time - How to show a real time Clock
The following example shows how to display a real time clock, during the execution of the program. The clock is updated continuously. Compile the program with:
hbmk2 test.prg xhb.hbc -w3. (by Giovanni Di Maria)



PROCEDURE main() LOCAL cName, cSurname LOCAL GetList := {} SetMode( 25, 80 ) cls ShowTime( 1, 70, .F. , "rg+/g" ) cName = Space( 20 ) cSurname = Space( 20 ) @ 10, 10 SAY "Name " GET cName @ 12, 10 SAY "Surname " GET cSurname READ ShowTime() RETURN




Time - How to call a function every "n" seconds
The following example shows how to call a function every "n" seconds. It works even if the program is waiting on the menu.(by Giovanni Di Maria)



#include "inkey.ch" PROCEDURE main() LOCAL nOption CLEAR SCREEN SET KEY K_F10 TO TheBeep() KEYSEC( K_F10, 5, - 1 ) nOption = 1 @ 10, 10 PROMPT "Option 1........." @ 11, 10 PROMPT "Option 2........." @ 12, 10 PROMPT "Option 3........." @ 13, 10 PROMPT "Option 4........." MENU TO nOption SET KEY K_F10 TO KEYSEC() RETURN PROCEDURE TheBeep() @ 05, 70 SAY "Beep" Tone( 1000, 2 ) @ 05, 70 SAY Space( 4 ) RETURN




Time - How to call a function at a certain time.
The following example shows how to call a function at a certain time. It works even if the program is waiting on the menu. In this example you can hear a long beep at 12:40:00 o'clock. (by Giovanni Di Maria)



#include "inkey.ch" PROCEDURE main() LOCAL nOption CLEAR SCREEN SET KEY K_F10 TO TheBeep() KEYTIME( K_F10, "12:40:00" ) nOption = 1 @ 10, 10 PROMPT "Option 1........." @ 11, 10 PROMPT "Option 2........." @ 12, 10 PROMPT "Option 3........." @ 13, 10 PROMPT "Option 4........." MENU TO nOption SET KEY K_F10 TO KEYTIME() RETURN PROCEDURE TheBeep() Tone( 2000, 18 ) RETURN




Appendix A - Photos









Appendix B - Contributors




Appendix C - What users think