Delphi Tips & Techniques. Brian Long (brian@falafel.com) Master Consultant Falafel Software. Before We Begin. Hours: 8:00 – 12:00 Break Time: 10:00 – 10:30 Please ask questions as we go along Let’s keep this informal. Agenda. The IDE The language The RTL The debugger Windows .NET.
Une image / un lien ci-dessous est fourni (tel quel) pour télécharger la présentation
Politique de téléchargement : le contenu du site vous est fourni TEL QUEL pour votre information et votre usage personnel ; il ne peut être vendu, concédé sous licence ni partagé sur d’autres sites sans l’accord de son auteur.Le contenu vous est fourni TEL QUEL, pour votre information et votre usage personnel uniquement.Téléchargez la présentation en cliquant sur ce lien.Lors du téléchargement, si vous ne parvenez pas à télécharger une présentation, l’éditeur a peut-être supprimé le fichier de son serveur.Pendant le téléchargement, si vous ne parvenez pas à obtenir une présentation, le fichier a peut-être été supprimé par l’éditeur.
Before We Begin • Hours: 8:00 – 12:00 • Break Time: 10:00 – 10:30 • Please ask questions as we go along • Let’s keep this informal
Agenda • The IDE • The language • The RTL • The debugger • Windows • .NET
The IDE • Toolbars • The Editor • The Form Designers • The Object Inspector • Miscellaneous • Enhancing from within • Undocumented registry entries
Toolbars • Save mouse-clicks with the File | Open toolbutton’s drop down menu • Less need to switch to the Project Manager with the Run | Run tool button’s drop down button • Avoid unneeded debugging with Run | No Debug • Restore corrupted toolbars • Move toolbars between systems
Code Insight et al Code Folding Refactoring Help Insight Error Insight Editor bookmarks Keyboard macros Case switching Buffer list Block marking Block indent / unindent Block operations Bracket matching Various selection / deletion operations Incremental search Drag & drop The Editor
The Editor • An overwhelming number of keyboard shortcuts available • In Delphi 7 help under “shortcuts” • In Delphi 8/“Diamondback” help via Reference | Keyboard Mappings • Many based on the ancient WordStar word processor keyboard shortcuts • Many were present in Turbo Pascal & Borland Pascal • Ctrl+Q+? is a Quick operation • Ctrl+K+? is a blocK operation • Ctrl+O+? is an Other operation • More recent additions just fill in any available gaps
The Editor • Code Insight – Code Completion • Manually invoked by Ctrl+Space • Supports being alpha-sorted • Supports being resized • Supports automatically adding units into the uses clause:HKCU\...\7.0\Code Insight\ExtraUnits(feature removed in Delphi 8, replaced in Delphi “Diamondback” with new option:Refactor | Find Unit)
The Editor • Code Insight – Code Parameters • Manually invoked with Ctrl+Shift+Space • Code Insight – Code Templates • Manually invoked with Ctrl+J • Stored in the text file delphi32.dci / bds.dci
The Editor • Code browsing • Ctrl+click on an identifier • context menu, Find declaration • Navigation buttons: Alt+← & Alt+→ • Module navigation • Ctrl+Shift+↓ or Ctrl+Shift+↑ • Class completion • Ctrl+Shift+C • Good property implementation
The Editor • Help Insight • Enabled by default • Ctrl+Shift+H • Works with Code Completion window • Error Insight • Enabled by default • Symbol existence verification
The Editor • Bookmarks • Toggle: Ctrl+Shift+n or Ctrl+K+n • Go to: Ctrl+n or Ctrl+Q+n (n = 0, 1, 2, ..., 9) • Not persisted in project desktops • Alternative is to use disabled breakpoints, which are persisted • Use the Breakpoints window to navigate (View | Debug Windows | Breakpoints)
The Editor • Keyboard macros: • Start/stop recording: Ctrl+Shift+R • Playback: Ctrl+Shift+P • Limited to editor keystrokes only • Macro toolbar (added officially in Delphi 8, unofficially in Delphi 7)
The Editor • Block operations • Toggle comment: Ctrl+/ • Write to text file: Ctrl+K+W • Read from text file: Ctrl+K+R • Print: Ctrl+K+P
The Editor • Bracket matching (almost obsolete in Delphi 8+) • Alt+[ • Alt+] • Ctrl+Q+[ • Ctrl+Q+] • Matches {,} and (,) • Does not match begin,end
The Editor • Selecting the current word • Ctrl+K+T • Deleting to the next word • Ctrl+T • Deleting to the end of the line • Ctrl+Shift+Y, Ctrl+Q+Y • Deleting the current line • Ctrl+Y
The Editor • Selecting the current line • Ctrl+K+L • Selecting lines • Home, Shift+↑ or Shift+↓ • Incremental search • Ctrl+Shift+S (or Ctrl+E in Classic)
The Editor • Drag & drop • Dragging text moves it • Ctrl+dragging text copies it • Same functionality as Microsoft Word • Preserves clipboard content
The Form Designers • Selecting a component’s parent • Escape • Selecting the form • VCL: Select a component, then Shift+click it • WinForms: Click form caption bar • Lassoing on a container • VCL: Ctrl+drag mouse • WinForms: drag the mouse
The Object Inspector • Property editor keyboard access • Ctrl+Enter • Incremental property search • Tab • Instance list • Ctrl+↓ • Following linked components (VCL-only) • Ctrl+double-click
Miscellaneous • Drag & drop RAD now works (kinda)! • MPD keyboard shortcuts • Ctrl+Tab and Shift+Ctrl+Tab • IDE memory consumption • IDE command line switches –hm and -hv • Preventing docking • Hold down Ctrl • Use the environment option
Enhancing from within • Implement a Win32 package • In Register procedure use e.g.: • Application • Application.MainForm • Application.FindComponent • Modify aspects of IDE as you choose • Tidy up in the finalization section • Use ToolsAPI for official route
Undocumented registry • All relative to HKCU\Software\Borland\ • Removing Ctrl+Alt shortcuts Delphi\7.0\Editor\Options\NoCtrlAltKeys="1“ Tools | Options | Editor Options | Key Mappings | Use Ctrl+Alt keys • Delphi 7 Macro toolbar (as in later versions) Delphi\7.0\Extras\ShowRecordMacro="1" • Delphi for .NET Reflection IL Disassembly BDS\3.0\Globals\ShowILDisassembly="1" • Designer Insight (WinForms) BDS\3.0\DesignerInsight\Visible="1"
The language • Logical array indices • Arrays need not be indexed by numbers • A typical array is specified using a subrange, e.g.:MyArray[ 1..10 ] of Byte; • Subranges can be made from any ordinal type, e.g.:MyArray[ Boolean ] of String;
The language • Typed constants • Very useful for initialising constant arrays & records • Currently defaults to actually being constant • Toggling the option allows them to be used like C static variables: • {$WRITEABLECONST ON} • {$J+}
The language • Typed constants • procedure TForm1.UpdateUI; • begin • if Length( Trim( edtTextEntry.Text ) ) = 0 then • Bar.SimpleText := 'No text to add' • else • Bar.SimpleText := 'You can add the text' • end; • ↓ • procedure TForm1.UpdateUI; • const • Desc: array[ Boolean ] of String = • ( 'No text to add', 'You can add the text' ); • begin • Bar.SimpleText := • Desc[ Length( Trim( edtTextEntry.Text ) ) <> 0 ]; • end;
The language • Sets & cases • Conditionals easily become cumbersome (develop a surfeit of brackets) • Conditionals that compare a variable against a number of values can be simplified using sets or case statements • If the values have an ordinal value less than 256 a set can be used • Otherwise you can employ a case statement
The language • Sets & cases • procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); • begin • if (Key = VK_UP) or (Key = VK_DOWN) or • (Key = VK_LEFT) or (Key = VK_RIGHT) then • begin • Bar.SimpleText := 'Cursor key'; • Key := 0; • end • else • if (Key = VK_PRIOR) or (Key = VK_NEXT) then • begin • Bar.SimpleText := 'Page movement key'; • Key := 0; • end • else • Bar.SimpleText := 'Miscellaneous key' • end;
The language • Sets & cases • procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); • begin • if Key in [ VK_LEFT..VK_DOWN ] then • begin • Bar.SimpleText := 'Cursor key'; • Key := 0; • end • else • if Key in [ VK_PRIOR, VK_NEXT ] then • begin • Bar.SimpleText := 'Page movement key'; • Key := 0; • end • else • Bar.SimpleText := 'Miscellaneous key' • end;
The language • Sets & cases • procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); • begin • case Key of • VK_LEFT..VK_DOWN: • begin • Bar.SimpleText := 'Cursor key'; • Key := 0; • end; • VK_PRIOR, VK_NEXT: • begin • Bar.SimpleText := 'Page movement key'; • Key := 0; • end • else • Bar.SimpleText := 'Miscellaneous key' • end • end;
The language • Concise object creation (who needs a variable?) • procedure TForm1.Button1Click(Sender: TObject); • const • RegPath = 'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; • RegEntry = 'HideFileExt'; • begin • with TRegistry.Create do • try • if OpenKey( RegPath, False ) then • WriteInteger( RegEntry, 0 ) • finally • Free • end • end;
The language • Accessing protected members • Delphi’s definition of protected is not the same as in C++ • It’s more like C++’s protected with friend classes • Rather like C#’s protected internal • Akin to .NET CLR’s family or asembly • Protected members are accessible to: • any derived classes • any code in the target class’s unit
The language • Accessing protected members • A common trick is to implement so called “access” classes or “hack” classes to gain access to protected members • An access class is a shallow descendant defined in the unit where access is required: type TWCAccess = class( TWinControl ); • Used several times in the VCL source • Search VCL / VCL for .NET source for: Access = class(T
The language • Accessing protected members • Another trick uses “interposer” classes • These are defined in the unit requiring access • Distinguishing feature is the name is the same as the original, thereby removing the need for a typecast: type TDBGrid = class( DBGrids.TDBGrid );
The language • Accessing private members • No easy answer to this except hacking • Relies on you knowing: • how many data fields precede the target private data field • Which class the field was added in • how many bytes they take up • Add to this the ancestor class’s instance size • You now have the offset from the start of the instance data
The language • Accessing private members • function GetPrivateField(Obj: TObject; Cls: TClass; DataOffset: Cardinal): Pointer; • var • ParentInstanceSize: Cardinal; • begin • //Get parent instance data size • //and add on the VMT pointer • ParentInstanceSize := Cls.ClassParent.InstanceSize + 4; • Result := Pointer( Cardinal( Obj ) + ParentInstanceSize + DataOffset ) • end; • var • FocusedCtl: TWinControl; • ... • FocusedCtl := TWinControl( • GetPrivateField( Self, TCustomForm, 4 )^ );
The language • Characters • Characters don’t need concatenation • They can be effectively embedded in the string as long as there is no white spaceCaption := 'Copyright '#169' 2004, Me';