delphi tips & techniques brian long ([email protected]) master consultant falafel software

73
Delphi Tips & Techniques Brian Long ([email protected]) Master Consultant Falafel Software

Upload: patience-hunter

Post on 26-Dec-2015

226 views

Category:

Documents


1 download

TRANSCRIPT

Delphi Tips & Techniques

Brian Long ([email protected])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

AgendaThe IDEThe languageThe RTLThe debuggerWindows.NET

The IDEToolbars

The Editor

The Form Designers

The Object Inspector

Miscellaneous

Enhancing from within

Undocumented registry entries

ToolbarsSave 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

The EditorCode 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 EditorAn overwhelming number of keyboard shortcuts availableIn Delphi 7 help under “shortcuts”In Delphi 8/“Diamondback” help via Reference | Keyboard

MappingsMany based on the ancient WordStar word processor

keyboard shortcutsMany were present in Turbo Pascal & Borland PascalCtrl+Q+? is a Quick operationCtrl+K+? is a blocK operationCtrl+O+? is an Other operationMore recent additions just fill in any available gaps

The EditorCode 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 EditorCode 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 EditorCode 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 EditorCode Folding

– Ctrl+Shift+K+G Fold interface and implementation– Ctrl+Shift+K+E Fold | Nearest– Ctrl+Shift+K+N Fold | Namespace (Unit)– Ctrl+Shift+K+C Fold | Types– Ctrl+Shift+K+M Fold | Methods– Ctrl+Shift+K+R Fold | Regions– Ctrl+Shift+K+P Fold | Nested Methods– Ctrl+Shift+K+U Unfold | Nearest– Ctrl+Shift+K+A Unfold | All– Ctrl+Shift+K+O Toggle code folding

The EditorRefactoring

– Ctrl+Shift+V Declare Variable– Ctrl+Shift+D Declare Field– Ctrl+Shift+M Extract Method– Ctrl+Shift+L Extract Resource String– Ctrl+Shift+A Find Unit– Ctrl+Shift+E Rename– Ctrl+Shift+J Sync Edit

The EditorHelp Insight

– Enabled by default– Ctrl+Shift+H– Works with Code Completion window

Error Insight

– Enabled by default

– Symbol existence verification

The EditorBookmarks

– 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 EditorKeyboard 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 EditorCase-switching:

– Upper case: Ctrl+K+N– Lower case: Ctrl+K+O– Toggle case: Ctrl+O+U

Buffer list:– Ctrl+B– Implemented in Win32 DclSmpEdit70.dpk

ToolsAPI package demo

The EditorBlock marking

– Shift+navigation keys• Non-inclusive: Ctrl+O+K (default)• Inclusive: Ctrl+O+I• Line: Ctrl+O+L• Column: Ctrl+O+C

– Alt+Shift+navigation keys or Alt+mouse• Column block marking

The EditorBlock indent

– Ctrl+Shift+I– Ctrl+K+I

Block unindent– Ctrl+Shift+U– Ctrl+K+U

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 EditorBracket matching (almost obsolete in Delphi 8+)

– Alt+[– Alt+]– Ctrl+Q+[– Ctrl+Q+]– Matches {,} and (,)– Does not match begin,end

The EditorSelecting 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 EditorSelecting the current line

– Ctrl+K+L

Selecting lines– Home, Shift+↑ or Shift+↓

Incremental search– Ctrl+Shift+S (or Ctrl+E in Classic)

The EditorDrag & drop

– Dragging text moves it– Ctrl+dragging text copies it

– Same functionality as Microsoft Word

– Preserves clipboard content

The Form DesignersSelecting a component’s parent

– EscapeSelecting 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 Form DesignersMoving & sizing components:

VCL designer WinForms designer

Move by one grid unit

Ctrl+Shift+cursor keys or drag component

Cursor keys or drag component

Move by one pixel Ctrl+cursor keys or Alt+drag component

Ctrl+cursor keys

