Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Grid Class - Adding Header Code Dynamically
Message
Information générale
Forum:
Visual FoxPro
Catégorie:
Classes - VCX
Divers
Thread ID:
00784946
Message ID:
00792059
Vues:
32
Thanks Edgar. I got the changes to read through your reply just yesterday and it's definately helpful. Though it may take me some time to get it implemented, but the concept is what I had dreamed about.

I had tried a similar but more direct no tables for configuration approach. I had an extra table defined in the DBC like a client would want. Then I designed a coded form which would load a browse window in change mode, though the thing I must say worked, but the text boxes didn't behave as they should and when lost focus would move the values, esp. numeric, beyond the window width.

>Mr. Nathwani,
>
>To explain this process in detail would required more than one article.
>
>The basic process is simple:
>
>A class library is just a Foxpro table with a funny extension (.vcx/.vct instead of .dbf/.dbt). If Fox can create object from information stored in a data file, then so can I, and from a much simpler column dictionary table.
>
>First, create a base grid class that contains all of the properties and methods that you are likely to use. This grid had no columns.
>
>From here you can subclass the base grid and add whatever columns you need. This is what we do for simple grids that the user cannot add columns to or remove columns from (non-customizable grids).
>
>For customizable grids, the grid is instantiated from the base grid class, and in the Init(), the .ColumnCount is zero. This is the grid's clue that it needs to add column from the column dictionary table.
>
>There are actually two such tables. The master table contains information about all columns in all grids. At run-time this table is read-only (in fact we build it into the executable so it cannot possibly be altered). The other table is the working dictionary that the grid reads from and writes to. This contains information about all of the columns that are on working grids. These columns include (1) the columns that we have designated must be on a grid (required columns) and columns the user has elected to place on the grid (optional columns). When the appliation is first run, the startup process looks to see whether a working grid dictionary table exists. If no, then it creates a working dictionary from the master dictionary assigning to each grid its required columns.
>
>If the Init() of the grid discovers that it has no column, then it calls a grid method, m_Add_Columns() to add to the grid the columns it finds are defined for the grid in the working column dictionary table.
>
>The dictionaries contain at minimum:
>
>1. The name of the grid,
>2. The name of each column
>3. A column property memo and
>4. A column methods memo.
>
>The property and method memos follow the same format as is used in the .vct methods and properties memos.
>
>We experimented with having a separate related table for the controls that are added to columns, but decided over time (and at the risk of sub-normalizing our dictionary table) that a separate table was not needed. (Has anyone else noticed that relations among tables is a lot more fragile now than it was in VFP 5.0a?)
>
>We decided that our column would never have more than two controls (other than the header). So we added additional fields to hold the name, class and class library of each of two controls and the properties and methods of each control. Now each column record holds not only the information about the column, but information about all of the controls on the column. This serves to make creating the column from code a much simpler prospect.
>
>Here is the structure of the column dictionary table:
>
>
>Structure for table:    C:\CPDEVEL\CPDM50\SYSTEM\COLDATA.DBF
>Number of data records: 4739
>Date of last update:    05/20/2003
>Memo file block size:   64
>Code Page:              1252
>Field  Field Name      Type                Width         Comment
>    1  GRIDNAME        Character              20         Name of parent grid
>    2  FIELDNAME       Character              20         Field data source
>    3  COLNAME         Character              20         Column name
>    4  COLPROPS        Memo                    4         Column properties
>    5  HDRPROPS        Memo                    4         Column methods
>    6  C1CLASS         Character              40         1st Control class
>    7  C1CLASSLIB      Character              40         1st Control class library
>    8  C1CLASSTYP      Character               3         1st Control type
>    9  C1PROPS         Memo                    4         1st Control properties
>   10  C2CLASS         Character              40         2nd Control class
>   11  C2CLASSLIB      Character              40         2nd Control class library
>   12  C2CLASSTYP      Character               3         2nd Control type
>   13  C2PROPS         Memo                    4         2nd Control properties
>   14  COLMETHODS      Memo                    4         Column methods
>   15  HDRMETHODS      Memo                    4         Header methods
>   16  C1METHODS       Memo                    4         1st Control methods
>   17  C2METHODS       Memo                    4         2nd Control methods
>   18  SYSCOLUMN       Logical                 1         True if required on the grid
>** Total **                                  260
>
>
>The column class must be created in code. Even though VFP 8.0 now allows you to specify the class from which to create a column object, it still does not allow a column to be created visually. This is a fine example of too little (still no visual columns), to late (I've had this technology for five years, now), so the new VFP 8.0 feature is no temptation for me to change the way I am doing things now. However, if I were starting new today, I would give it a serious look.
>
>Creating a column class in code is a little tricky. What we do to reduce the problems is to create a base column object, then add any special properties after the column is created.
>
>Here is the code to create a BaseColumn and BaseHeader class. A lot of this refers to properties and method of our base grid class, so will probably mean nothing to you. But for what it's worth...
>
>********************************************************************************
>FUNCTION DEFINEBASECOLUMNCLASSES()
>********************************************************************************
>*	
>*   OVERVIEW:   Creates the base column and base header classes for a code grid.
>*
>*   CALLED BY:   BaseGrid.m_AddColumns()
>*
>DEFINE CLASS BaseHeader AS HEADER
>
>   Alignment   = 2         && Middle Center
>   Backcolor   = 14741744   && RGB( 240,240,224)
>   FontName    = "Verdana"
>   FontSize    = 8
>   Visible     = .T.
>   WordWrap    = .T.
>
>   PROCEDURE Init
>
>      LOCAL lcFieldSource
>      WITH this
>
>         lcFieldSource = LOWER( ALLTRIM( .parent.FieldSource ) )
>         IF DBFSELECT( 'sdtmeta', .T. )
>
>            LOCATE FOR LOWER( ALLTRIM( objectname ) ) == lcFieldSource .AND. ALLTRIM( rectype ) $ 'FU'
>            IF FOUND()
>
>               .Caption = EVALUATE( fcaption )
>
>            ENDIF
>
>         ENDIF
>
>      ENDWITH
>
>   ENDPROC
>
>   PROCEDURE RightClick
>
>   *   BaseHeader.RightClick()
>   *
>   *   OVERVIEW:   Calls the BaseGrid function m_Header_RightClick_Menu()
>   *               to display a shortcut menu for the header.
>   WITH this
>
>      *   Before calling any grid method, ensure it exists.
>      IF PEMSTATUS( .parent.parent, "m_Header_RightClick_Menu", 5 )
>
>         *   Pass a reference to the column as a paramter to
>         *   m_Header_RightClick_Menu()
>         .parent.parent.m_Header_RightClick_Menu( .parent )
>
>      ENDIF
>
>   ENDWITH
>
>   RETURN
>
>   ENDPROC
>
>ENDDEFINE
>
>DEFINE CLASS BaseColumn AS Column
>
>   Backcolor   = 14741744   && RGB( 240,240,224)
>
>   *   Stores the code that created this column as a class.  The assignment
>   *   of the actual text string is made in m_Add_Columns().  This is only
>   *   for debugging.
>   ClassDefinition   = ""
>
>   *   Add the ColumnIndex property.  This property is an integer pointer to
>   *   the column in the Columns[] collection. (Not currently used JME 09/23/02)
>   ColumnIndex      = 0
>
>   *   Specifies whether the current control in the column contains a
>   *   non-empty value.  If a control is "required", then it must contain a
>   *   a value that is non-empty.  Whether the value is valid is tested by the control
>   *   itself in its own Valid() method.  The grid only tests for a non-empty value
>   *   if Column.Complete is true.  See: m_Required_Entries_Completed().
>   Complete         = .F.
>
>   *   Add the property to the column, but it does not apply if the column is
>   *   ReadOnly.  JME 04/22/03
>   ControlEnabled   = .T.
>
>   *   Specifies the original table.field from which the view controlsource for this
>   *   column was constructed.
>   FieldSource      = ''
>
>   FontName         = "Verdana"
>   FontSize         = 8
>
>   *   Specifies the column's position in the freeze panel.  If zero, the column
>   *   is not in the freeze panel
>   FreezeOrder      = 0
>
>   *   Specifies whether the column contains the control with focus.  Set by each
>   *   control as it gains and loses focus.  Also set in m_Control_When().  The
>   *   form property, "ControlWithFocus" contains the name of the control with
>   *   current focus.  Used in setting dynamic colors.  See: m_Set_DynamicColor_Expession()
>   HasFocus         = .F.
>
>   *   Holds the full header caption in the event the caption is truncated
>   *   for display by m_Column_Resize()
>   HeaderCaption    = ""
>
>   *   Holds the number of lines required to display the header caption.
>   HeaderLines      = 1
>
>   *   Specifies whether the column is readonly per security settings.  This property
>   *   will be set to .T. if a user is locked out of this column, then the column's
>   *   readonly property will also be set to TRUE.  In the event of an attempt to change
>   *   the column's readonly property, a readonly_assign method will fire, which will
>   *   check ReadOnlyBySecurity, and stop the changing of the value if it's set to .T.
>   ReadOnlyBySecurity = .F.
>
>   *   If a non-blank entry is required in a column, the Column.Required property
>   *   will be true.  Otherwise it will be false.  Used in m_Required_Entries_Completed()
>   *   to determine whether a non-blank value is required in a row before moving to
>   *   a new row.
>   Required         = .F.
>
>   Visible         = .T.
>
>   PROCEDURE Init
>
>   *   BaseColumns.Init()
>   *
>   *   OVERVIEW:   Remove the existing header and edit controls from the column
>   *               in preparation for adding a new BaseHeader and edit controls
>   *               in DEFINECOLUMN().
>   *
>   LOCAL lnI
>
>   WITH this
>
>      FOR lnI = .ControlCount TO 1 STEP -1
>         .RemoveObject( .Controls[ lnI ].Name )
>      NEXT
>
>      .ColumnIndex = .parent.ColumnCount
>      .Visible     = .T.
>
>   ENDWITH
>
>   RETURN
>
>   ENDPROC
>
>   PROCEDURE Moved
>
>   *   BaseColumn.Moved()
>   *
>   *   OVERVIEW:   When this column is moved.  Call the BaseGrid
>   *               function m_Column_Moved() to respond to the
>   *               event.
>   *
>   WITH this
>
>      *   Before calling any grid method, ensure it exists.
>      IF PEMSTATUS( .parent, "m_Column_Moved", 5 )
>         .parent.m_Column_Moved( .Name )
>      ENDIF
>
>   ENDWITH
>
>   RETURN
>
>   ENDPROC
>
>   PROCEDURE ReadOnly_Assign()
>
>   *   BaseColumn.ReadOnlyBySecurity()
>   *
>   *   OVERVIEW:   Prevents a column set ReadOnly by security from being
>   *               reenabled.
>   *
>   LPARAMETERS tlReadOnly
>
>   WITH this
>
>      IF PEMSTATUS( this, "ReadOnlyBySecurity", 5 ) .AND. .ReadOnlyBySecurity
>         .ReadOnly = .T.
>      ELSE
>         .ReadOnly = tlReadOnly
>      ENDIF
>
>   ENDWITH
>
>   RETURN
>
>   ENDPROC
>
>   PROCEDURE Resize
>
>   *   BaseColumn.Resize()
>   *
>   *   OVERVIEW:   When this column is resized.  Call the BaseGrid
>   *               function m_Column_Resize() to respond to the
>   *               event.
>   *
>   WITH this
>
>      *   Before calling any grid method, ensure it exists.
>      IF PEMSTATUS( .parent, "m_Column_Resize", 5 )
>
>         *   Pass a reference to the Header object to the method.
>         *   The header is always .Controls[1]
>         .parent.m_Column_Resize( .Controls[ 1 ] )
>
>      ENDIF
>
>   ENDWITH
>
>   RETURN
>
>   ENDPROC
>
>ENDDEFINE
>
>There is obviously a little more to this. But this should get you started.
>
>Regards,
Regards
Bhavbhuti
___________________________________________
Softwares for Indian Businesses at:
http://venussoftop.tripod.com
___________________________________________
venussoftop@gmail.com
___________________________________________
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform