# FreeBASIC 1.10 pro Windows — pokročilý kurz

Předpoklad: znáš základy (proměnné, `IF`, `FOR`, `SUB`/`FUNCTION`, `PRINT`). Tady jdeme do hloubky — typy, paměť, OOP, Windows API, vlákna, DLL.

---

## 1. Kompilace a přepínače (fbc.exe)

```bat
fbc program.bas                  :: klasický konzolový exe
fbc -s gui program.bas           :: bez konzole (GUI aplikace)
fbc -lang fb program.bas         :: dialekt FB (výchozí, nejsilnější)
fbc -lang qb program.bas         :: QuickBASIC kompatibilita
fbc -lang deprecated program.bas :: starší FB syntaxe
fbc -exx program.bas             :: všechny runtime kontroly (bounds, null ptr...)
fbc -g program.bas               :: debug symboly (pro gdb)
fbc -O 2 program.bas             :: optimalizace
fbc -m ModulName a.bas b.bas     :: víc souborů, hlavní modul explicitně
```

Na Windows 64bit použij `fbc64`, pro 32bit `fbc` (podle instalace). `-s gui` je klíčové pro "opravdové" Windows aplikace bez černého okna.

---

## 2. Typový systém do hloubky

### Pevné typy a jejich velikosti
```freebasic
Dim As Byte      b   ' 1 B, -128..127
Dim As UByte     ub  ' 1 B, 0..255
Dim As Short     s   ' 2 B
Dim As Integer   i   ' 4 B na 32bit, 4 B i na 64bit (pozor, není 8!)
Dim As Long      l   ' vždy 4 B
Dim As LongInt   li  ' vždy 8 B
Dim As Single    f   ' 4 B float
Dim As Double    d   ' 8 B float
Dim As UInteger  ui
```

`Integer` ve FreeBASICu **není** automaticky ukazatelová šířka na 64bit (na rozdíl od C `int`/`size_t`). Pro adresy/indexy do polí používej `Integer` klidně, ale pro ukazatelovou aritmetiku raději `ULongInt`/`Any Ptr`.

### Typová konverze a `Cast`
```freebasic
Dim As Single f = 3.7
Dim As Integer i = CInt(f)      ' zaokrouhlí
Dim As Integer i2 = Int(f)      ' ořízne (floor)

Dim As Any Ptr p = @f
Dim As Single Ptr sp = Cast(Single Ptr, p)  ' explicitní reinterpretace typu
```

### `Type` vs `Class`
`Type` = čistá datová struktura (jako C struct), může mít i metody a konstruktor, ale bez virtuálních funkcí a dědičnosti se v praxi chová jako POD. `Class` = plnokrevná OOP se zděděním a virtuálními metodami (viz sekce 5).

```freebasic
Type Vector3
    x As Single
    y As Single
    z As Single
    Declare Function Length() As Single
End Type

Function Vector3.Length() As Single
    Return Sqr(x*x + y*y + z*z)
End Function

Dim As Vector3 v = (1, 2, 2)
Print v.Length()   ' 3
```

### Union
```freebasic
Union Cislo
    AsInt As Integer
    AsFloat As Single
    AsBytes(0 To 3) As UByte
End Union

Dim As Cislo c
c.AsFloat = 1.5
Print c.AsInt   ' bitová reprezentace floatu jako int
```

---

## 3. Ukazatele a paměť

```freebasic
Dim As Integer x = 42
Dim As Integer Ptr p = @x
Print *p            ' dereference -> 42
*p = 100
Print x              ' 100

' Ukazatelová aritmetika
Dim As Integer arr(10) As Integer
Dim As Integer Ptr pa = @arr(0)
pa += 1
Print *pa            ' arr(1)
```

### Dynamická alokace
```freebasic
Dim As Integer Ptr buf = Allocate(100 * SizeOf(Integer))
If buf = 0 Then
    Print "Alokace selhala"
Else
    For i As Integer = 0 To 99
        buf[i] = i * i
    Next
    Deallocate(buf)
End If

' Callocate = vynulovaná paměť, Reallocate = změna velikosti
Dim As Any Ptr p2 = Callocate(50, SizeOf(Double))
p2 = Reallocate(p2, 100 * SizeOf(Double))
Deallocate(p2)
```