Resize by one grid unit

Drag grab handle Shift+cursor keys or drag grab handle

Resize by one pixel Shift+cursor keys or Alt+drag grab handle

Ctrl+Shift+cursor keys

The Object InspectorProperty editor keyboard access

– Ctrl+Enter

Incremental property search– Tab

Instance list– Ctrl+↓

Following linked components (VCL-only)– Ctrl+double-click

MiscellaneousDrag & drop RAD now works (kinda)!MPD keyboard shortcuts

– Ctrl+Tab and Shift+Ctrl+TabIDE memory consumption

– IDE command line switches –hm and -hvPreventing docking

– Hold down Ctrl– Use the environment option

Enhancing from withinImplement 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 registryAll relative to HKCU\Software\Borland\

Removing Ctrl+Alt shortcutsDelphi\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 DisassemblyBDS\3.0\Globals\ShowILDisassembly="1"

Designer Insight (WinForms)BDS\3.0\DesignerInsight\Visible="1"

The IDE

End of section

The languageIterations

Logical assignments

Logical array indices

Typed constants

Sets & cases

Accessing protected members

Accessing private members

Characters

Concise object creation

The language

Iterations - extension to for loop syntax

var I: Integer;

S: String;

...

for I := 0 to Pred(ListBox1.Items.Count) do

begin

S := ListBox1.Items[I];

MessageBox.Show(S)

end

The language

Iterations - extension to for loop syntax

var

S: String;

...

for S in ListBox1.Items do

MessageBox.Show(S)

The language

Iterations - extension to for loop syntax

var S: String;

...

for S in ListBox1.Items do

MessageBox.Show(S)

Works with arrays (inc. multi-dimensional), strings, sets, and anything that implements IEnumerable

The language

if X then

Y := True

else

Y := False

if X then

Y := False

else

Y := True

↓ ↓

Y := X Y := not X

Logical assignments

The languageLogical 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 languageTyped 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 languageTyped constantsprocedure 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 languageSets & 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 languageSets & casesprocedure 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 languageSets & casesprocedure 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 languageSets & casesprocedure 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' endend;

The languageConcise 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 endend;

The languageAccessing 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 languageAccessing 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 languageAccessing 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 languageAccessing 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 languageAccessing private membersfunction 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 space

Caption := 'Copyright '#169' 2004, Me';

The language

End of section

The RTLPlatform checking

Calling Win32 APIs

Tracking memory usage

Memory manager statistics

Memory manager debug routines

Replacing/chaining the memory manager

The RTLPlatform checking through SysUtils

– Win32Platform•VER_PLATFORM_WIN32_WINDOWS•VER_PLATFORM_WIN32_NT

– Win32MajorVersion– Win32MinorVersion– Win32BuildNumber– Win32CSDVersion

• Corrective Service Disk (Service Pack)– CheckWin32Version

The RTL

Operating System Win32Platform Win32MajorVersion Win32Minor-Version

Win32CSD-Version[1]

Windows 95 VER_PLATFORM_WIN32_WINDOWS 4 0

Windows 95 OSR2 VER_PLATFORM_WIN32_WINDOWS 4 0 'B' or 'C'

Windows 98 VER_PLATFORM_WIN32_WINDOWS 4 10

Windows 98 SE VER_PLATFORM_WIN32_WINDOWS 4 10 'A'

Windows Me VER_PLATFORM_WIN32_WINDOWS 4 90

Windows NT VER_PLATFORM_WIN32_NT <= 4 Service pack

Windows 2000 VER_PLATFORM_WIN32_NT 5 0 Service pack

Windows XP VER_PLATFORM_WIN32_NT 5 1 Service pack

Windows Server 2003 VER_PLATFORM_WIN32_NT 5 2 Service pack

Platform checking

The RTLPlatform checking through .NET FCL

– Environment.OSVersion.Platform• PlatformID.Win32Windows• PlatformID.Win32NT• PlatformID.Win32CE

