DOC

THE DELPHI COMPONENT WRITING FAQ

By Danielle Elliott,2014-03-02 05:17
9 views 0
THE DELPHI COMPONENT WRITING FAQ

The Delphi Component Writing FAQ

    发信人: I007 (阿健), 信区: Visual

     : The Delphi Component Writing FAQ

    发信站: BBS 水木清华站 (Sat Nov 29 08:29:26 1997)

    非常值得一看:

    The Delphi Component Writing FAQ

    Edited By: John M. Miano

    miano@worldnet.att.net

    Version: 9

    Last Updated: 21-Jul-1997

    Changes:

    caught up on all the suggestions everyone has sent me in thI finally

    e

    past few months.

    The original version of this document is now at

    http://home.att.net/~miano

    ------------------------------------------------------------------------

    Table of Contents

    Section 1 - Introduction

    1.1. What is the purpose of this document?

    Section 2 - IDE

    2.1. How can I locate problems that result when my component is used in the IDE?

    2.2. How do I view assembly langugage the Delphi Generates? 2.3. I can create my control at run time but it crashes at design time. What is

     wrong?

    2.4. How can I create a component that cannot be dropped on a form? 2.5. What is an easy way to backtrack through source code? 2.6. How can I add to the popup menu that is displayed when the right

     mouse butt

    on is clicked on my component?

    2.7. How come I get I/O 103 in design mode?

    2.8. Why are my property values not getting saved when I use a component editor?

    Section 3 - Using other components within a component

    3.1. How can I add a scroll bar component to my component and have it

     work at in

     design mode?

    3.2. How do I create a Windows '95-style scroll bar?

    Section 4 - Bound Controls

    4.1. Where is the documentation for the TDataLink class? 4.2. How can I tell the number of the record I am on in a data set?

Section 5 - VCL

    5.1. How can I step through the VCL source while debugging? 5.2. My component references other components. How can I tell if a component my

     component references had been deleted?

    5.3. What are component messages?

    5.4. My control has focus but it is not getting keystroke messages. What's happ

    ening?

    Section 6 - Other Sources of Information

     there any books one how to write Delphi components? 6.1. Are

    6.2. Are there any good web sites with information on how to write components?

    Section 7 - Persistent Objects

    7.1. How can I save a complex object containing child objects to the .DFM file.

    7.2. How can I tell if my constructor is being called for an object being loaded

     from a stream?

    7.3. How can I tell if my component's properties are being saved correctly to th

    e form file?

    Section 8. Tools for Delphi

    8.1. Is there YACC and LEX for Delphi?

    8.2. How can I write code to display JPEG files?

    Section 9. Basic Programming Techniques

    9.1. How do I create a dynamic array of objects?

    9.2. Where is Wincrt in Delphi 2.0?

    9.3. What should the base class be for my component?

    9.4. What is the difference between the Free and Destroy methods ? Section 10. Advanced Programming Techniques

    10.1. Is there a Delphi equivalent to C++'s I/O stream classes? 10.2. How can I get the text equivalent for an enumerated type? Section 11. Component Virtual Methods

    11.1. How can I find out when my component has had its window handle created?

    11.2. How can I tell when all the components on my form have been loaded?

    11.3. Where is the best place to draw my control?

    Section 12. Windows API Functions

    12.1. I am trying to scroll the contents of my control but I get an ugly flicker

     effect. How can I eliminate this?

    12.2. How can I restart windows?

    12.3. How can I batch updates to when changing the appearance of my control?

    Section 13. Control Borders

    13.1. How come my control does not have a 3D border even when I have CTL3D set t

    o True?

    13.2 How do I implement a BorderStyle property?

    Section 14. Control Styles

    14.1. How do I stop my control from flickering when it gets repainted? Section 15. Windows Messages

     come my control does not get keystroke messages for the arr15.1. How

    ow keys?

    15.2. Is there an equivalent of Visual Basic's "DoEvents" statement? ------------------------------------------------------------------------

    Section 1 - Introductions

    1.1. What is the purpose of this document?

    The purpose of this document is to answer common or undocumented questions relat

    ed to writing Delphi components. After spending a ridiculous amount of time try

    ing to decipher the TDataLink component it occured to me that there ought to be

    some way of recording and sharing solutions to the problems encountered while wr

    iting controls. All information is provided as is. There are no guarantee as to

     its correctness.

    If you have any questions you would like to be answered or have any contribution

    s you think would be suitable for inclusion please send them to the editor. Rep

    orts of errors or omissions are also welcome.

    In addition to including more answers and questions I am trying to expand in two

     more areas:

    1. Tools that are of interest to advanced developers: These might not

     be directl

    y related to component writing but they will have some integration with Delphi.

    2. References to publications: Since there is not enough room in an FAQ for ext

    ensive examples as I come across examples of how to do things in print I will in

    clude them here. This will not be an academic style bibliography I only indend

    to include references to the best or most accessible document or publication.

    If you have an suggestions for any of these they are also welcome. Keep in mind

     that I cannot include an item if I cannot verify it.

    ------------------------------------------------------------------------

    Section 2 - IDE Problems

     can I locate problems that result when my component is used 2.1. How

    in the IDE?

    The only solution to locating problems I have found is to: 1. In Delphi go to Tools/Options then go to the "Library" page. Check the "Compile With Debug Info" box.

    2. Rebuild the library.

    3. Run Delphi from within Turbo Debugger.

    4. Use "File/Change Dir" to include the source directories. If you get a GPF you can use view the stack and get some idea where the problem

    is occuring.

    Another suggestion from Roger Hernandez

    One way of tracing what is going on inside a component is the following:

    {$IFDEF DebugOutput}

     OutputDebugString ('Some debug string goes here.');

    {$ENDIF}

    I have used this technique to trace problems dealing with component creation, destruction, and property loading while running in the IDE. It can also be used to debug problems with component property editors running in the IDE. One can also use a more complicated system where

     a

    debug function is called that can optionally take a severity level, and

    only print messages over a given level. What I ended up doing was encapsulating the debug message functions in a unit.

    2.2. How do I view assembly langugage the Delphi Generates? From Glen Boyd

    Run the REGEDIT program and go to "HKEY_CURRENT_USER\Software\Borland\Delphi\2.0

    \Debugging" and add a string value called EnableCPU and set its string value to

    1. This adds the CPU window to the view menu. The CPU window is active at run