### `New` / `Delete` (objektová alokace)
```freebasic
Type Bod
    x As Integer
    y As Integer
End Type

Dim As Bod Ptr b = New Bod
b->x = 5 : b->y = 10
Delete b

Dim As Bod Ptr pole = New Bod[100]   ' pole objektů na heapu
Delete[] pole
```

Pravidlo: `Allocate`/`Deallocate` pro syrovou paměť (C-styl, žádné konstruktory), `New`/`Delete` když typ má konstruktor/destruktor.

---

## 4. Řetězce — pořádně

FreeBASIC má **dva** typy stringů:

- `String` — dynamický, garbage-collected na pozadí (referenčně počítaný buffer), pohodlný.
- `ZString` / `String * n` — C-styl (null-terminated) nebo pevná délka, nutné pro Windows API.

```freebasic
Dim As String s = "Ahoj svete"
Dim As ZString * 260 buf   ' pevný buffer, typicky na cesty (MAX_PATH)

' Konverze String -> ZString pro WinAPI volání
Dim As String cesta = "C:\test.txt"
Dim As ZString Ptr zp = StrPtr(cesta)   ' pozor, platí jen dokud "cesta" žije

' Wide (Unicode) řetězce pro *W varianty WinAPI funkcí
Dim As WString * 260 wbuf
wbuf = "Ahoj UTF-16"
```

### Práce s Unicode na Windows
Pro plnou podporu Unicode kompiluj s `-lang fb` (výchozí) a používej `WString`, případně `*W` verze API funkcí (`MessageBoxW`, `CreateWindowExW`...). `Str()`, `Val()`, `Format()` fungují jen na `String` (ANSI/UTF-8 bufferu), pro převod:

```freebasic
Dim As WString * 100 w
Dim As String a = "test"
w = a   ' implicitní konverze ANSI -> wide
```

---

## 5. Objektově orientované programování

```freebasic
Type Zvire Extends Object
    Protected:
        jmeno As String
    Public:
        Declare Constructor(jmeno As String)
        Declare Virtual Function Zvuk() As String
        Declare Sub Predstav()
End Type

Constructor Zvire(jmeno As String)
    This.jmeno = jmeno
End Constructor

Function Zvire.Zvuk() As String
    Return "..."
End Function

Sub Zvire.Predstav()
    Print jmeno & " dela: " & This.Zvuk()
End Sub

Type Pes Extends Zvire
    Public:
        Declare Constructor(jmeno As String)
        Declare Virtual Function Zvuk() As String Override
End Type

Constructor Pes(jmeno As String)
    Base(jmeno)   ' volání konstruktoru rodiče
End Constructor

Function Pes.Zvuk() As String
    Return "Haf!"
End Function

Dim As Pes p = Pes("Rex")
p.Predstav()   ' Rex dela: Haf!

' Polymorfismus přes ukazatel
Dim As Zvire Ptr zp = @p
zp->Predstav()   ' díky Virtual/Override zavolá Pes.Zvuk
```

Klíčová slova: `Virtual` (deklaruje virtuální metodu — nutné pro pozdní vazbu), `Override` (explicitně přepisuje), `Abstract` (čistě virtuální, typ nejde instanciovat), `Final` (nejde dál dědit/přepsat).

```freebasic
Type Tvar Extends Object Abstract
    Declare Abstract Function Obsah() As Double
End Type
```

### Vlastnosti (Property)
```freebasic
Type Ucet
    Private:
        zustatek As Double
    Public:
        Declare Property Zustatek() As Double
        Declare Property Zustatek(hodnota As Double)
End Type

Property Ucet.Zustatek() As Double
    Return zustatek
End Property

Property Ucet.Zustatek(hodnota As Double)
    If hodnota >= 0 Then zustatek = hodnota
End Property

Dim As Ucet u
u.Zustatek = 500
Print u.Zustatek
```

### Operátorové přetěžování
```freebasic
Type Komplex
    re As Double
    im As Double
    Declare Operator + (rhs As Komplex) As Komplex
End Type

Operator Komplex.+ (rhs As Komplex) As Komplex
    Dim As Komplex vysl
    vysl.re = This.re + rhs.re
    vysl.im = This.im + rhs.im
    Return vysl
End Operator

Dim As Komplex a = (1, 2), b = (3, 4)
Dim As Komplex c = a + b
```

