Jump to content

Work Place Shell Programming - Part 1: Difference between revisions

From EDM2
Ak120 (talk | contribs)
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
Written by [[Chris Palchak]]
{{WPSProg}}
 
''Written by [[Chris Palchak]]''
{| width="400" cellpadding="4"
| align="CENTER" valign="MIDDLE" |
[[Work Place Shell Programming - Part 1|Part 1]]
| align="CENTER" valign="MIDDLE" |
[[Work Place Shell Programming - Part 2|Part 2]]
| align="CENTER" valign="MIDDLE" |
[[Work Place Shell Programming - Part 3|Part 3]]
| align="CENTER" valign="MIDDLE" |
[[Work Place Shell Programming - Part 4|Part 4]]
|}


==Purpose==
==Purpose==
The purpose of this series of articles is to teach the reader how to integrate an application with the OS/2 Work Place Shell. As this writer always looks for ways to avoid using API calls, the settings pages are written in C++ using the IBM Visual Age for C++ compiler and Open Class Library. Hopefully, those readers who are unfamiliar with C++ will be inspired to learn the language once they see the brevity of the settings page programs.
The purpose of this series of articles is to teach the reader how to integrate an application with the OS/2 Work Place Shell. As this writer always looks for ways to avoid using API calls, the settings pages are written in C++ using the IBM Visual Age for C++ compiler and Open Class Library. Hopefully, those readers who are unfamiliar with C++ will be inspired to learn the language once they see the brevity of the settings page programs.


==Overview==
==Overview==
There are two parts to a Work Place Shell (WPS) program. The first is a System Object Model (SOM) Interface Definition Language (IDL) source file. The second part, is the code you write in C, C++, or some other supported language. This first article will show the reader how to:
There are two parts to a Work Place Shell (WPS) program. The first is a System Object Model (SOM) Interface Definition Language (IDL) source file. The second part, is the code you write in C, C++, or some other supported language. This first article will show the reader how to:
* Create the SOM IDL module,
* Create the SOM IDL module,
* Compile the IDL code,
* Compile the IDL code,
Line 25: Line 12:
* Register the new WPS class,
* Register the new WPS class,
* Create objects of the new class
* Create objects of the new class
The second article in this series will show the reader the code that needs to be added to the generated C++ program.
The second article in this series will show the reader the code that needs to be added to the generated C++ program.


Line 33: Line 19:


==SOM IDL==
==SOM IDL==
IBM's SOM is the basis for all WPS objects. To create custom WPS objects, you must use the SOM IDL. This may seem intimidating at first, but note that there are only two categories of statements in the SOM IDL:
IBM's SOM is the basis for all WPS objects. To create custom WPS objects, you must use the SOM IDL. This may seem intimidating at first, but note that there are only two categories of statements in the SOM IDL:
# Attribute (or data) definition statements
# Attribute (or data) definition statements
# Interface (function) declaration statements
# Interface (function) declaration statements
Once these statements are prepared, you simply generate stub program files and fill in the functions with your own code. For the purposes of this article, the generated stub files will be C++ programs. The following command will read a SOM IDL file and generate a stub C++ program along with the necessary header files:
Once these statements are prepared, you simply generate stub program files and fill in the functions with your own code. For the purposes of this article, the generated stub files will be C++ programs. The following command will read a SOM IDL file and generate a stub C++ program along with the necessary header files:
 
  sc.exe -s"xc;xh;xih;def" -S128000 chfile.idl.
  <small>
  sc.exe -s"xc;xh;xih;def" -S128000 chfile.idl.
</small>


In this case, chfile.idl is the SOM IDL file. The class described in this file is ChartFile. This is a class that inherits from WPDataFile and contains stock quotes. This is the first of two WPS classes that will be developed over the course of these articles. The other class that will be developed is ChartFolder. ChartFolder inherits from WPFolder and is used to store ChartFile objects.
In this case, chfile.idl is the SOM IDL file. The class described in this file is ChartFile. This is a class that inherits from WPDataFile and contains stock quotes. This is the first of two WPS classes that will be developed over the course of these articles. The other class that will be developed is ChartFolder. ChartFolder inherits from WPFolder and is used to store ChartFile objects.


ChFile.idl listing:
ChFile.idl listing:
 
<code>
<small>
   #ifndef CHFILE_IDL
   #ifndef CHFILE_IDL
   #define CHFILE_IDL
   #define CHFILE_IDL
Line 272: Line 251:
   
   
   #endif
   #endif
</small>
</code>


