Tutorial: Working with Forms
Most real-world applications need more than one window. In this tutorial you will build a multi-form project with a main form and a settings dialog. You will learn how to open forms modally, pass data between them, and configure common form properties.
Step 1: Set Up the Project
- Create a new project called
MultiFormDemovia File → New Project. - The IDE creates
main.prgwith a starter form. - We will add a second source file for the settings form in the next step.
Step 2: Design the Main Form
- Open
main.prgin the Form Designer. - Set the form title to
"Multi-Form Demo"and size to700, 500. - Add a Label at the top to display the current username — set
cValueto"User: (none)". - Add a Button with
cPromptset to"Open Settings".
Your main form code will look like this:
#include "hbbuilder.ch" function Main() local oForm, oLblUser, oBtnSettings DEFINE FORM oForm TITLE "Multi-Form Demo" ; SIZE 700, 500 FONT "Segoe UI", 10 @ 30, 50 LABEL oLblUser VALUE "User: (none)" ; OF oForm SIZE 300, 24 @ 80, 50 BUTTON oBtnSettings PROMPT "Open Settings" ; OF oForm SIZE 140, 36 ; ACTION OpenSettings( oForm, oLblUser ) ACTIVATE FORM oForm CENTERED return nil
Step 3: Create the Settings Form
- Select File → New Form to add a second form to the project. Name it
settings.prg. - In the Form Designer for
settings.prg, set the title to"Settings"and size to400, 300. - Add a Label with
cValue"Your name:"at row 30, col 30. - Add a TextBox (
TGet) next to the label for the user to type their name. - Add a CheckBox below with
cPrompt"Enable dark mode". - Add two buttons: "OK" and "Cancel" at the bottom.
Step 4: Implement ShowModal and Data Passing
The key technique is to call ShowModal() on the settings form. This blocks the main form
until the user closes the dialog. After the modal form closes, you read back the values the
user entered.
static function OpenSettings( oMainForm, oLblUser ) local oSettings, oGetName, oChkDark, oBtnOK, oBtnCancel local cName := "", lDark := .F., nResult DEFINE FORM oSettings TITLE "Settings" ; SIZE 400, 300 FONT "Segoe UI", 10 ; STYLE "dialog" @ 30, 30 LABEL oLbl VALUE "Your name:" ; OF oSettings SIZE 100, 24 @ 30, 140 GET oGetName VAR cName ; OF oSettings SIZE 220, 24 @ 70, 30 CHECKBOX oChkDark VAR lDark ; PROMPT "Enable dark mode" ; OF oSettings SIZE 200, 24 @ 220, 180 BUTTON oBtnOK PROMPT "OK" ; OF oSettings SIZE 90, 32 ; ACTION ( oSettings:nModalResult := 1, oSettings:Close() ) @ 220, 280 BUTTON oBtnCancel PROMPT "Cancel" ; OF oSettings SIZE 90, 32 ; ACTION ( oSettings:nModalResult := 0, oSettings:Close() ) nResult := oSettings:ShowModal( oMainForm ) if nResult == 1 oLblUser:SetValue( "User: " + cName ) if lDark oMainForm:SetDarkMode( .T. ) else oMainForm:SetDarkMode( .F. ) endif endif return nil
Use ShowModal( oParent ) when the user must complete the dialog before returning to the parent.
Use Show() for non-blocking windows that the user can switch between freely.
Step 5: Form Properties Reference
Here are the most commonly used form properties you can set in the Object Inspector or in code:
| Property | Type | Description |
|---|---|---|
cTitle |
String | Text shown in the form's title bar. |
nWidth / nHeight |
Numeric | Form dimensions in pixels. |
lMaximize |
Logical | Whether the maximize button is enabled. |
lMinimize |
Logical | Whether the minimize button is enabled. |
lResizable |
Logical | Whether the user can resize the form. |
cStyle |
String | "normal", "dialog", or "toolwindow". |
nModalResult |
Numeric | Return value after ShowModal(). Set before calling Close(). |
Step 6: Build and Test
- Press F9 to build and run.
- Click "Open Settings" on the main form — the settings dialog appears modally.
- Type a name, toggle the checkbox, and click OK.
- The main form label updates to show the name you entered.
- Open the dialog again and click Cancel — the main form remains unchanged.
Form Lifecycle Flow
ACTIVATE FORM CENTERED"] --> B["User clicks
Open Settings"] B --> C["Settings Form
ShowModal( oMainForm )"] C --> D{"User action"} D -->|"OK"| E["nModalResult = 1
Close()"] D -->|"Cancel"| F["nModalResult = 0
Close()"] E --> G["Main form reads
cName and lDark"] F --> H["Main form ignores
dialog values"] style A fill:#58a6ff,stroke:#388bfd,color:#0d1117 style C fill:#d2a8ff,stroke:#bc8cff,color:#0d1117 style E fill:#3fb950,stroke:#2ea043,color:#0d1117 style F fill:#f0883e,stroke:#d18616,color:#0d1117
Now that you can work with multiple forms, continue to the Event Handling tutorial to learn about all the event types available in HarbourBuilder.