---

## 6. Namespace a moduly

```freebasic
Namespace Geometrie
    Function Obvod(r As Double) As Double
        Return 2 * Pi * r
    End Function
End Namespace

Print Geometrie.Obvod(5)
' nebo
Using Geometrie
Print Obvod(5)
```

Pro víc souborů: `.bas` soubory se sdíleným kódem includuj přes `#Include Once "soubor.bi"` (hlavičky `.bi` s deklaracemi) a linkuj přes `fbc -m Main main.bas modul.bas`.

---

## 7. Chyby a ošetření za běhu

FreeBASIC nemá klasické `try/catch`, ale má:

```freebasic
' 1) Kontrola návratových kódů / Err()
Open "neexistuje.txt" For Input As #1
If Err() <> 0 Then Print "Chyba: " & Err()

' 2) ON ERROR (starší styl, funguje i v FB dialektu)
On Error Goto Handler
Dim As Integer x = 10 / 0
Goto Konec
Handler:
    Print "Chyba c. " & Err()
Konec:

' 3) -exx při kompilaci zapne bounds-checking a null-pointer kontrolu,
'    důležité během vývoje, vypni pro release kvůli výkonu.
```

Pro robustní vlastní chyby je běžné dělat návratové kódy / `Result Ptr` vzory, případně `CException`-like typy vlastní výroby s `Type`.

---

## 8. Multithreading

```freebasic
Dim Shared As Integer citac = 0
Dim Shared As Any Ptr mutex

Sub VlaknoFunkce(ByVal data As Any Ptr)
    For i As Integer = 1 To 100000
        MutexLock(mutex)
        citac += 1
        MutexUnlock(mutex)
    Next
End Sub

mutex = MutexCreate()
Dim As Any Ptr t1 = ThreadCreate(@VlaknoFunkce)
Dim As Any Ptr t2 = ThreadCreate(@VlaknoFunkce)
ThreadWait(t1)
ThreadWait(t2)
MutexDestroy(mutex)
Print citac   ' 200000
```

`Dim Shared` je nutné — proměnné pro sdílení mezi vlákny musí být sdílené (globální nebo staticky sdílené), jinak každé vlákno vidí vlastní kopii lokálních proměnných.

---

## 9. Windows API a DLL

### Volání WinAPI přímo
```freebasic
#Include Once "windows.bi"

MessageBox(0, "Ahoj z FreeBASICu", "Titulek", MB_OK Or MB_ICONINFORMATION)

Dim As HWND hwnd = GetForegroundWindow()
Dim As RECT r
GetWindowRect(hwnd, @r)
Print r.right - r.left
```

`windows.bi` obsahuje kompletní deklarace WinAPI — struktury, konstanty, funkce. Je součástí instalace FB.

### Vlastní DLL
```freebasic
' mojedll.bas — přeložit: fbc -dll mojedll.bas
Declare Function Secti CDecl Alias "Secti" (ByVal a As Integer, ByVal b As Integer) As Integer Export

Function Secti CDecl (ByVal a As Integer, ByVal b As Integer) As Integer Export
    Return a + b
End Function
```

Volání z jiného FB programu:
```freebasic
Declare Function Secti CDecl Alias "Secti" Lib "mojedll.dll" (ByVal a As Integer, ByVal b As Integer) As Integer

Print Secti(3, 4)   ' 7
```

`CDecl` je důležité pro kompatibilitu volací konvence s C/WinAPI (na rozdíl od výchozí `Pascal`/`StdCall` konvence FB pro některé kontexty — u WinAPI funkcí se typicky používá `Alias` s originálním jménem a `Lib "user32.dll"` apod.).

### Volání funkce ze `.dll` bez `.bi` hlavičky
```freebasic
Declare Function GetTickCount64 Lib "kernel32.dll" Alias "GetTickCount64" () As ULongInt
Print GetTickCount64()
```

---

## 10. Inline assembler (jen na x86/x86_64)

```freebasic
Dim As Integer a = 5, b = 10, vysledek

Asm
    mov eax, [a]
    add eax, [b]
    mov [vysledek], eax
End Asm

Print vysledek   ' 15
```

