c++formstemplatesfiremonkeyc++builder-xe8

Detecting if a form of a given type is already open in Firemonkey application


I am trying to come up with a way to tell if a given type of form is open in my application, before opening a new one. The reason for this, is that there are certain forms in the application which only make sense to have one instance of them open at a time, but I would rather not make them strictly modal.

To solve this I have implemented the following method, which iterates through Screen->Forms and attempts to cast each form to the type of form provided. I figured if the cast was made, I have discovered that type of form is already open.

template <typename T>
bool __fastcall FormOfTypeExists( T * Form )
{
    for( int i = 0; i < Screen->FormCount; i++ )
    {
        T * CurrentForm = (T*)Screen->Forms[i];

         if( CurrentForm != 0 )
         {
             return true;
         }
    }

    return false;
};

Then I call the method wherever I am attempting to create a form, like so:

TFormA *Form;

if( FormOfTypeExists( Form ) )
{
    return;
}

Form = new TFormA( Owner );

Form->Show();

The problem that I am running into is that it seems I am always able to successfully cast the TCommonCustomForm objects in Screen->Forms to whatever type of form I have passed in.

Is there a way I can alter my logic to successfully detect if a form of a certain type already exists in the application? Is there a better approach to this problem I should be looking at?


Solution

  • You are using a hard cast that does not take the object's real type into account. That is why the cast always succeeds (when it really doesn't). To test if an object is of a particular type, you need to use dynamic_cast instead.

    And don't pass a variable as input when you are not actually using it for anything.

    Try this instead:

    template <typename T>
    bool __fastcall FormOfTypeExists()
    {
        for( int i = 0; i < Screen->FormCount; i++ )
        {
            T * CurrentForm = dynamic_cast<T*>(Screen->Forms[i]);
            if( CurrentForm != NULL )
            {
                return true;
            }
        }
    
        return false;
    }
    

    if( FormOfTypeExists<TFormA>() )
    {
        return;
    }
    
    TFormA *Form = new TFormA( Owner );
    Form->Show();