– Environment.OSVersion.Version.Major– Environment.OSVersion.Version.Minor– Environment.OSVersion.Version.Build– Environment.OSVersion.Version.Revision

The RTL Calling Win32 APIs

– GetLastError– RaiseLastWin32Error– RaiseLastOSError– SysErrorMessage– Win32Check– EWin32Error– EOSError

The RTL Tracking memory usage

– AllocMemCount– AllocMemSize

Win32 Memory manager statistics– GetHeapStatus– THeapStatus

The RTLWin32 Memory manager debug routines

– GetHeapBlocks– FindObjects– Recompiling the RTL

Win32 Replacing the memory manager

– Chasing AVs

– Tracking memory

The RTL

End of section

The debuggerTracing

The CPU window

Run without debugging

Re-executing code

Debugging DLLs

Watching special values

The debuggerTracing

– Debug messages

– The Event Log

– SysInternals DebugView

– Hooking Automation (Win32)•VarDispProc• hooking named parameters

The debuggerTracing

– Reimplemented assertions (Win32)•AssertErrorProc

– Advanced breakpoints

– Evaluating functions in watches

The debuggerThe CPU window

– Navigating around• Keys• Context menus• Following addresses to code and data• Changing memory

The debuggerThe CPU window (Win32)

– Object internals

TBar Variable

TBar VMTTBar Instance

VMT Ptr

IFoo Variable

IYada Variable

IFoo MT

IYada MT

TBar.Meth1

TBar.Meth2

TBar.Meth1Code

TBar.Meth2Code

IFoo+TBar.Meth1 Stub

IFoo+TBar.Meth2 Stub

IFoo.Meth1

IFoo.Meth2

IFoo+TBar MT

IYada+TBar MT

The debuggerThe CPU window (Win32)

– Object internalsTFoo Variable

TFoo.VMeth1

TFoo.VMeth2

DMT Ptr

TFoo VMT

VMT Ptr

TFoo Instance

TFoo.VMeth1Code

TFoo.VMeth2Code

TFoo.DMeth1

TFoo.DMeth2

DMT Count

TFoo.DMeth1 id

TFoo.DMeth2 id

TFoo.DMeth1Code

TFoo.DMeth1Code

The debuggerThe CPU window (Win32)

– VMT prefix fields

– Locating an object’s class name• Follow the VMT trail•vmtClassName

– How big is a memory block?• Prefix fields• The $7FFFFFFC mask

The debuggerRe-executing code – reset EIP

Debugging DLLs

– Host application

– Remote debug symbols required to debug COM DLLs

Watching special values– TDateTime values

The debugger

End of section

WindowsThe Windows key

+e Explorer +f Find files– Ctrl++f Find computer +l Lock workstation (XP+) +m Minimize all– Shift++m Undo minimize all +d Bring desktop to front +r Run... +F1 Windows help +Break System properties +u Microsoft Narrator

WindowsTask Manager keystroke: Ctrl+Shift+Esc

Can drag from Explorer to Command prompt window and Run... dialog

Can add NotePad etc. to Send To by adding a shortcut in %USERPROFILE%\SendTo

WindowsEntering ANSI/ASCII symbols on numeric keypad:

– Alt + 4 digit number = ANSI character– Alt + 3 digit number = ASCII character

Retrieving lost windows– Alt+Space drops down the system menu– M triggers Move menu– Cursor keys move the window around– Mouse makes window snap to pointer

Accessibility options

.NETSDK Command prompt

Profiling

– CLR Profiler

– Brew your own

Debugging outside the IDE

– cordbg

– GUI Debugger

– Windbg & SOS

I’ll Be Back

3222: Microsoft .NET Framework Interop

Wednesday, 8:00 – 9:15

Right Here (Room C1/C4)

Thank You

1002

Delphi Tips & Techniques

Please fill out the speaker evaluation

You can contact me further at [email protected]