time for stepping through and stuff like that.

    2.3. I can create my control at run time but it crashes at design time. What is

     wrong?

    1. Your component must descend from TComponent

    2. Your constructory and destructor declarations must look like: Constructor Create (AOwner : TComponent) ; Override ;

    Destructor Destroy ; Override ;

    3 All fields that are published must be either ordinal, single, double, extende

     currency, string, small set, method pointer or a class. Thed, comp,

     Delphi com

    piler does not produce an error if you use any other type in a published section

    . However you will get an GPF if you try to use a control that contains a publis

    hed declaration of any other type.

    The following declarations will cause serious problems if you attempt

     to use TMy

    Component in design mode.

    Type

     TComplex = Record

     RealPart : Double ;

     ComplexPart : Double ;

     End ;

    class TMyComponent = Class (TComponent)

     Private

     F1 : TComplex ;

     Published

     Property P1 : TComplex Read F1 Write F1 ;

     End ;

    2.4. How can I create a component that cannot be dropped on a form? From Ray Lischner

    If you don't want the user to be able to drop the component on a form

     then

    use then RegisterNoIcon and RegisterClass procedures.

    2.5. What is an easy way to backtrack through source code? From Ray Konopka

    When viewing the source for the VCL units, it's definitely a good idea to

    become comfortable with bookmarks in the editor. That is, Ctrl+Shift+N,

    when N is a number 0-

    9, to set a bookmark. Jump to a bookmark using Ctrl+N.

    2.6. How can I add to the popup menu that is displayed when the right

     mouse butt

    on is clicked on my component?

    You do this by creating a Component Editor. One would think that a component ed

    itor would be something that is called from the popup menu but it actually contr

    ols what appears in the menu or rather the items that your component can add to

    the menu.

     to follow are: The steps

    1. Create a class that derives from TComponentEditor

    2. In your class override the method GetVerbCount, GetVerb, and ExecuteVerb.

     your component's Register procedure add a call to RegisterCompo3. In

    nentEditor

    that associates your component editor with your component. This topic is described well in the book "Developing Delphi Components".

    2.7. How come I get I/O 103 in design mode?

    You probably have WriteLn statements in your code.

    2.8. Why are my property values not getting saved when I use a component editor?

    I have found that when using a component editor that a component's properties wi

    ll not be saved. The property appears to be correct in design mode but when you

    run or save the property is set to a different value.

    It appears that a property editor needs to call

     Designer.Modified

    to let Delphi know that you have changed a property value. ------------------------------------------------------------------------

    Section 3 - Using other components within a component

    3.1. How can I add a scroll bar component to my component and have it

     work at in

     design mode?

    You need to define your own scroll bar class that intercepts the CM_DESIGNHITTES

    T message.

    TMyScrollBar = class (TScrollBar)

     Procedure CMDesignHitTest (var Message : TCMDesignHitTest) ; Message CM_DE

    SIGNHITTEST ;

     End ;

    Procedure TMyScrollBar.CMDesignHitTest (var Message : TCMDesignHitTest) ;

     Begin

     Message.Result := 1 ;

     End ;

    When your component creates one of these scroll bars it needs to use TMyScrollBar.Create (Nil)

    rather than

    TMyScrollBar.Create (Self)

     bar will display sizing handles when it is clickotherwise the scroll

    . This me

    ans you need to be sure to explicitly free the scroll bar in your component's de

    structor.

    3.2 How do I create a Windows '95-style scroll bar? You need to set the page size for the scroll bar. The following code sequence

    illustrates this:

    Procedure SetPageSize (ScrollBar : TScrollBar ; PageSize : Integer) ;

     Var

     ScrollInfo : TScrollInfo ;

     Begin

     ScrollInfo.cbSize := Sizeof (ScrollInfo) ;

     ScrollInfo.fMask := SIF_PAGE ;

     ScrollInfo.nPage := PageSize ;

     SetScrollInfo (ScrollBar.Handle, SB_CTL, ScrollInfo, True) ;

     End ;

    To retrieve the page size use:

    Function GetpageSize (ScrollBar : TScrollBar) ;

     Var

     ScrollInfo : TScrollInfo ;

     Begin

     If HandleAllocated Then

     Begin

     ScrollInfo.cbSize := Sizeof (ScrollInfo) ;

     ScrollInfo.fMask := SIF_PAGE ;

     GetScrollInfo (ScrollBar.Handle, SB_CTL, ScrollInfo) ;

     Result := ScrollInfo.nPage ;

     End ;

    ------------------------------------------------------------------------

    Section 4 - Bound Controls

    4.1. Where is the documentation for the TDataLink class?

    The C++Builder documentation contains a description of the TDataLink class. It i

    s not in any Delphi documentation so far. For those of you who do not

     have C++Bu

    ilder here is the description that has been in this document for a long time:

    Properties:

    ===========

    Property: Active : Boolean (Read Only)

    ----------------------------------------

     the data link is connected to an active datasource. Returns true when

    The ActiveChanged method is called to give notification when the state changes.

    Property: ActiveRecord: (Read/Write)

    --------------------------------------

    This sets or returns the current record within the TDatalink's buffer

     window. V

    alid values are

    0..BufferCount -

     1. There appear to be no range checks so assigning values outs ide this range produces unpredictable results.

    Property: BufferCount: (Read/Write)

    -------------------------------------

    The TDataLink maintains a window of records into the dataset This property is t

    he size of this window and determines the maximum number of row that can be view

     simultaneously. For most controls you would use a BufferCount of one. For con

    trols such as a data grid this value is the number of visible rows. Property: DataSet: TDataSet (Read)

    ------------------------------------

    The dataset the TDataLink is attached to. This is a shortcut to DataSource.Data

    Set.

    Property: DataSource: TDataSource (Read/Write)

    ------------------------------------------------

    Sets or returns data source control the TDataLink is attached to. Property: DataSourceFixed: Boolean (Read/WRite)

    -------------------------------------------------

    This property is used to prevent the data source for the TDataLink from being ch

    anged. If this property is set to Trye then assigning a value to the

     DataSource

     property will result in an exception.

    Property: Editing: Boolean (Read Only) ----------------------------------------

    Returns true if the datalink is in edit mode. Property: ReadOnly: Boolean (read/Write) ------------------------------------------

    This property determines if the TDataLink is read only. It does not

    appear to a

    ffect the attached datalink

    or dataset. If this property is set to True the datalink will not go

     into edit

    mode.

    Property: RecordCount: Integer (Read) ---------------------------------------

     the approximate number of records in the attacheThe property returns

    d dataset.

    Methods:

    ========

    function Edit: Boolean;

    -----------------------

    Puts the TDatalink's attached dataset into edit mode. Return Value:

     True => Success

     False => Failure

    procedure UpdateRecord;

    -----------------------

    It appears that this is a function that is intended to be called by o

    ther parts

    of the data base interface and should not be called directly. All it

     does is se

    t a flag and call UpdateData (described below). Virtual Methods

    ===============

    The mechanism for having the TDataLink object communicate with a comp

    onent is to

     override these procedures.

    procedure ActiveChanged

    ------------------------

    This procedure is called whenever the datasource the TDataLink is att

    ached to be

    comes active or inactive. Use the Active property to determine wheth

    er or not t

    he link is active.

    procedure CheckBrowseMode

