Chapter 29 Exercises: Menus, Dialogs, and Application Structure
Part A: Conceptual Understanding
A.1. Explain the difference between an accelerator key (like Alt+F for the File menu) and a keyboard shortcut (like Ctrl+S for Save). How are they created differently in Lazarus?
Guidance
An accelerator key is defined by the& prefix in a menu item's Caption (e.g., &File makes Alt+F open the File menu). It navigates the menu system. A keyboard shortcut (set via the ShortCut property) triggers an action directly without opening any menu. Accelerators require the Alt key; shortcuts typically use Ctrl. Accelerators are discovered by looking at the underlined letter in the menu; shortcuts are displayed next to the menu item text.
A.2. What is a TActionList and why is it better than writing separate handlers for menu items, toolbar buttons, and keyboard shortcuts?
Guidance
TActionList centralizes actions — each action defines its code (OnExecute), enabled state (OnUpdate), caption, icon, and shortcut in one place. Multiple UI elements (menu items, toolbar buttons) reference the same action. Without TActionList, you would need to duplicate handler assignments, synchronize Enabled states across multiple controls, and maintain icons and captions independently. TActionList is the single-source-of-truth pattern applied to UI commands.A.3. Describe the sequence of events that occurs when the user clicks the X button to close the application. What is the purpose of each event?
Guidance
1.OnCloseQuery fires first — its purpose is to ask whether the form should close. Set CanClose := False to cancel. This is where you check for unsaved changes. 2. OnClose fires next — its purpose is cleanup (saving settings, closing files). The CloseAction parameter controls what happens (caFree, caHide, caMinimize, caNone). 3. OnDestroy fires last — for final resource deallocation before the form is freed.
A.4. Explain the Filter property format for TOpenDialog/TSaveDialog. Write a Filter string that shows three options: "Pascal Files (.pas)", "All Source Files (.pas;.pp;.inc)", and "All Files (.)".
Guidance
The format isDescription|Pattern|Description|Pattern|... with pipe separators. The answer: 'Pascal Files (*.pas)|*.pas|All Source Files (*.pas;*.pp;*.inc)|*.pas;*.pp;*.inc|All Files (*.*)|*.*'. Multiple patterns within one filter are separated by semicolons within the pattern section.
Part B: Exploration and Analysis
B.1. Create a form with a TMainMenu containing File and Edit menus. Add at least 5 items to each menu with appropriate shortcuts. Experiment with checked items (set Checked := True), disabled items (Enabled := False), and submenus. Document what you observe.
B.2. Create a form with a TMemo and a TPopupMenu. The popup menu should have: Cut, Copy, Paste, Select All, and a separator followed by "Word Count" (which shows the word count in a message dialog). Assign the popup to the memo. Test each operation.
B.3. Explore TIniFile by creating an application that saves and restores: window position/size, a user-entered name, a checkbox state, and a combo box selection. Close and reopen the application to verify persistence. Find where the .ini file is stored on your system.
Part C: Coding Challenges
C.1. Notepad Clone (Intermediate) Build a basic text editor with: TMainMenu (File: New, Open, Save, Save As, Exit; Edit: Cut, Copy, Paste, Select All, Undo; Format: Word Wrap, Font), a TMemo filling the form, a TStatusBar showing line/column count, and TOpenDialog/TSaveDialog for file operations. Track unsaved changes and prompt before closing.
Hints
UseMemo1.Lines.LoadFromFile and Memo1.Lines.SaveToFile for file I/O. Track changes by setting a boolean in the Memo's OnChange event. For line/column, use Memo1.CaretPos (a TPoint with X=column, Y=line). Update the status bar in the Memo's OnClick and OnKeyUp events.
C.2. Settings Dialog (Intermediate) Create a "Preferences" dialog for PennyWise with tabs (use TPageControl): General tab (default currency symbol, date format), Appearance tab (font selection using TFontDialog, color scheme), and Data tab (default save location using a folder dialog, auto-save interval). Save settings to an INI file and apply them when OK is clicked.
C.3. Action List Refactoring (Intermediate) Take the PennyWise project from the chapter checkpoint and refactor it to use TActionList exclusively. Create actions for: New, Open, Save, Save As, Export CSV, Exit, Add Expense, Edit Expense, Delete Expense, Toggle Toolbar, Toggle Status Bar, About. Verify that menu items and toolbar buttons stay synchronized.
C.4. Recent Files Menu (Advanced) Add a "Recent Files" submenu to PennyWise's File menu. It should show the last 5 opened/saved files. Clicking a recent file opens it. The list persists between sessions (stored in the INI file). When a file is opened or saved, it moves to the top of the recent list. If a recent file no longer exists, show it grayed out with "(missing)" appended.
Part M: Metacognitive Exercises
M.1. Before reading section 29.7 (Action Lists), how were you planning to handle the duplication between menu items and toolbar buttons? After reading it, how has your understanding of UI architecture changed?
M.2. Look at a desktop application you use daily (a text editor, file manager, or email client). Map its menu structure. How many levels of nesting does it use? How many keyboard shortcuts does it define? What can you learn from its organization?
M.3. The chapter showed three levels of user notification: status bar messages, message dialogs, and input dialogs. Think of five user-facing messages in PennyWise and categorize each into the appropriate level. Justify your choices.