Používá se AT&T i Intel syntax dle nastavení (`-asm intel` při kompilaci pro Intel styl). Vhodné pro kritické výkonové úseky nebo přístup k CPU instrukcím (CPUID, SIMD).

---

## 11. Preprocesor a makra

```freebasic
#Define MAX(a, b) IIf((a) > (b), (a), (b))
#Define VERZE "1.0.3"

#IfDef __FB_WIN32__
    Print "Beží na Windows"
#EndIf

#If __FB_64BIT__
    Print "64bitová verze"
#EndIf
```

Užitečné vestavěné makrosymboly: `__FB_WIN32__`, `__FB_LINUX__`, `__FB_64BIT__`, `__FB_VERSION__`, `__DATE__`, `__TIME__`, `__FUNCTION__`.

---

## 12. Grafika bez WinAPI (vestavěná knihovna FB Graphics)

```freebasic
Screen 19, 32, , 2   ' 800x600, 32bit barva, double buffering (fbgfx)
Dim As Integer x = 0

Do
    ScreenLock
    Cls
    Circle (x, 300), 40, RGB(255, 0, 0),,,, F
    ScreenUnlock
    x += 2 : If x > 800 Then x = 0
    Sleep 16
Loop Until MultiKey(FB.SC_ESCAPE)
```

Pro reálné GUI aplikace (okna, tlačítka) se ale na Windows obvykle jde přímo přes `windows.bi` (vlastní message loop, `RegisterClassEx`, `CreateWindowEx`) — to je "opravdový" pokročilý Windows FreeBASIC vývoj.

Minimální kostra Win32 okna:
```freebasic
#Include Once "windows.bi"

Declare Function WndProc(ByVal hwnd As HWND, ByVal msg As UInteger, _
    ByVal wp As WPARAM, ByVal lp As LPARAM) As LRESULT

Dim As WNDCLASSEX wc
wc.cbSize = SizeOf(wc)
wc.lpfnWndProc = @WndProc
wc.hInstance = GetModuleHandle(0)
wc.lpszClassName = @"MojeOkno"
wc.hCursor = LoadCursor(0, IDC_ARROW)
RegisterClassEx(@wc)

Dim As HWND hwnd = CreateWindowEx(0, "MojeOkno", "Titulek", WS_OVERLAPPEDWINDOW, _
    100, 100, 400, 300, 0, 0, GetModuleHandle(0), 0)
ShowWindow(hwnd, SW_SHOW)

Dim As MSG msg
While GetMessage(@msg, 0, 0, 0)
    TranslateMessage(@msg)
    DispatchMessage(@msg)
Wend

Function WndProc(ByVal hwnd As HWND, ByVal msg As UInteger, _
    ByVal wp As WPARAM, ByVal lp As LPARAM) As LRESULT
    Select Case msg
        Case WM_DESTROY
            PostQuitMessage(0)
            Return 0
    End Select
    Return DefWindowProc(hwnd, msg, wp, lp)
End Function
```
Kompiluj s `-s gui`, jinak se navíc otevře konzole.

---

## 13. Binární I/O a soubory

```freebasic
Type Zaznam
    id As Integer
    jmeno As String * 30
End Type

Dim As Integer f = FreeFile
Open "data.bin" For Binary As #f

Dim As Zaznam z
z.id = 1 : z.jmeno = "Petr"
Put #f, , z          ' zápis raw struktury

Dim As Zaznam nacteny
Get #f, 1, nacteny    ' čtení 1. záznamu (Binary indexuje od 1 po velikosti typu)
Close #f
```

Pozor: `String` uvnitř `Type` pro binární I/O musí být pevné délky (`String * n`), dynamický `String` obsahuje jen ukazatel, ne data.

---

## 14. Co dál

- `fbc --help` a `windows.bi` (v instalaci FB, obsahuje tisíce deklarací) jsou tvoji nejlepší kamarádi pro WinAPI detaily.
- Oficiální wiki: freebasic.net/wiki — sekce `KeyPg*` (Key Pages) má referenci každého klíčového slova s příklady.
- Fórum freebasic.net má aktivní komunitu i pro pokročilé WinAPI/DLL/multithreading dotazy.

Chceš, abych se zaměřil hlouběji na některé z těchto témat — třeba psaní vlastní GUI knihovny nad WinAPI, COM interop, nebo optimalizaci výkonu (SIMD/inline asm)?
