TKnob
Source: source/classes/tknob.prg | Command: include/tknob.ch
Inherits from: TControl
Contributed by Silvio Falconi.
TKnob is a modern custom rotary knob control for FiveWin / Harbour, designed for audio,
MIDI and synthesizer style applications (mixers, drum machines, VST-like interfaces and
touch screens). It is a pure Harbour/FiveWin implementation built on TControl —
all drawing is done with GDI primitives, so no extra DLL is required.
Features
- Modern rotary knob design with compact control area and correct clipping.
- Transparent / themed background support (
IsAppThemed()). - Two indicator modes: LED (dot) or LINE.
- External illuminated ring with soft glow, plus optional external ticks (
lTicks). - Unipolar mode (0..127) and Bipolar mode (-30..+30, shows signed value).
- Mouse drag (vertical) and mouse wheel control; hold CTRL for a finer wheel step.
- Double click resets to the default value.
- Enable / disable state with dimmed visual feedback (
Toggle()). - Internal value display and external label, with separate fonts (
oFontInner/oFont). bSetGetvariable binding,bChangedandbActioncallbacks.
Key DATA Members
| DATA | Type | Default | Description |
|---|---|---|---|
nValue | Numeric | 64 | Current value (clamped to nMin..nMax) |
nMin | Numeric | 0 | Minimum value |
nMax | Numeric | 127 | Maximum value |
nDefault | Numeric | 64 | Value restored on double click |
cIndicator | Char | "LED" | Indicator style: "LED" or "LINE" |
cMode | Char | "UNIPOLAR" | Range mode: "UNIPOLAR" or "BIPOLAR" |
lTicks | Logical | .F. | Draw external tick marks around the ring |
lActive | Logical | .T. | Enabled state (dimmed when .F.) |
nWheelStep / nCtrlStep | Numeric | 1 | Wheel step, and finer step while CTRL is held |
oFont / oFontInner | Object | Fonts for the external label and the inner value text | |
bSetGet | Block | SetGet codeblock for variable binding (read/write) | |
bChanged | Block | Fired when the value changes; receives ( Self, nValue ) | |
bAction | Block | Fired on toggle; receives ( Self, lActive ) |
Methods
| Method | Description |
|---|---|
New( nTop, nLeft, bSetGet, oWnd, nWidth, nHeight, cMsg, nMin, nMax, cIndicator, cMode, lTicks, bAction, lDesign, oFont, oFontInner ) | Create a new knob control |
SetValue( nValue ) | Set the value (clamped), fire bSetGet/bChanged and repaint |
GetValue() | Return the current nValue |
SetMode( cMode ) | Switch between "UNIPOLAR" (0..127) and "BIPOLAR" (-30..+30) and reset range/default |
Toggle() | Flip the enabled state and fire bAction |
Display() / Paint() | Render the knob (ring, glow arc, body, indicator, value, label) |
Destroy() | Destroy the control |
The @ ... KNOB Command
Include tknob.ch to use the declarative command:
@ <nRow>, <nCol> KNOB <oKnob> ;
VAR <nVar> ;
OF <oWnd> ;
SIZE <nWidth>, <nHeight> ;
LABEL <cMsg> ;
MIN <nMin> MAX <nMax> ;
[ LED | LINE ] ;
[ UNIPOLAR | BIPOLAR ] ;
[ TICKS | NOTICKS ] ;
FONT <oFont> FONTINNER <oFontInner> ;
[ ON CHANGE <uChange> ] ;
[ ACTION <uAction> ]
Example: Volume & Modulation Knobs
#include "FiveWin.ch"
#include "tknob.ch"
function Main()
local oDlg, oFont, oFontInner
local oKnobVol, oKnobMod, oSayVol, oSayMod
local nVol := 0, nMod := 64
DEFINE FONT oFont NAME "Segoe UI" SIZE 0, -11 BOLD
DEFINE FONT oFontInner NAME "Segoe UI" SIZE 0, -14 BOLD
DEFINE DIALOG oDlg TITLE "TKnob" SIZE 780, 280 PIXEL
@ 35, 150 SAY oSayVol PROMPT "VOL: " + AllTrim( Str( nVol ) ) ;
SIZE 40, 10 PIXEL OF oDlg
@ 35, 40 KNOB oKnobVol VAR nVol OF oDlg SIZE 76, 86 ;
LABEL "VOL" MIN -30 MAX 30 LED BIPOLAR NOTICKS ;
FONT oFont FONTINNER oFontInner ;
ON CHANGE { |o,n| oSayVol:SetText( "VOL: " + AllTrim( Str( n ) ) ) }
@ 35, 370 SAY oSayMod PROMPT "MOD: " + AllTrim( Str( nMod ) ) ;
SIZE 50, 10 PIXEL OF oDlg
@ 35, 200 KNOB oKnobMod VAR nMod OF oDlg SIZE 76, 86 ;
LABEL "MOD" MIN 0 MAX 200 LINE UNIPOLAR TICKS ;
FONT oFont FONTINNER oFontInner ;
ON CHANGE { |o,n| oSayMod:SetText( "MOD: " + AllTrim( Str( n ) ) ) }
ACTIVATE DIALOG oDlg CENTERED ;
VALID ( oFont:End(), oFontInner:End(), .T. )
return nil
Notes
- Drag the knob vertically to change the value; the mouse wheel also works, and holding CTRL uses the finer
nCtrlStep. - A single click (no drag) toggles the enabled state via
Toggle(); a double click resets tonDefault. - In
BIPOLARmode the inner value is shown signed (e.g.+12) and the green arc starts from the center (zero) position. - Bind a variable with
VAR(the command wraps it in abSetGetblock) or setbSetGetmanually; useON CHANGEfor UI updates. - Demos:
samples/knobtst1.prg(directNew) andsamples/knobtst2.prg(command syntax).