I am building an application that has a main form and sub forms that need to
share data.  After struggling with handles for a while, I am convinced there
must be an easier way.  For those that have done this, if they can offer
quick advice or sample code with preferred techniques, I'd appreciate it...
For those that like puzzles, and/or to skewer rookies' poor attempts at
tricks such as this, I have included my code for your enjoyment and
hopefully for my education. :)

I have set up the following global variables to track all field handles, and
the "current field" being worked on by a sub-form:

        // Array of text handles to track main form fields while passing
data between forms.
        MemHandle gTextH[MainLastField - MainFirstField + 1];

        // Main Field currently being worked on by sub-forms.  This is also
used to calculate offset into gTextH array for the appropriate field handle.
        UInt16  gMainFormFieldID = 0;

I then set the global handle prior to switching to a sub-form, via the
following case in MainFormHandleEvent:

        case SwitchToSubForm:

             // Indicate which field should be populated next time we return
to the main form.
             gMainFormFieldID = MainFirstField;

             // Set global handle for the above field before jumping to the
sub-form - in my code, this is a function call.
             fldP = (FieldType *)GetObjectPtr(gMainFormFieldID);

             // Set appropriate global text handle from field.
             fieldH = FldGetTextHandle(fldP);

             // Valid?
             if (fieldH) {

                    // Set valid handle in global area for retrieval by main
form.
                    gTextH[gMainFormFieldID - MainFirstField] = fieldH;

                    // Release handle from the field on the form, so when
the form closes the handle won't be destroyed.
                    FldSetTextHandle(fldP,NULL);
             }

             // Jump to sub-form
             FrmGotoForm (SubForm);
             handled = true;
             break;

In the SubFormHandleEvent, I set the appropriate field handle from the
global...

         switch (eventP->eType) {
                case frmOpenEvent:

                    frmP = FrmGetActiveForm();

                    // Is there a global text handle?
                    if (gTextH[gMainFormFieldID - MainFirstField]) {

                         // Set handle of sub-form field
                        fldP = (FieldType *)GetObjectPtr(SubFormFieldID);
                        oldH = FldGetTextHandle(fldP);
                        FldSetTextHandle(fldP,gTextH[gMainFormFieldID -
MainFirstField]);
                        if (oldH)
                            MemHandleFree(oldH);
                     }

                    FrmDrawForm(frmP);
                    break;
        }

Then when the user hits the "Done" button in the SubForm, I set the global
handle, and set the field handle to null prior to going back to the main
form...

      case SubFormDoneButton:

            fldP = (FieldType *)GetObjectPtr(SubFormFieldID);
            fieldH = FldGetTextHandle(fldP);
            if (fieldH) {
                  // Set valid handle in global area for retrieval by main
form.
                  gTextH[gMainFormFieldID - MainFirstField] = fieldH;
                  // Release handle from the field on the form, so when the
form closes the handle won't be destroyed.
                  FldSetTextHandle(fldP,NULL);
            }

            // Return to Main Form.
            FrmGotoForm(MainForm);
            handled = true;
            break;

And lastly, I set the field handles on the main form in MainFormInit (part
of the FormOpen event), as follows:

         // Get Global handles for any fields updated by sub forms.
         for (i = MainFirstField; i <= MainLastField; i++) {

                 // Is there a global text handle?
                 if (gTextH[i - MainFirstField]) {

                         // Get main field it corresponds to.
                         fldP = (FieldType *)GetObjectPtr(i);

                         // Set handle of main field, release old handle.
                        oldH = FldGetTextHandle(fldP);
                        FldSetTextHandle(fldP,gTextH[i - MainPickerField]);
                        if (oldH)
                              MemHandleFree(oldH);
                 }
         }

When I run this, it works for "one" (the first) field, but when I go to the
second field and come back to the main form, I sporadically get a "Memory
Free" error when I try to 'reconnect' the handles in the MainFormInit
routine...If I leave this routine out, the handles stay valid for all the
sub forms--I can bounce around to any of them, and they set the handles and
display the contents just fine...

Sorry for all the code - as I said, there must be a better way!  Any ideas
or suggestions would be greatly appreciated!

Geoff Thompson



-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palmos.com/dev/support/forums/

Reply via email to