Modifying FF generated code

Started by Richard Kelly, April 13, 2010, 01:43:02 AM

Previous topic - Next topic

Richard Kelly

What are the implications of modifying a form's formname_show() function? I want to change the byval UserData as long to byref myarray() as string.

Richard Kelly

I just studied the FF auto generated code and I'll just have to figure out the code to pass in an array.

Richard Kelly

There must a better way. I have a form that is called by many other forms. In the forms create function is where I setup everything. "Everything" is usually contained in some array in another function. Being a relative newly minted PB user, I just couldn't figure out how to pass that original array and know it's size. My kludge worked out like this:

Build a single pointer array to pass in...


Function BuildFormData (ByRef arAny() As String, _
                        ByRef arFormData() As Long) As Long
                       
' Take arAny array and build an array of pointers in arFormData with arFormData(0) containing the size of the array

Local nSize       As Long
Local nIndex      As Long

   nSize = ArrayAttr (arAny(), 4)
   
   If nSize > 0 Then
   
      ReDim arFormData (0 To nSize)
     
      arFormData (0) = nSize
     
      For nIndex = 0 To nSize - 1
     
         arFormData (nIndex + 1) = VarPtr(arAny (nIndex))
         
      Next nIndex
   
   End If

End Function


Showing the form:


FromName_Show (hWnd, %TRUE, ByVal VarPtr(arForm(0)))


Then in the forms create function:


Dim arForm()           As String Ptr
Local nSize                As Long

   ReDim arForm (0 To 0) At UserData
   
   nSize = arForm (0)


Now i can get at the various strings with @arForm() syntax and nSize tells me the array size.

It works and just doens't feel optimal.

Paul Squires

That's a tough question. Kind of need to be able to pass two longs/dwords to the form CREATE rather than just one in order to make it work easier. Looks like your approach is about as 'clean' as it could be. Other than using global variables, global classes, or SetProp/GetProp to store the array size/location, I think that your approach is workable.
Paul Squires
PlanetSquires Software

Mark Strickland

There is some danger in modifying a FF function to work properly future releases of FF.  If something changes inside of FF you will be faced with a maintenance issue for this modified version.  If it is too many months or years down the road you won't remember what you did and you may create lots of extra work.  Even worse you may create hidden problems that compile without error but don't work as expected.

Lots of people complain about globals but I find them easy and safe to deal with.  If you ALWAYS put your globals in the same place in the project they will not get lost.  If you use a naming convention that identifies them like   gMyArray    you can identify them when you see them (globals always start with a lower case g).

Another alternative could be a table of parameters.  If you have many many different parameters to pass to lots of different functions you can put them in a global "table of parameters" and pass the array index through the single global allowed by FF.

After many decades in IT of managing software projects, packaged software, and programming tools I avoid making core changes to everything.  It will compromise your code and your ability to maintain things in the future.

Information Technology Architecture is a discipline within itself these days for bigger IT development shops.  These architects make sure the design of systems and code can survive future changes in software and infrastructure as well as designs that perform well.

One persons opinion.
Mark Strickland, CISSP, CEH
www.SimplyBASICsoftware.com

Paul Squires

Likewise, I use globals all the time. They are part of th elanguage and as long as you name them right then you should have no problem using them correctly. It is like anything else in programming - you need to take precautions to ensure that you use the functionality correctly. When I see people like MCM spouting on and on about no globals is a must it just makes me laugh. It is no different than using GOTO incorrectly.

I try to keep all of my globals in one global TYPE struture (declare it something like gApp or similar). Granted, it is too bad that PB never implement dynamic stings and dynamic arrays as part of a TYPE (I stopped voicing my opinions on that matter). These days, it is just as easy to use a global CLASS that holds all of your global numeric, string, array, etc. data.
Paul Squires
PlanetSquires Software

Patrice Terrier

Have a look on the post here, it is very handy to replace the use of GLOBALS and to store/retrieve static values.

...

Richard Kelly

Thank all of you for your feedback. I do use globals and have them all together in FF_AppStart and they work. I have an entire group of "common" forms that I wanted to be "self sufficient" and not rely on globals. In other words, I call the function that starts some common process and then all the forms that may be invoked within that process are all self-contained without reference to anything outside what is passed around in UserData and returned via FF_FormClose. I hold information on forms with hidden labels and I can even store addresses on the form that way. In the app I'm working on, there is an entire section dealing with persons and all the related functions that may be used in their maintenance. If I isolate the pertinent associated functions (i.e. like multiple addresses, phone numbers, contacts, etc) then I can allow my users to work on more than one person at a time and easily switch around to other app capabilities vs forcing them into single threaded activities with modal forms. (Which do have their place and I use them). Listviews are particularly targeted since there is usually a variable amount of rows to be shown. The idea of using a hidden listview form is interesting and I'll take a look at that. I have been looking into using in memory tables in SQLite3 with one associated global counter to ensure unique table names. Now, if only PB would add some more options for building UDT types....

Patrice Terrier

Here is a function and a subroutine i wrote for WinDev, because they do not have built-in static.
It can be use to store/retrieve 32-bit values, either LONG, DWORD or SINGLE.

In this code replace Handle(MyWindow..Name) with the handle of the Parent of the hidden LISTBOX,
and change int to long, END to END IF, PROCEDURE to SUB, and RESULT with FUNCTION =.

// Retrieve static 32-bit value.
FUNCTION GetStaticValue(LOCAL sUseString is string)
sUseString += "|"
nValue is int = 0
nhMain is int = Handle(MyWindow..Name)
nStaticHandle is int = GetDlgItem(nhMain, IDC_STATIC)
IF nStaticHandle THEN
   nIndex is int = SendMessage(nStaticHandle, 399, -1, &sUseString)
   IF nIndex > -1 THEN // We found it
      nValue = SendMessage(nStaticHandle, 409, nIndex, 0)
   END
END
RESULT nValue


// Save static 32-bit value.
// Could be used also to save a real as they fit in 32-bit.
PROCEDURE SetStaticValue(LOCAL sUseString is string, LOCAL nValue is int)
sUseString += "|"
nhMain is int = Handle(MyWindow..Name)
nStaticHandle is int = GetDlgItem(nhMain, IDC_STATIC)
IF nStaticHandle = 0 THEN
   nStaticHandle = CreateWindowEx(0, "LISTBOX", "", WS_CHILD + LBS_HASSTRINGS, 0, 0, 0, 0, nhMain, IDC_STATIC, Instance, 0)
END
IF nStaticHandle THEN
   nIndex is int = SendMessage(nStaticHandle, 399, -1, &sUseString)
   IF nIndex > -1 THEN // We found same static
      SendMessage(nStaticHandle, 410, nIndex, nValue)
   ELSE // Add it to our static list
      SendMessage(nStaticHandle, 410, SendMessage(nStaticHandle, 384, 0, &sUseString), nValue)
   END
END


...