Using Forms in a DLL

   

One of the unique things you can do with C++Builder is to put forms and other visual controls into your DLLs. These controls can be used so that they appear to be a part of the application that loads the DLL, even though they are not. This can help make a project more modular and also provides the basis for plug-in support allowing an application to be enhanced and extended independently.

Let's look at the sample project titled MDIChild_DLL.bpr , which can be found in the MDIDLL folder on the CD-ROM that accompanies this book. Listing 16.14 provides the header for the example, and Listing 16.15 provides the source code.

Listing 16.14 The MDIChild_DLL Header File
 #ifndef MDIChild_DLL  #define MDIChild_DLL  extern "C" void __declspec(dllexport)ShowMDIChildForm(HWND CallingApp);  extern "C" void __declspec(dllexport)ShowSDIFormModal(void);  #endif 
Listing 16.15 The MDIChild_DLL Source File
 #include <vcl.h>  #include <windows.h>  #pragma hdrstop  #include "MDIChild_DLL.h"  #include "MDIChildForm.h"  #include "SDIForm.h"  #pragma argsused  TApplication *ThisApp = NULL;  HWND  Handle;  BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)  {      // If the DLL is being unloaded then we need to reset its      // Application instance to what it originally was.      if (fwdreason == DLL_PROCESS_DETACH)      {         if (ThisApp) // any MDIs             Application = ThisApp;      }      return 1;  }  //                                      - void ShowMDIChildForm(HWND CallingApp)  {      if (!ThisApp)      {          ThisApp = Application;          Application->Handle = CallingApp;      }      FormMDIChild = new TFormMDIChild(Application);      FormMDIChild->Show();  }  //                                      - void ShowSDIFormModal(void)  {      FormSDI = new TFormSDI(NULL);      FormSDI->ShowModal();      delete FormSDI;  } 

Basically, this DLL provides the capability for an application to create a child window or a modal form. It's very simple in nature, but provides an example of some of the effects a DLL can provide for an application. The two principle functions provided by this DLL are ShowMDIChildForm() and ShowSDIFormModal() . In a moment we'll look at an example application that utilizes these functions, but first let's look at what is required to embed a form into a DLL.

You'll notice that in the ShowMDIChildForm() function created for this DLL the TFormMDIChild class that is used. Likewise, in ShowSDIFormmmodal() , the TFormSDI class is used. These two classes are identified in the header files listed at the top of our source code.

 #include "MDIChildForm.h"  #include "SDIForm.h" 

Using C++Builder, two forms were created; one to represent an MDI child window, and the other to represent an SDI window. These forms are created just like any other C++Builder form. Our project file for the DLL links these forms so that they are contained within the DLL, as illustrated in Figure 16.13. These forms can only be activated when an application calls either ShowMDIChildForm() or ShowSDIFormModal() .

Figure 16.13. Project Manager dialog for MDIChild_DLL .

graphics/16fig13.gif

Let's now take a look at some example code that makes use of this DLL functionality.

Modal SDI Windows

It's often useful to provide a Single Document Inferface (SDI) form that can appear to the user to display information or provide a mechanism for input. In our DLL example, ShowSDIChild() requires no parameter. We simply call the DLL function within our application, as shown in Listing 16.16.

Listing 16.16 Code Example Using ShowSDIForm , Which Is Contained Within MDIChild_DLL
 void __fastcall TParent::ShowSDIFormModalClick(TObject *Sender)  {      typedef void __declspec(dllimport)SHOWSDIFORM(void);      SHOWSDIFORM *ShowSDIForm;      // See if the DLL is loaded already.      if (!Dll)          Dll = LoadLibrary("MDIChild_DLL.dll");      // Check and make sure the Dll loaded      if (Dll)      {          // Get the address of the function.          ShowSDIForm = (SHOWSDIFORM *)GetProcAddress(Dll, "_ShowSDIFormModal");          // Make sure we have the address then call the function.          if (ShowSDIForm)              ShowSDIForm();          else          {              ShowMessage(SysErrorMessage(GetLastError()));              // If we couldn't get the address of the function              // we want to free the Dll.              FreeLibrary(Dll);          }      }      else      {          ShowMessage(SysErrorMessage(GetLastError()));          ShowMessage("Unable to load the DLL");      }  } 

When ShowSDIForm() is called, the DLL will then use the ShowModal() method to display a single instance of the form embedded within the DLL, which will be placed on top of the calling application. This is illustrated in Figure 16.14.

Figure 16.14. The MDI parent form displaying a modal SDI form.

graphics/16fig14.gif

A more practical example might be a DLL that generates an About box for an application. We could simply create an About form with generic fields and text, and provide a function with enough parameters to alter the form so that it works for a wide variety of applications. This way, we wouldn't have to re-create a new About form for every application. We can just use the DLL that contains the generic about box. This specific example is demonstrated later in the Using C++Builder DLLs with Microsoft Visual C++ section.

MDI Child Windows

Let's now look at how we can support a multiple document interface (MDI) for an application through our DLL. We might want to us an MDI feature when displaying multiple windows of similar information to the user. The code used to utilize this functionality within our example DLL is provided in Listing 16.17.

Listing 16.17 Code Example Using ShowMDIChild , Which Is Contained Within MDIChild_DLL
 void __fastcall TParent::New1Click(TObject *Sender)  {      typedef void __declspec(dllimport)SHOWMDICHILD(HWND);      SHOWMDICHILD *ShowMDIChild;      // See if the DLL is loaded already.      if (!Dll)          Dll = LoadLibrary("MDIChild_DLL.dll");      // Check and make sure the Dll is loaded      if (Dll)      {          // Get the address of the function.          ShowMDIChild = (SHOWMDICHILD *)GetProcAddress(Dll,                                                 "_ShowMDIChildForm");          // Make sure we have the address then call the function.          if (ShowMDIChild)              ShowMDIChild(Handle);          else          {              ShowMessage(SysErrorMessage(GetLastError()));              // If we couldn't get the address of the function              // we want to free the Dll.              FreeLibrary(Dll);          }      }      else      {          ShowMessage(SysErrorMessage(GetLastError()));          ShowMessage("Unable to load the DLL");      }  }  //                                      - 

For ShowMDIChild() , we simply provide the Handle to our application as the lone parameter. The DLL uses this window handle to associate the application with the MDI window that will be created. Basically, we trick the DLL into thinking the child form is part of the application that contains the parent. This is accomplished by switching the Application instance for the DLL to the Application instance of the calling application (but, we keep track of the DLL Application instance for clean up). The end result is that the MDI child is fully aware of its parent form. The affect of this capability is illustrated in Figure 16.15.

Figure 16.15. The MDI parent form with three MDI child forms open within it.

graphics/16fig15.gif

That's all there is to it. We call these functions containing visual controls, such as forms, much the same way we would call any other functions within a DLL. What's appealing about this approach is that the functionally is totally contained within the DLL, and our application can hijack and use this functionality at runtime.


   
Top


C++ Builder Developers Guide
C++Builder 5 Developers Guide
ISBN: 0672319721
EAN: 2147483647
Year: 2002
Pages: 253

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net