-------------------------

    This method appears to get called before any changes take place to the database.

    procedure DataSetChanged;

    -------------------------

    This procedure gets called when the following events occur:

     o Moving to the start of the dataset

     o Moving to the end of the dataset

     o Inserting or Appending to the dataset

     o Deleting a record from the dataset

     Canceling the editing of a record o

     o Updating a record

    The non-overridden action for this procedure is to call

     RecordChanged (Nil)

    procedure DataSetScrolled(Distance: Integer)

    --------------------------------------------

    This procedure is called whenever the current record in the dataset changes. Th

    e Distance parameter tells how far the buffer window into the dataset

     was scroll

    ed (This seems to always be in the range -1, 0, 1). Use the ActiveRecord to determine which record within the buffer window is the c

    urrent one.

    It is not possible to force a scroll of the buffer window. procedure FocusControl(Field: TFieldRef)

    ----------------------------------------

    This appears to get called as a result of Field.FocusControl. procedure EditingChanged

    -------------------------

    This procedure is called when the editing state of the TDataLink changes. Use t

    he Editing property to determine if the TDataLink is in edit mode or not.

    procedure LayoutChanged

    -----------------------

    This procedure is called when the layout of the attached dataset changes (e.g. c

    olumn added).

    procedure RecordChanged(Field: TField)

    --------------------------------------

    This procedure gets called when:

     o The current record is edited

     o The record's text has changed

Report this document

For any questions or suggestions please email
cust-service@docsford.com