home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 7.ddi / OWLDOC.ZIP / OWLDLL.DOC < prev   
Encoding:
Text File  |  1992-06-10  |  31.3 KB  |  787 lines

  1. Online document
  2. ___________________________________________________________________________
  3.  
  4.                                        ObjectWindows dynamic link libraries
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12. CONTENTS
  13. ___________________________________________________________________________
  14.  
  15.  
  16.  
  17.  
  18.  
  19.            ObjectWindows dynamic             Macro expansion . . . . . .  7
  20.            link libraries          1         Pointers and typedefs . . .  7
  21. C++ DLLs . . . . . . . . . . . . . 1       Building a shared class in a
  22.   Writing DLL functions  . . . . . 1       DLL . . . . . . . . . . . . . 10
  23.     LibMain and WEP  . . . . . . . 2       Using a shared class  . . . . 10
  24.     DLL-specific functions . . . . 3     Calling an ObjectWindows DLL from
  25.   Exporting DLL functions  . . . . 3     outside ObjectWindows . . . . . 11
  26.   Calling DLL functions  . . . . . 4   Using ObjectWindows as a DLL  . . 12
  27.   ObjectWindows DLLs . . . . . . . 4
  28.     The module object  . . . . . . 5
  29.   Shared classes . . . . . . . . . 6
  30.     Declaring and defining a shared
  31.     class  . . . . . . . . . . . . 6
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.                     A dynamic-link library (DLL) is a library of functions
  39.                     whose references are resolved at run time rather than
  40.                     at compile time. DLL functions are dynamically linked
  41.                     to a calling application.
  42.  
  43.                     Each application using statically linked code has its
  44.                     own copy of the code. The code for functions defined in
  45.                     a DLL is shared by all calling applications; only one
  46.                     copy is placed in memory. Defining code shared by a
  47.                     group of applications in a DLL therefore reduces the
  48.                     size of the .EXEs of the calling applications.
  49.  
  50.                     You might want to define complex windowing behavior,
  51.                     shared by a group of your applications, in an Object-
  52.                     Windows DLL. In this chapter, you'll learn how to write
  53.                     and use an ObjectWindows DLL. You'll also learn how to
  54.                     use the ObjectWindows dynamic-link library (OWL31.DLL).
  55.  
  56.  
  57.  
  58. ===========================================================================
  59. C++ DLLs
  60. ===========================================================================
  61.  
  62.                     DLLs can contain ordinary functions or a combination of
  63.                     functions and exported C++ classes. First, we'll
  64.                     examine DLLs in the context of a library of ordinary
  65.                     functions. This section contains an overview of Borland
  66.                     C++ DLLs; you'll learn how to write, export, and call a
  67.                     DLL function using Borland C++.
  68.  
  69.  
  70.        Writing DLL
  71.          functions  =======================================================
  72.  
  73.                     Windows requires that two functions be defined in every
  74.                     DLL: LibMain and WEP (Windows Exit Procedure).
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.                                    - 1 -
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88. ------------------  You must supply the LibMain function, which is the main
  89.    LibMain and WEP  entry point for a Windows DLL. Windows calls LibMain
  90.                     once, when the library is first loaded. LibMain
  91. ------------------  initializes the DLL; this initialization depends almost
  92.                     entirely on the particular DLL's function, but might
  93.                     include the following tasks:
  94.  
  95.                     o unlocking the data segment with UnlockData, if it has
  96.                       been declared as MOVEABLE
  97.  
  98.                     o setting up global variables for the DLL, if it uses
  99.                       any
  100.  
  101.               Note  The DLL startup code C0Dx.OBJ initializes the local
  102.                     heap automatically.
  103.  
  104.                     The following parameters are passed to LibMain:
  105.  
  106.                       int PASCAL LibMain(HANDLE hInstance, WORD wDataSeg,
  107.                                          WORD cbHeapSize, LPSTR lpCmdLine)
  108.  
  109.  HANDLE, WORD, and  o hInstance is the instance handle of the DLL.
  110.  LPSTR are defined
  111.      in windows.h.  o wDataSeg is the value of the data segment (DS)
  112.                       register.
  113.  
  114.                     o cbHeapSize is the size of the local heap specified in
  115.                       the module definition file for the DLL.
  116.  
  117.                     o lpCmdLine is a far pointer to the command line
  118.                       specified when the DLL was loaded. This is almost
  119.                       always null, because typically DLLs are loaded
  120.                       automatically without parameters. It is possible,
  121.                       however, to supply a command line to a DLL when it is
  122.                       loaded explicitly.
  123.  
  124.                     The return value for LibMain is either 1 (successful
  125.                     initialization) or 0 (unsuccessful initialization).
  126.                     Windows will unload the DLL from memory if the value is
  127.                     0.
  128.  
  129.                     WEP is the exit point of a DLL; Windows calls it prior
  130.                     to unloading the DLL. This function is not necessary in
  131.                     a DLL (because the Borland C++ run-time libraries
  132.                     provide a default one), but can be supplied by the
  133.                     writer of a DLL to perform any cleanup of the DLL
  134.                     before it is unloaded from memory.
  135.  
  136.                     Under Borland C++, WEP does not need to be exported.
  137.                     This is the prototype for WEP:
  138.  
  139.                       int FAR PASCAL WEP (int nParameter)
  140.  
  141.  
  142.  
  143.  
  144.  
  145.                                    - 2 -
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.                     o nParameter is either WEP_SYSTEMEXIT (all of Windows
  153.                       shuts down) or WEP_FREE_DLL (just this DLL is
  154.                       unloaded).
  155.  
  156.                     WEP returns 1 to indicate success. Note that Windows
  157.                     currently doesn't use this return value.
  158.  
  159.  
  160.                     The additional functions defined in your DLL depend on
  161. ------------------  the services your DLL provides. When writing functions
  162.       DLL-specific  that will be called from an application, you need to
  163.          functions  keep these things in mind:
  164.  
  165. ------------------  o Make calls to DLL functions far calls, and make
  166.                       pointers specified as parameters and return values
  167.                       far pointers. This is because a DLL has different
  168.                       code and data segments than the calling application.
  169.  
  170.                     o Static data defined in a DLL is global to all calling
  171.                       applications. Global data set by one caller can be
  172.                       accessed by another. If you need data to be private
  173.                       for a given caller, you need to dynamically allocate
  174.                       and manage the data yourself.
  175.  
  176.  
  177.      Exporting DLL
  178.          functions  =======================================================
  179.  
  180.                     After writing your DLL functions, you must export the
  181.                     functions that you want available to a calling
  182.                     application. There are two steps involved: compiling
  183.                     your DLL functions as exportable functions and
  184.                     exporting them. You can do this in the following ways:
  185.  
  186.                     o If you flag a function with the _export keyword, it's
  187.                       compiled as exportable and is then exported.
  188.  
  189.                     o If you don't flag a function with _export and you use
  190.                       the -WD command-line switch or the Windows DLL All
  191.                       Functions Exportable IDE option when compiling, the
  192.                       function is compiled as exportable. However, the
  193.                       function only gets exported if you also list it in
  194.                       the EXPORTS section of the module definition (.DEF)
  195.                       file.
  196.  
  197.                     o If you add the _export keyword to a class
  198.                       declaration, the entire class (data and function
  199.                       members) will be compiled as exportable and exported.
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.                                    - 3 -
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.        Calling DLL  =======================================================
  217.          functions
  218.                     You call a DLL function within an application just as
  219.                     you would call a function defined in the application
  220.                     itself. However, you must import the DLL functions that
  221.                     your application calls.
  222.  
  223.                     There are two ways to import a DLL function:
  224.  
  225.                     1. You can add an IMPORTS section to the calling
  226.                        application's module definition (.DEF) file and list
  227.                        the DLL function as an import.
  228.  
  229.                     2. You can link an import library that contains import
  230.                        information for the DLL function to the calling
  231.                        application. (Use IMPLIB to make the import
  232.                        library.)
  233.  
  234.                     When your application is executed, the .DLL files for
  235.                     the DLLs that it calls must be in the current
  236.                     directory, on the path, or in the Windows or Windows
  237.                     system directory; otherwise, your application won't
  238.                     load.
  239.  
  240.  
  241. ObjectWindows DLLs
  242.                     =======================================================
  243.  
  244.                     ObjectWindows DLLs differ from ordinary DLLs in that,
  245.                     with ObjectWindows DLLs, you export classes derived
  246.                     from ObjectWindows classes as well as your own classes.
  247.                     This makes those classes and their member functions
  248.                     available to all .EXEs that dynamically link with your
  249.                     DLL.
  250.  
  251.                     If you find that complex window behavior is shared by a
  252.                     group of your applications, you can define this
  253.                     behavior in an ObjectWindows DLL. For example, you
  254.                     might build a DLL that defines
  255.  
  256.                     o a complex window used by related applications
  257.  
  258.                     o useful dialogs
  259.  
  260.                     o reusable custom controls
  261.  
  262.                     o common drawable controls
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.                                    - 4 -
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280. ------------------  An instance of TModule acts as an object-oriented
  281.  The module object  replacement for an ObjectWindows DLL. TModule member
  282.                     functions provide support for window and memory
  283. ------------------  management and process errors.
  284.  
  285.                     Construct a module object in the LibMain function of
  286.                     your DLL:
  287.  
  288.                       PTModule TheModule;
  289.  
  290.                       int FAR PASCAL LibMain(HANDLE hInstance, WORD,
  291.                                              WORD cbHeapSize, LPSTR
  292.                                              lpCmdLine)
  293.                       {
  294.                         int TheStatus;
  295.  
  296.                         TheModule = new TModule("LibName", hInstance,
  297.                       lpCmdLine);
  298.                         TheStatus = TheModule->Status;
  299.                         if (TheStatus != 0)
  300.                         {
  301.                           TheModule->Error(TheStatus);
  302.                           delete TheModule;
  303.                           TheModule = NULL;
  304.                         }
  305.  
  306.                         return (TheStatus == 0);
  307.                       }
  308.  
  309.                     In this example LibMain, an instance of TModule is
  310.                     constructed. The hInstance and lpCmdLine parameters
  311.                     received from Windows are passed to the TModule
  312.                     constructor to initialize data members of the same
  313.                     name.
  314.  
  315.                     After the module object is constructed, its Status data
  316.                     member is used to determine the success or failure of
  317.                     module initialization. If the Status member contains a
  318.                     nonzero value, the initialization of the module object
  319.                     is unsuccessful. At this point, you should delete the
  320.                     module object in LibMain; zero will be returned to
  321.                     Windows to indicate that an error occurred (as shown
  322.                     previously in LibMain). Set Status to an error that you
  323.                     define (a nonzero value) if your DLL cannot be
  324.                     successfully initialized.
  325.  
  326.                     In WEP, the module object is deleted:
  327.  
  328.                       int FAR PASCAL WEP(int)
  329.                       {
  330.                         delete TheModule;
  331.                         return 1;
  332.  
  333.  
  334.  
  335.  
  336.  
  337.                                    - 5 -
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.                       }
  345.  
  346.                     As noted, Windows does not use WEP's return value.
  347.  
  348.                     Usually, your DLL will require additional
  349.                     initialization and cleanup. You could perform this
  350.                     processing in your LibMain and WEP functions; better
  351.                     yet, derive a class from TModule. Perform the required
  352.                     initialization and cleanup in its constructor and
  353.                     destructor, and define data members for data global to
  354.                     your DLL.
  355.  
  356.  
  357.     Shared classes
  358.                     =======================================================
  359.  
  360.                     You can share code that defines the behavior of a
  361.                     general-use dialog box by defining a dialog class in a
  362.                     DLL (a shared class). For example, a group of graphics
  363.                     applications might use a color dialog defined in a DLL
  364.                     to retrieve an RGB value from the user. To do so,
  365.                     you'll need to export the class from the DLL and import
  366.                     the class into your applications.
  367.  
  368.  
  369.                     You'll need to do the following in order to
  370. ------------------  successfully define and declare a shared class.
  371.      Declaring and
  372.  defining a shared  o pass an additional PTModule parameter to window
  373.              class    constructors (in certain situations).
  374.  
  375. ------------------  o conditionally declare your class as either _export or
  376.                       huge.
  377.  
  378.                     o use far pointers and far references in your
  379.                       declarations.
  380.  
  381.                     If you declare a shared class in an include file that
  382.                     is included by both the DLL and an application using
  383.                     the DLL, the class must be declared _export when
  384.                     compiling the DLL and huge when compiling the
  385.                     application. You can do this with the _EXPORT macro,
  386.                     which is set to _export or huge as needed when building
  387.                     a DLL or using an .EXE with a DLL.
  388.  
  389.                       class _EXPORT TColorControl : public TControl
  390.                       {
  391.  
  392.                       protected:
  393.                       ...
  394.  
  395.                       public:
  396.                       ...
  397.                       };
  398.  
  399.  
  400.  
  401.                                    - 6 -
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.                  Macro expansion
  409.                  =========================================
  410.  
  411.                     The _EXPORT macro expands into _export if _ _DLL_ _ is
  412.                     defined. Borland C++ defines _ _DLL_ _ automatically
  413.                     when you supply the -WD or -WDE options to the
  414.                     command-line compiler, or when you specify that you are
  415.                     building a DLL in the IDE. If you are not building a
  416.                     DLL, then _EXPORT expands to _CLASSTYPE. _CLASSTYPE is
  417.                     a macro that expands into "huge", "far", or "near".
  418.  
  419.                     For _CLASSTYPE to expand into "huge" (which is required
  420.                     for classes shared between an application and DLLs), a
  421.                     third macro is used: _CLASSDLL. You must define
  422.                     _CLASSDLL on either the compiler command line or by
  423.                     including it in the "Defines" edit field in the
  424.                     compiler options dialog box of the Borland C++ IDE.
  425.                     When defined, _CLASSDLL communicates to both the
  426.                     compiler and to the _CLASSTYPE macro your intention to
  427.                     use the classes being compiled as shared classes.
  428.  
  429.                     In summary, declare your shared classes with _EXPORT as
  430.                     in the example above. Compile your DLLs with the
  431.                     appropriate compiler directives and your classes will
  432.                     be exported. Compile your .EXE with the _CLASSDLL macro
  433.                     defined, and your classes will be compiled as huge and
  434.                     will therefore be suitable for sharing with DLLs.
  435.  
  436.  
  437.                  Pointers and typedefs
  438.                  =========================================
  439.  
  440.                     You must also declare the pointers and references in
  441.                     the header file of your shared class as far pointers.
  442.                     You can explicitly set the pointers to far, or you can
  443.                     use the _FAR macro to do this. _FAR is set to far only
  444.                     when _CLASSDLL is defined.
  445.  
  446.                     ObjectWindows defines data type specifiers for each
  447.                     ObjectWindows class using the _FAR macro. The PTDialog
  448.                     typedef is shown here:
  449.  
  450.                       typedef TDialog _FAR *PTDialog;
  451.  
  452.                     ObjectWindows defines similar type specifiers for each
  453.                     ObjectWindows class. Using these ObjectWindows typedefs
  454.                     will help improve the readability of your code.
  455.  
  456.                     When referring to a pointer to an ObjectWindows class,
  457.                     use a type whose name is P followed by the name of a
  458.                     class. Similarly, for a reference to a class, use an R
  459.                     followed by the name of the class. For example, a
  460.                     pointer to a TWindow is a PTWindow. A reference to a
  461.                     TDialog is an RTDialog.
  462.  
  463.  
  464.  
  465.                                    - 7 -
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.                     All ObjectWindows classes automatically define those
  473.                     and other typedefs that make use of the _FAR macro. To
  474.                     automatically get those typedefs defined for your own
  475.                     classes, use the _CLASSDEF macro at the top of your
  476.                     header file for each class you define. For example,
  477.                     this code
  478.  
  479.                       _CLASSDEF(TMyWindow)
  480.                       class _EXPORT TMyWindow:public TWindow
  481.                       {
  482.                       ...
  483.                       };
  484.  
  485.                     will cause PTMyWindow, RTMyWindow, and other typedefs
  486.                     to be defined. See the documentation on _CLASSDEF in
  487.                     Chapter 18 for details of the typedefs automatically
  488.                     defined.
  489.  
  490.                     Due to the way the Borland C++ compiler treats classes
  491.                     and structures, if your shared classes contain, as data
  492.                     members, pointers to structures or other classes, you
  493.                     may have to declare any referenced structures and
  494.                     classes with the _CLASSTYPE macro. For example,
  495.  
  496.                       struct _CLASSTYPE TMyStruct
  497.                       {
  498.                       };
  499.                       typedef TMyStruct _FAR * PTMyStruct;
  500.  
  501.                       class _EXPORT TMyClass
  502.                       {
  503.                          PTMyStruct ptms;
  504.                       };
  505.  
  506.                     In the above example, TMyStruct may need to be declared
  507.                     with _CLASSTYPE (as shown), since pointers to it are
  508.                     contained in the huge class TMyClass. (_EXPORT implies
  509.                     "huge" when you are compiling a DLL or compiling an
  510.                     .EXE with the _CLASSDLL macro defined).
  511.  
  512.                     The declaration of a TColorDialog shared class and the
  513.                     TColorControl class that it uses are shown next.
  514.  
  515.         This class    _CLASSDEF(TColorControl)
  516. definition is from
  517.        colordlg.h.    class _EXPORT TColorControl : public TControl
  518.                       {
  519.                       public:
  520.                         COLORREF Color;
  521.  
  522.                         TColorControl(PTWindowsObject AParent, int
  523.                                       ResourceId, COLORREF AColor, PTModule
  524.                                       AModule = NULL);
  525.  
  526.  
  527.  
  528.  
  529.                                    - 8 -
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.                       protected:
  537.                         virtual LPSTR GetClassName();
  538.                         virtual void GetWindowClass(WNDCLASS _FAR &
  539.                       AWndClass);
  540.                         virtual void Paint(HDC, PAINTSTRUCT _FAR & PS);
  541.                         virtual WORD Transfer(Pvoid DataPtr, WORD
  542.                       TransferFlag);
  543.                         virtual void WMLButtonDown(RTMessage Msg) =
  544.                                      [WM_FIRST + WM_LBUTTONDOWN];
  545.                         virtual void WMLButtonDblClk(RTMessage Msg) =
  546.                                      [WM_FIRST + WM_LBUTTONDBLCLK];
  547.  
  548.                       public:
  549.                         virtual void SetColor(COLORREF AColor);
  550.                       };
  551.  
  552.                       _CLASSDEF(TColorDialog)
  553.  
  554.                       class _EXPORT TColorDialog : public TDialog
  555.                       {
  556.                       protected:
  557.                         PTScrollBar ColorBar1;
  558.                         PTScrollBar ColorBar2;
  559.                         PTScrollBar ColorBar3;
  560.                         PTColorControl SelColor;
  561.  
  562.                       public:
  563.                         TColorDialog(PTWindowsObject AParent, COLORREF _FAR
  564.                                      & TheColor, PTModule TheModule =
  565.                                      NULL);
  566.  
  567.                       protected:
  568.                         virtual void DefChildProc(RTMessage Msg);
  569.                         virtual void SetupWindow();
  570.                         virtual void TransferData(WORD TransferFlag);
  571.                         virtual void UpdateBars(COLORREF AColor);
  572.                       };
  573.  
  574.                     An RTMessage typedef is used in these declarations to
  575.                     improve code readability and to ensure the reference is
  576.                     a far reference when the class is used as a shared
  577.                     class. ObjectWindows defines it as follows:
  578.  
  579.                       typedef TMessage _FAR & RTMessage;
  580.  
  581.                     Various other macros that use the _FAR macro are
  582.                     defined by ObjectWindows in _defs.h.
  583.  
  584.                     After you've properly declared your shared class, you
  585.                     can define its implementation in your DLL as you would
  586.                     in an ObjectWindows application.
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.                                    - 9 -
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600. ------------------  After declaring and defining your shared class, you
  601.  Building a shared  need to
  602.     class in a DLL
  603.                     o write LibMain and WEP functions
  604. ------------------
  605.                     o compile your DLL
  606.  
  607.                     You can copy the LibMain and WEP functions previously
  608.                     shown to your DLL's .CPP source file, or you can use
  609.                     your customized versions.
  610.  
  611.                     To compile your DLL, simply follow the normal
  612.                     procedures for generating DLLs. For the command-line
  613.                     compiler, specify either the -WDE or -WD options. For
  614.                     the IDE, ensure you are building a DLL by checking both
  615.                     the Options|Compiler|Entry/Exit Code and Options|Linker
  616.                     dialog boxes for the correct DLL options. See your
  617.                     Borland C++ documentation for general information about
  618.                     building DLLs.
  619.  
  620.                     After you have compiled and linked your DLL, use IMPLIB
  621.                     to generate an import library for your DLL. This import
  622.                     library will list all exported member functions from
  623.                     your shared classes as well as any ordinary functions
  624.                     which you've exported.
  625.  
  626.  
  627.                     To use a shared class from a DLL in your application,
  628. ------------------  you need to compile your application defining the
  629.     Using a shared  _CLASSDLL macro (as discussed earlier). Then link your
  630.              class  application with the import library you created for
  631.                     your DLL. Then you can use the class defined in the DLL
  632. ------------------  as if the class had been defined by your application.
  633.  
  634.                     In the following example code, TColorDialog is executed
  635.                     when a Color menu item is selected from TTestWindow's
  636.                     menu:
  637.  
  638.                       void TTestWindow::CMColor(RTMessage) {
  639.                         COLORREF TheColor;
  640.  
  641.                       ...
  642.                         if (GetApplication()->ExecDialog(new
  643.                                                          TColorDialog(this,
  644.                                                          TheColor,
  645.                                                          GetModule())) ==
  646.                                                          IDOK)
  647.                       ...
  648.                       }
  649.  
  650.                     this is specified as the parent window object to the
  651.                     constructor of the TColorDialog.
  652.  
  653.  
  654.  
  655.  
  656.  
  657.                                   - 10 -
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.                     You could share code that defines the behavior of a
  665.                     window (perhaps, a complex help window) or of a control
  666.                     (perhaps a custom or drawable control). The procedure
  667.                     outlined here applies to the definition of any Object-
  668.                     Windows shared class.
  669.  
  670.                     You can use an ObjectWindows shared class as a base
  671.                     class for a class that is defined in an ObjectWindows
  672.                     application, or in another ObjectWindows DLL.
  673.  
  674.  
  675. Calling an Object-
  676.   Windows DLL from  =======================================================
  677.    outside Object-
  678.            Windows  Up to this point, we've assumed that the applications
  679.                     calling your DLL were written using ObjectWindows. You
  680.                     can also call an ObjectWindows DLL from a non-Object-
  681.                     Windows application.
  682.  
  683.                     An ObjectWindows child window requires some support
  684.                     from a parent window object. When a child window is
  685.                     created in a DLL and the parent window is created by
  686.                     the calling application, the parent-child relationship
  687.                     must be simulated in the DLL. This is done by
  688.                     constructing a window object in the ObjectWindows DLL
  689.                     that's associated with the parent window whose handle
  690.                     is specified on a DLL call. This object will be deleted
  691.                     by ObjectWindows when the window in the calling
  692.                     application is destroyed.
  693.  
  694.                     Note that incoming messages for the parent window are
  695.                     first dispatched to its associated ObjectWindows
  696.                     object. The associated object only responds to those
  697.                     messages that support its child windows. All messages
  698.                     are passed on to the window in the calling application.
  699.  
  700.                     In the following code, the exported function
  701.                     CreateDLLWindow is in an ObjectWindows DLL. It is
  702.                     assumed to be called by a non-ObjectWindows .EXE
  703.                     (although it will work from an ObjectWindows .EXE as
  704.                     well).
  705.  
  706.                       BOOL _far _export CreateDLLWindow(HWND ParentHWnd)
  707.                       {
  708.                         PTWindowsObject AParentAlias;
  709.                         PTWindow TheWindow;
  710.  
  711.                         AParentAlias =
  712.                       DLLHelloLib->GetParentObject(ParentHWnd);
  713.                         TheWindow = new TWindow(AParentAlias, "Hello from a
  714.                                                 DLL!", DLLHelloLib);
  715.                         TheWindow->Attr.Style |= WS_POPUPWINDOW |
  716.                                                  WS_CAPTION | WS_THICKFRAME
  717.  
  718.  
  719.  
  720.  
  721.                                   - 11 -
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.                                                  | WS_MINIMIZEBOX |
  729.                                                  WS_MAXIMIZEBOX;
  730.                         TheWindow->Attr.X = 100;
  731.                         TheWindow->Attr.Y = 100;
  732.                         TheWindow->Attr.W = 300;
  733.                         TheWindow->Attr.H = 300;
  734.                         return (DLLHelloLib->MakeWindow(TheWindow) ==
  735.                       TheWindow);
  736.                       }
  737.  
  738.                     CreateDLLWindow is passed the handle to a window that
  739.                     potentially might not correspond with an ObjectWindows
  740.                     window. The call to GetParentObject returns an Object-
  741.                     Windows object which is either the actual ObjectWindows
  742.                     TWindowsObject (if there is one) or a surrogate object
  743.                     created on the fly. You can use this TWindowsObject
  744.                     instance just as though you had created it in the DLL.
  745.  
  746.                     In the above example, a child window of the supplied
  747.                     ParentHWnd is created as a popup window.
  748.  
  749.                     Note that the DLL's module pointer, DLLHelloLib, is
  750.                     supplied as the last parameter to TWindow's constructor
  751.                     to provide an owning TModule for the window.
  752.  
  753.  
  754.  
  755. ===========================================================================
  756. Using ObjectWindows as a DLL
  757. ===========================================================================
  758.  
  759.                     To enable your ObjectWindows applications to share a
  760.                     single copy of the ObjectWindows library, you can
  761.                     dynamically link them to the ObjectWindows DLL. To do
  762.                     this, you'll need to be sure of the following:
  763.  
  764.                     o When compiling, be sure to define the macro _CLASSDLL
  765.                       on the compiler command line or in the IDE.
  766.  
  767.                     o If using any model other than large, ensure that all
  768.                       pointers and references in class data members,
  769.                       argument lists, and return values use the _FAR macro
  770.                       to force far addresses.
  771.  
  772.                     o Instead of specifying the static link ObjectWindows
  773.                       library when linking (that is, OWLWS.LIB, OWLWM.LIB,
  774.                       or OWLWL.LIB), specify the ObjectWindows DLL import
  775.                       library (OWL.LIB).
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.                                   - 12 -
  786.  
  787.