Work Place Shell Programming - Part 1
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:
- Attribute (or data) definition 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:
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.