I have given Writing Help Files its own page.
Sub-Directories
Help | This is for the Help files |
TestCases | These are to regression test your work. They should cover every property, method and event. |
Scratch | This is for files that I don't necessarily want to keep |
Backups | I like to keep periodic backups (snapshots) of my code ... Just in case. |
Testing
After you have registered the component, you can place it on your form by selecting it from the Component Palette. At this point, the published properties and procedures (events) should appear in the property editor (Object Inspector).
You can still edit the component's code and place breakpoints. However, the design time attributes won't change until you explicitly save the component source and re-compile the package.
In order to re-compile a package, first "Open" it - from the menu, select
File / Open... / [the appropriate package - *.dpk] or File / Reopen... /Then click the Compile button.
Resources
See Resources.html for a discussion of various resource viewers and editors.
In general, you should plan for your components to contain one *.res file (for run time mouse cursors and the like) and one *.dcr file (for the design time toolbar bitmaps).
For *.res files, Be sure to place the following in the interface section of the unit (*.pas file) that defines the control - I place mine just before the implementation section. (It should also work in the implementation section.)
{$R SomeName.res}
If used, be sure to place the *.dcr file in the same directory as the *.pas file with the same base name. When properly installed, the *.dcr file will have its own line in the package dialog box. If it is missing (normally because it did not exist when the unit was originally added), simply add the associated *.pas file again (which automatically includes the *.dcr file) and press compile.
Be careful, the term "icon" has 2 completely different meanings
Components Which Need a Windows Handle
As discussed below, this causes a number of problems. Basically,
Design Time Icons (Toolbar Buttons)
{$R *.res}The project's icon (the icon shown in Windows Explorer and in the project's title bar) is saved as MAINICON, a 32x32 16-color icon.
Component icons (displayed in the tool palette) are 25x25 bitmaps with the same name as the class. These MUST NOT be placed in the same file as the project's icon. One convention is to use the same name as the unit that defines the component. If you use an *.res (resource) file, then the bitmaps will be compiled into your *.exe files. However, if you use an *.dcr (dynamic component resource) file, then the bitmaps will be used for the palette but not compiled into *.exe files.
To make this work, place the *.dcr file in the same directory as the *.pas file with the same base name. The *.pas file must not use a Resource statement to include the *.dcr file
{$R mcINI_File.dcr} // Don't do this, if present, the resources // will be compiled into the *.exe filesInstead, when the *.pas file is added to the package (*.dpk file), the *.dcr file will be automatically included and will have its own line in the package dialog box. If it is missing (normally because it did not exist when the unit was originally added), simply add the associated *.pas file again and press compile.
In general, you should plan for your components to contain one *.res file (for run time mouse cursors and the like) and one *.dcr file (for the design time toolbar bitmaps). Resource files can be created and edited via
Tools / Image Editor(The Delphi help says that the bitmaps should be 24x24, "Delphi 4 in 21 Days" says 25x25. Larger and smaller sizes seem to also work. Use your judgement. For more information, search the Delphi 5 help for palette bitmaps.)
Delphi allows a form fragment (called a frame) to be defined so that a common component configuration and code is easier to reuse. These are added to the toolbar by displaying the frame (select File Open...), right clicking it, and selecting Add To Palette. The Palette Icon can be set to any 24x24 bitmap (*.bmp file). It will not allow a 25x25 bitmap to be added.
The lower-left pixel of the bitmap defines the transparent color - every occurrence of that color is automatically replaced with the color of the toolbar background.
See this for additional information on Resource files.
Warning: You must NOT, for any reason, delete any icons in your component's *.res files. If you do, there is no way to control which icon is associated with ANY application that uses your component. If you accidentally add an icon to the *.res file and then "delete" it, the Image Editor actually only hides it (it deletes the pointer but leaves the icon) and you're screwed. To fix this, use the Resource Hacker (or a similar tool) to actually delete the icon.
I suspect that you will have the same problem using cursors since the implementation is similar to icons. Bitmaps are handled differently and should not cause a problem.
Components Based on TComponent
Components Based on TCustomControl
In addition, when you add the control to the form, the Height and Width are set to zero. You need to set these to non-zero values in the constructor. If these are not changed in the constructor, then the Paint method will not be called. You will also not be able to use the mouse to select the control on the form. Even blocking an area won't get it. You will have to use the Object Inspector to select your invisible component.
In order to display the control only at design time, simply set the Visible (public, not published) property to false. This property is ignored at design time ... and the Paint method won't be called at run time.
public { Public declarations } constructor Create(AOwner : TComponent); override; procedure Paint; override; const iHeight = 25+6; // The icons are 25x25 iWidth = 25+6; // This provides a border constructor TxxName.Create(AOwner : TComponent); begin inherited; Width :=iWidth; // Show this at design time Height:=iHeight; Visible := false; // Do not show this at run time end; procedure TxxName.Paint; var BitMap1 : TBitMap; begin inherited; // This actually does nothing Width :=(iWidth); // This keeps the user from resizing Height :=(iHeight); // the icon BitMap1 := TBitMap.Create; try BitMap1.LoadFromResourceName(HInstance,'TxxName'); BitMap1.Transparent := true; inherited Canvas.Draw(3,3,BitMap1); finally BitMap1.Free; end; end;
More
The changes took effect immediately for run time, but had no effect at design time. Yes, I had Package / Options / Rebuild as Needed selected. So I spun my wheels for 2 days until I discovered that an explicit package re-build was required to change the design time functions.
Talk about no documentation.
Another feature is
BitMap1.Transparent := true;I was lucky to stumble onto that one.
Graphics
with Canvas do // Draw a diagonal line begin MoveTo(0, 0); LineTo(width, height); end;
Freeing Components
constructor Txx.Create(AOwner: TComponent); begin inherited Create(AOwner); FOpenDialog := TOpenDialog.Create(self); FSaveDialog := TSaveDialog.Create(AOwner); end; // Txx.Create destructor Txx.Destroy; begin FSaveDialog.Free; // This fails with Exception EAccessViolation // because self is not the owner FOpenDialog.Free; // This works because the Owner is self inherited Destroy; end;This is based on experience - I was not able to find any documentation to support this behavior.
Referencing Another Component
For code details, see Actions that Reference Components.
FEdit:= TEdit.create(self); FEdit.Visible := True; // Default value FEdit.Enabled := True; // Default value FEdit.Parent := Self; // without this, the control will not be displayed
TWinControl.SetBounds
At run-time, SetBounds is NOT called
Width := value; // This generates a call to SetBounds Height := value; // This generates a call to SetBounds
LockWindowUpdate
LockWindowUpdate(Memo1.Handle); // Stop updates for a while // add lines to the memo here LockWindowUpdate(0); // This releases the lock and displays the changes