Saturday, June 10, 2017

Breaking down Grid's Column object

A foxite member has sought assistance on how to make an active cell of a specific column change color, as additional visual highlight, upon receiving focus.  Of course it means AllowCellSelection is .T. to allow that specific cell focus.  So I showed him how via a sample code whereby I manipulated both GotFocus() and LostFocus() of the text object for that column to change the backcolor when it receives focus and to return it back to white on LostFocus.

I said new findings because a fellow respected member of Foxite, Tony Vignone, has mentioned on a comment under mine  that lostfocus is not needed on my sample codes as it achieves that switching of backcolor even without it (lostfocus codes I have shown) though he is not clear as to the whys.  So he asked me if I have an idea as to the whys.

And yes, having manipulated objects of VFP myself to create a single new object in form (control classes like xBox, PopCalc, DTPickerX, EditX, etc.) for my ssUltimate library, I do immediately got a "new perspective" of how a grid's column is composed of.  And this is what I am sharing here now.  How really is a column of a grid composed of?

Column's Composition

Originally I think of a column consisting of 3 objects.  A container, a header and a textbox (by default). His comments helped lift up the fog in my eyes which resulted to this new perspective of a grid's column's composition now.



Here is what I think now how a grid column is composed of:

  1. Container also known as the column
  2. Commandbutton (for header)
  3. Textbox (to show the values on top, what is merely shown on allowcellselection = .f.).  We will term this as upper textbox.
  4. Another texbox that works as the activecell and CurrentControl, by default, when allowcellselection is .t., we will term this as lower textbox.


What is new above?  That upper textbox has never occured to me and most probably to most of you as VFP do not show it on PEM.  But that is not surprising as VFP's grid and other objects such as pageframes, listbox, combobox, etc.; are nothing but just skilfully manipulated combined objects turned into one; just like a control class.

So like I said, a column actually consists of that extra upper textbox hidden in PEM.  We will put this to a test in a short while here.

Having said that about the upper textbox, then all we need to achieve changing backcolor of an active cell of a grid is to simply "change the backcolor of what is seen as text1 of a column", either by PEM or by code in its init event.  Try it.

Going back to Tony's question of how the grid was able to restore back the cell to default white when it looses focus without any codes on its lostfocus event, that is because that text1 or what we termed above as lower textbox (now colored diffirently) is the one used by grid (talking about default objects of a column) for its active cell.  While on the rest of inactive cells, grid is switching to that upper textbox hidden in PEM (which has white color by default).

To prove this theory further is simple.  All you need to do is set Sparse propery of that column to .F. and presto, you will see that the whole column will now turn to that lower textbox' backcolor.  Because what Sparse = .F. does is it  turns the upper textbox  invisible.

Again, activecell uses lower textbox, inactive cells uses upper textbox object hidden in PEM.  Unless you set Sparse to .F. whereby VFP will now disregard the upper textbox (rendering it invisible) and will use instead the underlying currentcontrol of a column.

Here is a sample code:

loTest = Createobject("Sample")
loTest.Show(1)

Define Class Sample As Form
      AutoCenter = .T.
      Width = 300
      Height = 340

      Add Object command1 As CommandButton With ;
            Caption = 'Turn Sparse OFF', Top = 5, Left = 10,;
             Height =30, Width = 120

      Add Object grid1 As Grid With ;
            Left = 10, Top = 50, Height = 280, Width = 270, ;
            DeleteMark=.F., RecordMark = .F.

      Procedure Load
            Rand(-1)
            Create Cursor junk (fld1 i, fld2 i, fld3 i, fld4 i)
            For lnloop = 1 To 40
                  Insert Into junk Values (1+100* Rand(),1+400* Rand(),1+60* Rand(),1+150* Rand())
            Next
            Go Top
      Endproc

      Procedure grid1.Init
            With This
                  .RecordSourceType =1
                  .RecordSource = 'junk'
                  For Each loColumn In .Columns
                        loColumn.RemoveObject('Text1')
                        loColumn.AddObject('Text1','MyText')
                        loColumn.Text1.Visible = .T.
                  Next
            Endwith
      Endproc

      Procedure command1.Click
            Local lnColumn, llSparse
            Thisform.grid1.SetFocus()
            lnColumn = Thisform.grid1.ActiveColumn
            llSparse = Thisform.grid1.Columns(m.lnColumn).Sparse
            Thisform.grid1.Columns(m.lnColumn).Sparse = !m.llSparse
            Thisform.command1.Caption = 'Turn Sparse '+Iif(m.llSparse,'ON','OFF')
      Endproc
Enddefine


Define Class myText As TextBox
      * We will change these properties for lower textbox
      BorderStyle = 0
      BackColor = Rgb(0,255,255)
      FontBold = .T.
      FontSize = 12

      Procedure GotFocus
            Thisform.command1.Caption = 'Turn Sparse '+Iif(This.Parent.Sparse,'OFF','ON')
      Endproc
Enddefine






No comments:

Post a Comment