==Building the DLL==
==Building the DLL==
===The Module Definition File===
===The Module Definition File===
The following file is generated by the SOM compiler. This file must be modified to include the custom functions declared for setting and getting ChartFile's data.
The following file is generated by the SOM compiler. This file must be modified to include the custom functions declared for setting and getting ChartFile's data.


ChFile.def Listing
ChFile.def Listing
 
<code>
<small>
   ;  This file was generated by the SOM Compiler.
   ;  This file was generated by the SOM Compiler.
   ;  FileName: ChFile.def.
   ;  FileName: ChFile.def.
Line 299: Line 275:
       M_ChartFileClassData
       M_ChartFileClassData
       M_ChartFileNewClass
       M_ChartFileNewClass
</small>
</code>


This is the modified module definition file. Note that there is no need to use mangled function names for this DLL because the exported functions are not really C++ class members. This file has been named Export.def so that it does not get overlaid when a new ChFile.def gets generated.
This is the modified module definition file. Note that there is no need to use mangled function names for this DLL because the exported functions are not really C++ class members. This file has been named Export.def so that it does not get overlaid when a new ChFile.def gets generated.


Export.def Listing
Export.def Listing
 
<code>
<small>
   LIBRARY ChFile INITINSTANCE
   LIBRARY ChFile INITINSTANCE
   DESCRIPTION 'ChartFile Class Library'
   DESCRIPTION 'ChartFile Class Library'
Line 335: Line 310:
       ChFileX_getDaysInShortAvg    @23
       ChFileX_getDaysInShortAvg    @23
       ChFileX_setLastDD            @24
       ChFileX_setLastDD            @24
</small>
</code>
 
ChFile.mak Listing


<small>
ChFile.mak Listing
<code>
   # ChFile.mak
   # ChFile.mak
   # Created by IBM WorkFrame/2 MakeMake at 21:59:45 on
   # Created by IBM WorkFrame/2 MakeMake at 21:59:45 on
Line 389: Line 363:
       .\ChFile.cpp \
       .\ChFile.cpp \
       {D:\som\ChFile;$(INCLUDE);}ChFile.xih \
       {D:\som\ChFile;$(INCLUDE);}ChFile.xih \
</small>
</code>


==Registering ChartFile==
==Registering ChartFile==
The following REXX program will register the ChartFile class:
The following REXX program will register the ChartFile class:
 
<code>
<small>
   /* REXX: Register */
   /* REXX: Register */
   
   
Line 410: Line 382:
   
   
   Exit;
   Exit;
</small>
</code>


==Creating instances ChartFile==
==Creating instances ChartFile==
Even though the SOM compiler creates a C++ class, you can NOT use the "new" operator to create WPS objects. The following REXX program will create a ChartFile object in the Charts directory on drive d:. Alternatively, WinCreateObject can be used to create new ChartFile objects.
Even though the SOM compiler creates a C++ class, you can NOT use the "new" operator to create WPS objects. The following REXX program will create a ChartFile object in the Charts directory on drive d:. Alternatively, WinCreateObject can be used to create new ChartFile objects.
 
<code>
<small><nowiki>
   /* REXX: Create */
   /* REXX: Create */
   
   
Line 426: Line 396:
   
   
   Exit;
   Exit;
</nowiki></small>
</code>


==Deregistering ChartFile==
==Deregistering ChartFile==
The following REXX program will deregister the ChartFile class:
The following REXX program will deregister the ChartFile class:
 
<code>
<small>
   /* REXX: Deregister */
   /* REXX: Deregister */
   
   
Line 446: Line 414:
   
   
   Exit;
   Exit;
</small>
</code>


==Debugging a WPS DLL==
==Debugging a WPS DLL==
Be sure to read the following section in the Workplace Shell Programming Guide that comes with the OS/2 toolkit:
Be sure to read the following section in the Workplace Shell Programming Guide that comes with the OS/2 toolkit:
 
* Using Workplace Shell Debugging Techniques
* Using Workplace Shell Debugging Techniques [http://cyberkinetica.homeunix.net/os2tk45/wpsguide/]
 
This is a subsection of the main section:
This is a subsection of the main section:
 
* Debugging Workplace Shell Applications
* Debugging Workplace Shell Applications [http://cyberkinetica.homeunix.net/os2tk45/wpsguide/]
 
This information is VERY useful. It shows how to bring up OS/2 with an OS/2 window instead of the WPS. It also shows how to start, stop, and, debug the WPS. Since a DLL can not be debugged directly, the programmer must debug PMSHELL.EXE (the WPS) and set a "Load" break point for the DLL in question.
This information is VERY useful. It shows how to bring up OS/2 with an OS/2 window instead of the WPS. It also shows how to start, stop, and, debug the WPS. Since a DLL can not be debugged directly, the programmer must debug PMSHELL.EXE (the WPS) and set a "Load" break point for the DLL in question.


[[Category:SOM Articles]]
[[Category:SOM Articles]]

Latest revision as of 15:22, 24 August 2022

Work Place Shell Programming
Part: 1 / 2 / 3 / 4

Written by Chris Palchak

Purpose

The purpose of this series of articles is to teach the reader how to integrate an application with the OS/2 Work Place Shell. As this writer always looks for ways to avoid using API calls, the settings pages are written in C++ using the IBM Visual Age for C++ compiler and Open Class Library. Hopefully, those readers who are unfamiliar with C++ will be inspired to learn the language once they see the brevity of the settings page programs.

Overview

There are two parts to a Work Place Shell (WPS) program. The first is a System Object Model (SOM) Interface Definition Language (IDL) source file. The second part, is the code you write in C, C++, or some other supported language. This first article will show the reader how to:

  • Create the SOM IDL module,
  • Compile the IDL code,
  • Make the C++ DLL,
  • Register the new WPS class,
  • Create objects of the new class

The second article in this series will show the reader the code that needs to be added to the generated C++ program.

The third article in this series will show the reader how to access this class from another C++ program.

The fourth article in this series will cover a second WPS class.

SOM IDL

IBM's SOM is the basis for all WPS objects. To create custom WPS objects, you must use the SOM IDL. This may seem intimidating at first, but note that there are only two categories of statements in the SOM IDL:

  1. Attribute (or data) definition statements
  2. Interface (function) declaration statements

Once these statements are prepared, you simply generate stub program files and fill in the functions with your own code. For the purposes of this article, the generated stub files will be C++ programs. The following command will read a SOM IDL file and generate a stub C++ program along with the necessary header files:

sc.exe -s"xc;xh;xih;def" -S128000 chfile.idl.

In this case, chfile.idl is the SOM IDL file. The class described in this file is ChartFile. This is a class that inherits from WPDataFile and contains stock quotes. This is the first of two WPS classes that will be developed over the course of these articles. The other class that will be developed is ChartFolder. ChartFolder inherits from WPFolder and is used to store ChartFile objects.

ChFile.idl listing:

  #ifndef CHFILE_IDL
  #define CHFILE_IDL
  #include <wpdataf.idl>
  interface M_ChartFile;

  interface ChartFile : WPDataFile
  {
     #ifdef __SOMIDL__

     // Access methods for ChartFile's data

        void   setStockSymbol(in string s);
        void   setExchange(in string s);
        void   setLastDD(in short dd);
        void   setLastMM(in short mm);
        void   setLastYYYY(in short yyyy);
        void   setReversalBoxes(in short boxes);
        void   setBoxSize(in float bSize);
        void   setDaysInLongAvg(in short nDays);
        void   setDaysInShortAvg(in short nDays);
        void   setBarDataSaved(in short trueFalse);
        void   setPfDataSaved(in short trueFalse);
        void   setStockDataSaved(in short trueFalse);

        string getStockSymbol();
        string getExchange();
        short  getLastDD();
        short  getLastMM();
        short  getLastYYYY();
        short  getReversalBoxes();
        float  getBoxSize();
        short  getDaysInLongAvg();
        short  getDaysInShortAvg();

     // indicators: 0 = not saved, 1 = saved

        short  getBarDataSaved();
        short  getPfDataSaved();
        short  getStockDataSaved();

     //------------------------------------------------------
     // This method that reallocates memory for ChartFile's
     // strings is necessary because string is defined as
     // "char *" in \ibmcpp\include\som\somcorba.h.
     //------------------------------------------------------

        string reallocateString(in string oldString,
                                in string newValue);

        implementation
        {
            externalstem   = ChFile;
            local;
            externalprefix = ChFileX_;
            majorversion   = 1;
            minorversion   = 1;
            filestem       = ChFile;
            metaclass      = M_ChartFile;

      //-----------------------------------------------------
      // Class method (function) overrides
      //-----------------------------------------------------
      // add my settings pages
            wpAddSettingsPages: override;

      // restore state when object is awaken
            wpRestoreState:     override;

      // save state during shut down or idle times
            wpSaveState:        override;

      // called when object is created
            wpSetup:            override;

      // called when object is opened
            wpOpen:             override;

      // allocate memory for this object
            wpInitData:         override;

      // free allocated memory
            wpUnInitData:       override;

      // add my items to the pop-up menu
            wpModifyPopupMenu:  override;

      // process user selection of my menu items
            wpMenuItemSelected: override;

      //-----------------------------------------------------
      // Instance data (Exists separately for each
      // ChartFile object). These are NOT declared with the
      // SOM IDL "attribute" statement so that the get
      // and set functions can be named manually.
      //-----------------------------------------------------

      //  Stock Settings Page

            string stockSymbol;
            string exchange;
            short  lastDD;
            short  lastMM;
            short  lastYYYY;

       // Point & Figure settings

            short  reversalBoxes;
            float  boxSize;

       // Bar Chart settings page

            short  daysInLongAvg;
            short  daysInShortAvg;

       // State Indicators 0 = not saved, 1 = saved

            short  barDataSaved;
            short  pfDataSaved;
            short  stockDataSaved;

      //-----------------------------------------------------
      // Passthru Statements:
      // These statements are passed without change to the
      // generated "chfile.xih" and "chfile.xh" files.
      //-----------------------------------------------------

      // These statements get written to ChFile.xih.
      // ChFile.xih is included in ChFile.cpp.

          passthru C_xih_before =  ""
         " /* PM and OS2 include directives */"
         "   #define INCL_WINWORKPLACE"
         "   #define INCL_WIN"
         "   #include <os2.h>"
         ""
         " /* WPS include directives */"
         "   #define INCL_WPCLASS"
         "   #define INCL_WPObject"
         "   #include <pmwp.h>"
         ""
         " /* C include directives */"
         "   #include <stdio.h>"
         "";

      // These statements get written to ChFile.xh.
      // ChFile.xh is included in C++ programs that
      // reference ChartFile objects.

          passthru C_xh_before =  ""
         " /* PM and OS2 include directives */"
         "   #define INCL_WINWORKPLACE"
         "   #define INCL_WIN"
         "   #include <os2.h>"
         ""
         " /* WPS include directives */"
         "   #define INCL_WPCLASS"
         "   #define INCL_WPObject"
         "   #include <pmwp.h>"
         ""
         " /* C include directives */"
         "   #include <stdio.h>"
         "";
        };

     #endif
  };

  //---------------------------------------------------------
  // Metaclass section:
  // ------------------
  // Describe the metaclass of ChartFile. The Meta Class
  // defines data that is common (global) to all ChartFile
  // objects. It also defines functions that operate on Meta
  // Class Data.
  //---------------------------------------------------------

  interface M_ChartFile

  // Comment for parent WPDataFile:

  {
    //
    // No new class methods
    //

  #ifdef __SOMIDL__
      implementation
      {
    // Class Modifiers
         externalstem = ChFile;
         local;
         externalprefix = ChFileX_;
         functionprefix = ChFileC_;
         majorversion = 1;
         minorversion = 1;
         filestem = ChFile;

    // non-instance (global) data

         unsigned long hChartFileIcon; // Object's icon handle


    // Class method Modifiers

    // allocate required memory
         wpclsInitData:         override;

    // free allocated memory
         wpclsUnInitData:       override;

    // must override to make icon stick
         wpclsQueryIcon:        override;

    // define the double-click view
         wpclsQueryDefaultView: override;
      };

  #endif /* __SOMIDL__ */

  };

  #endif

Building the DLL

The Module Definition File

The following file is generated by the SOM compiler. This file must be modified to include the custom functions declared for setting and getting ChartFile's data.

ChFile.def Listing

  ;  This file was generated by the SOM Compiler.
  ;  FileName: ChFile.def.
  ;  Generated using:
  ;      SOM Precompiler somipc: 2.29.1.7
  ;      SOM Emitter emitdef: 2.42
  LIBRARY ChFile INITINSTANCE
  DESCRIPTION 'ChartFile Class Library'
  PROTMODE
  DATA MULTIPLE NONSHARED LOADONCALL
  EXPORTS
     ChartFileCClassData
     ChartFileClassData
     ChartFileNewClass
     M_ChartFileCClassData
     M_ChartFileClassData
     M_ChartFileNewClass

This is the modified module definition file. Note that there is no need to use mangled function names for this DLL because the exported functions are not really C++ class members. This file has been named Export.def so that it does not get overlaid when a new ChFile.def gets generated.

Export.def Listing

  LIBRARY ChFile INITINSTANCE
  DESCRIPTION 'ChartFile Class Library'
  PROTMODE
  DATA MULTIPLE NONSHARED LOADONCALL
  EXPORTS
      ChartFileCClassData           @1
      ChartFileClassData            @2
      ChartFileNewClass             @3
      M_ChartFileCClassData         @4
      M_ChartFileClassData          @5
      M_ChartFileNewClass           @6
      ChFileX_setBoxSize            @7
      ChFileX_getBoxSize            @8
      ChFileX_getLastYYYY           @9
      ChFileX_setStockSymbol        @10
      ChFileX_setLastYYYY           @11
      ChFileX_setLastMM             @12
      ChFileX_setDaysInShortAvg     @13
      ChFileX_getReversalBoxes      @14
      ChFileX_setReversalBoxes      @15
      ChFileX_setExchange           @16
      ChFileX_setDaysInLongAvg      @17
      ChFileX_getLastDD             @18
      ChFileX_getExchange           @19
      ChFileX_getDaysInLongAvg      @20
      ChFileX_getLastMM             @21
      ChFileX_getStockSymbol        @22
      ChFileX_getDaysInShortAvg     @23
      ChFileX_setLastDD             @24

ChFile.mak Listing

  # ChFile.mak
  # Created by IBM WorkFrame/2 MakeMake at 21:59:45 on
  # 13 May 1997
  #
  # The actions included in this make file are:
  #  Compile::SOM Compiler
  #  Compile::C++ Compiler
  #  Lib::Import Lib (from def)
  #  Link::Linker
  #

  .SUFFIXES: .IDL .cpp .obj .rc .res .def

  .all: \
      .\ChFile.LIB \
      .\ChFile.dll

  .IDL.cpp:
      @echo " Compile::SOM Compiler "
      sc.exe -s"xc;xh;xih;def" -S128000 %s

  .cpp.obj:
      @echo " Compile::C++ Compiler "
      icc.exe /Ti /Gm /Gd /Ge- /C %s

  .\ChFile.LIB: \
      .\Export.def
      @echo " Lib::Import Lib (from def) "
      implib.exe ChFile.LIB export.def

  .\ChFile.dll: \
      .\ChFile.obj \
      .\Export.def \
      {$(LIB)}somtk.lib
      @echo " Link::Linker "
      icc.exe @<<
       /B" /de /noe"
       /FeChFile.dll
       ChFile.obj
       somtk.lib
       Export.def
  <<

  .\ChFile.cpp: \
      d:\som\ChFile\ChFile.IDL

  .\ChFile.obj: \
      .\ChFile.cpp \
      {D:\som\ChFile;$(INCLUDE);}ChFile.xih \

Registering ChartFile

The following REXX program will register the ChartFile class:

  /* REXX: Register */

  Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs';
  Call SysLoadFuncs;

     rc=SysRegisterObjectClass('ChartFile','chfile');

     If rc <> 1
        Then Do;
  Say "ChartFile: could not register ChartFile, rc="rc ".";
          Exit;
          End;

  Exit;

Creating instances ChartFile

Even though the SOM compiler creates a C++ class, you can NOT use the "new" operator to create WPS objects. The following REXX program will create a ChartFile object in the Charts directory on drive d:. Alternatively, WinCreateObject can be used to create new ChartFile objects.

  /* REXX: Create */

  Call RxFuncAdd'SysLoadFuncs','REXXUTIL','SysLoadFuncs';
  Call SysLoadFuncs;

  rc=SysCreateObject('ChartFile','Mitchell Energy&Dev Cl A',
                     'D:\Charts',,'replace');

  Exit;

Deregistering ChartFile

The following REXX program will deregister the ChartFile class:

  /* REXX: Deregister */

  Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs';
  Call SysLoadFuncs;

       rc=SysDeregisterObjectClass('ChartFile');

       If rc <> 1
          Then Do;
            Say  "ChartFile: could not deregister";
            End;

  Exit;

Debugging a WPS DLL

Be sure to read the following section in the Workplace Shell Programming Guide that comes with the OS/2 toolkit:

  • Using Workplace Shell Debugging Techniques

This is a subsection of the main section:

  • Debugging Workplace Shell Applications

This information is VERY useful. It shows how to bring up OS/2 with an OS/2 window instead of the WPS. It also shows how to start, stop, and, debug the WPS. Since a DLL can not be debugged directly, the programmer must debug PMSHELL.EXE (the WPS) and set a "Load" break point for the DLL in question.