Jump to content

Open Class Library (OCL) FAQ: Difference between revisions

From EDM2
Ak120 (talk | contribs)
 
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
By [[Stéphane Charette]]
''By [[Stéphane Charette]]''


=General Information=
==General Information==
==History of the Open Class Library FAQ==
===History of the Open Class Library FAQ===
The revision history is as follows:
The revision history is as follows:
 
{|class="wikitable"
{| border="1" cellpadding="5"
!Version||Comment||Author||Date
| align="center" | Version
| align="center" | Comment
| align="center" | Author
| align="center" | Date
|-
|-
| 0.1
|0.1
| initial write-up in OS/2's IPF (.INF) format
|initial write-up in OS/2's IPF (.INF) format
| SC
|SC
| 1997June20-21
|1997-06-21
|-
|-
| 0.1a
|0.1a
| added table of files at Hobbes
|added table of files at Hobbes
| SC
|SC
| 1997June24
|1997-06-24
|-
|-
| 0.1b
|0.1b
| converted the FAQ to HTML format
|converted the FAQ to HTML format
| SC
|SC
| 1997June28
|1997-06-28
|-
|-
| 0.1d
|0.1d
| Added animation sample<br /> Added LNK2029 information<br /> Updated fixpak information<br /> Created "Errors in IBM's include files"
|Added animation sample<br /> Added LNK2029 information<br /> Updated fixpak information<br /> Created "Errors in IBM's include files"
| SC
|SC
| 1997Sept05
|1997-09-05
|-
|-
| 0.1e
|0.1e
| Changed e-mail address<br /> Added POV_Launch to the Hobbes index<br /> Added custom-draw container information
|Changed e-mail address<br /> Added POV_Launch to the Hobbes index<br /> Added custom-draw container information
| SC
|SC
| 1997Nov02
|1997-11-02
|}
|}


==How to obtain a copy of the FAQ==
===How to obtain a copy of the FAQ===
To obtain a HTML copy of the FAQ for local installation, download the file ftp://hobbes.nmsu.edu/pub/os2/dev/cplusplus/ocl_faq.zip.
To obtain an HTML copy of the FAQ for local installation, download the file [ocl_faq.zip].
 
Unzip this file in it's own directory (if using PKUNZIP, remember to use the /D option to create the subdirectories) and use your favorite web browser to access the files locally.  


==Where to obtain additional information==
Unzip this file in its own directory (if using PKUNZIP, remember to use the /D option to create the subdirectories) and use your favourite web browser to access the files locally.


The on-line reference for OCL is located in your VisualAge folder, under the <code>VisualAge C++ Information</code> folder. The reference .INF file should be titled <code>Open Class Library Reference</code> (<code>D:\IBMCPP\HELP\CLREF.INF</code>) while a second .INF user's guide is called <code>Open Class Library User's Guide</code> (<code>D:\IBMCPP\HELP\CPPCLSUG.INF</code>).
===Where to obtain additional information===
The on-line reference for OCL is located in your VisualAge folder, under the ''VisualAge C++ Information'' folder. The reference .INF file should be titled ''Open Class Library Reference'' (<tt>\IBMCPP\HELP\CLREF.INF</tt>) while a second .INF user's guide is called ''Open Class Library User's Guide'' (<tt>\IBMCPP\HELP\CPPCLSUG.INF</tt>).


The first book, <code>Open Class Library Reference</code> has all of the documented methods, objects, and necessary include files. The easiest way to find what you need is probably to click on <code>Classes By Name</code>, normally the second option from the top (may depend on the version of the documentation).
The first book, ''Open Class Library Reference'' has all of the documented methods, objects, and necessary include files. The easiest way to find what you need is probably to click on ''Classes By Name'', normally the second option from the top (may depend on the version of the documentation).


Note that one of the most useful .INF books which IBM ships with VisualAge can easily be overlooked; in the <code>VisualAge C++ Information</code> folder is a book called <code>VisualAge C++ Frequently Asked Questions</code> which deals with quite a few OCL topics.
Note that one of the most useful .INF books which IBM ships with VisualAge can easily be overlooked; in the ''VisualAge C++ Information'' folder is a book called ''VisualAge C++ Frequently Asked Questions'' which deals with quite a few OCL topics.


Additional information on programming using OCL can be obtained from a variety of sources. There is an increase in books published (some of which by IBM) which deal with OCL, as well as numerous sources on the Internet.
Additional information on programming using OCL can be obtained from a variety of sources. There is an increase in books published (some of which by IBM) which deal with OCL, as well as numerous sources on the Internet.


For more information, consult:
For more information, consult:
* <code>D:\IBMCPP\SAMPLES\IOC\*</code>
* <code>D:\IBMCPP\SAMPLES\IOC\*</code>
* [http://hobbes.nmsu.edu/h-search.php?sh=1&button=Search&key=ocl&stype=all&sort=type_name&dir=%2Fpub%2Fos2%2Fdev%2Fcplusplus ocl*.zip] ''([hobbes_index.html index of samples])''
* [ocl*.zip] ''([hobbes_index.html index of samples])''
* ftp://service.boulder.ibm.com/ps/products/visualagecpp/tools ''(IBM VB and OCL sample code)''
* {{L-IBM|/ps/products/visualagecpp/tools}} ''(IBM VB and OCL sample code)''
* http://??? ''(Chinese version of the OCL-FAQ)''
* ''(Chinese version of the OCL-FAQ)''
* http://www.davebsoft.com/Programming/tips ''([[Dave Briccetti]]'s OS/2 Warp Programming Tips and Samples)''
* http://www.davebsoft.com/Programming/tips ''([[Dave Briccetti]]'s OS/2 Warp Programming Tips and Samples)''
* news://comp.os.os2.programmer.oop
* news://comp.os.os2.programmer.oop
Line 64: Line 58:
Books which deal with OCL are:
Books which deal with OCL are:


; OS/2 Class Library: Power GUI programming with C/Set++
;OS/2 Class Library: Power GUI Programming with C/Set++
: Written by Leon, Law, Love Tsuji & Olson<br /> Published by John Wiley & Sons<br /> ISBN 0-471-13117-2<br />''(Obsolete and replaced by the following book)''
:Written by Leon, Law, Love Tsuji & Olson
; Power GUI Programming with VisualAge C++
:Published by John Wiley & Sons
: Written by Law, Love, Olson & Tsuji<br /> Published by John Wiley & Sons<br /> ISBN 0-471-16482-8<br />''(recommended by Mark Anderson, os2team@romeop03.fishkill.ibm.com)''
:ISBN 0-471-13117-2
 
:''(Obsolete and replaced by the following book)''
;Power GUI Programming with VisualAge C++
:Written by Law, Love, Olson & Tsuji
:Published by John Wiley & Sons
:ISBN 0-471-16482-8
:''(recommended by Mark Anderson, os2team@romeop03.fishkill.ibm.com)''


===Index of samples on Hobbes===
===Index of samples on Hobbes===
 
Starting mid-June, 1997, I have begun to upload to ftp://hobbes.nmsu.edu/pub/os2/dev/cplusplus a series of Open Class Library samples that I have written. The following table is the index of these samples.
tarting mid-June, 1997, I have begun to upload to <code>ftp://hobbes.nmsu.edu/pub/os2/dev/cplusplus</code> a series of Open Class Library samples that I have written. The following table is the index of these samples.
{|class="wikitable"
 
!Filename||Description||Classes Used
{| border="1" cellpadding="5"
! Filename
! Description
! Classes Used
|-
|-
|
|OCL_ANI1.ZIP
[http://hobbes.nmsu.edu/h-search.php?key=ocl_ani1.zip OCL_ANI1.ZIP]
|animation sample
| animation sample
|IApplication, IColor, IDrawingCanvas, IEvent, IFrameWindow, IGBitmap, IGList, IRectangle, ITimer
| IApplication, IColor, IDrawingCanvas, IEvent, IFrameWindow, IGBitmap, IGList, IRectangle, ITimer
|-
|-
|
|OCL_CON1.ZIP
[http://hobbes.nmsu.edu/h-search.php?key=ocl_con1.zip OCL_CON1.ZIP]
|details view container sample
| details view container sample
|IApplication, IContainerColumn, IContainerControl, IContainerObject, IFrameWindow, IString
| IApplication, IContainerColumn, IContainerControl, IContainerObject, IFrameWindow, IString
|-
|-
|
|OCL_THR1.ZIP
[http://hobbes.nmsu.edu/h-search.php?key=ocl_thr1.zip OCL_THR1.ZIP]
|thread and timer sample (minimized icon fix explained)
| thread and timer sample (minimized icon fix explained)
|IApplication, ICommandEvent, ICommandHandler, IFrameWindow, IListBox, IPushButton, IString, ISystemMenu, IThread, IThreadFn, ITimer
| IApplication, ICommandEvent, ICommandHandler, IFrameWindow, IListBox, IPushButton, IString, ISystemMenu, IThread, IThreadFn, ITimer
|-
|-
|
|OCL_ANI2.ZIP
[http://hobbes.nmsu.edu/h-search.php?key=ocl_ani2.zip OCL_ANI2.ZIP]
|animation sample #2
| animation sample #2
|IApplication, ICommandEvent, ICommandHandler, IColor, IControlEvent, IDrawingCanvas, IFrameWindow, IFrameEvent, IFrameHandler, IGBitmap, IGList, IGraphicContext, IMouseClickEvent, IMouseHandler, IPopUpMenu, ITimerMemberFn0
| IApplication, ICommandEvent, ICommandHandler, IColor, IControlEvent, IDrawingCanvas, IFrameWindow, IFrameEvent, IFrameHandler, IGBitmap, IGList, IGraphicContext, IMouseClickEvent, IMouseHandler, IPopUpMenu, ITimerMemberFn0
|-
|-
|
|OCL_CON2.ZIP
[http://hobbes.nmsu.edu/h-search.php?key=ocl_con2.zip OCL_CON2.ZIP]
|custom drawing in a details-view container
| custom drawing in a details-view container
|IApplication, ICnrDrawHandler, IContainerColumn, IContainerControl, IContainerObject, IFrameWindow
| IApplication, ICnrDrawHandler, IContainerColumn, IContainerControl, IContainerObject, IFrameWindow
|-
|-
|
|PLNCH01G.ZIP
[http://hobbes.nmsu.edu/h-search.php?key=plnch01g.zip PLNCH01G.ZIP]
|POV front-end
| POV front-end
|Some of almost all classes available, including threads, canvases, icons, bitmaps, standard controls, profiles and exceptions.
| Some of almost all classes available, including threads, canvases, icons, bitmaps, standard controls, profiles and exceptions.
|}
|}


; Note:
;Note:See also [[#Where to Obtain Additional Information]]
: See also [[#Where to Obtain Additional Information]]
 
=OCL - Compiling=


==How to Compile==
==OCL - Compiling==
===How to Compile===
If you wish to correctly compile your OCL application, then the following should be used:
If you wish to correctly compile your OCL application, then the following should be used:
 
*if you are using the project templates and WorkFrame that come with Visual Age, then
* if you are using the project templates and WorkFrame that come with Visual Age, then
*# click on <code>Tools</code>
*# click on <code>Tools</code>
*# make certain that <code>View</code> is set to <code>Actions</code>
*# make certain that <code>View</code> is set to <code>Actions</code>
Line 132: Line 118:
*# use the command <code>icc.exe /Gm+ /C ''<other optional compiler flags>'' myfile.cpp</code>
*# use the command <code>icc.exe /Gm+ /C ''<other optional compiler flags>'' myfile.cpp</code>


; Note:
;Note: See also [[#/Gm+]], [[#How to Link]], [[#Static Linking]] and [[#Dynamic Linking]]
: See also [[#/Gm+]], [[#How to Link]], [[#Static Linking]] and [[#Dynamic Linking]]


==Required compiler flag==
===Required compiler flag===
There is one flag that absolutely must be specified when compiling source code which uses OCL calls. This flag is described as follows in the on-line help:
There is one flag that absolutely must be specified when compiling source code which uses OCL calls. This flag is described as follows in the on-line help:
;/Gm+
:Link with multithread runtime libraries.


/Gm+
The default for ICC is to use /Gm- (no support for the multithreaded libraries) so the /Gm+ flag must be specified. Typical compiler behaviour when this flag is not specified is:
    Link with multithread runtime libraries.
  D:\IBMCPP\INCLUDE\ibase.hpp(226:3) : error EDC3086:
 
  Error: Use of IBM Open Class Library requires the /Gm+ compiler option.
The default for ICC is to use /Gm- (no support for the multithreaded libraries) so the /Gm+ flag must be specified. Typical compiler behavior when this flag is not specified is:
  D:\IBMCPP\INCLUDE\ibase.hpp(227:3) : error EDC3086:
 
  D:\IBMCPP\INCLUDE\ibase.hpp(226:3) : error EDC3086:  
  Error: Use of IBM Open Class Library requires the /Gm+ compiler option.  
  D:\IBMCPP\INCLUDE\ibase.hpp(227:3) : error EDC3086:  
  Check the makefile (or its profile) for a missing /Gm+ option.
  Check the makefile (or its profile) for a missing /Gm+ option.
Note: See also [[#How to Compile]] and [[#Error EDC3086]]
Note: See also [[#How to Compile]] and [[#Error EDC3086]]


==Errors in IBM's include files==
===Errors in IBM's include files===
If your source code has the extension .c and you are including some OCL #includes, then the compiler may generate many errors which seem to come from the IBMCPP include files. These errors are generated because the compiler assumes that .c files only contain C code, not C++, and the OCL include files require the compiler to be in the C++ mode.
If your source code has the extension .c and you are including some OCL #includes, then the compiler may generate many errors which seem to come from the IBMCPP include files. These errors are generated because the compiler assumes that .c files only contain C code, not C++, and the OCL include files require the compiler to be in the C++ mode.


Line 161: Line 143:
  imsgtext.hpp(28:33) : error EDC0045: Undeclared identifier messageFileName.  
  imsgtext.hpp(28:33) : error EDC0045: Undeclared identifier messageFileName.  
  imsgtext.hpp(29:33) : error EDC0045: Undeclared identifier textInsert1.
  imsgtext.hpp(29:33) : error EDC0045: Undeclared identifier textInsert1.
;Note:See also [[#How to Compile]]


; Note:
==OCL - Linking==
:See also [[#How to Compile]]
===How to Link===
 
=OCL - Linking=
==How to link==
The recommended method of linking when some or all of the object files have references to OCL function calls is to use ICC, and not LINK386, ILINK, etc.
The recommended method of linking when some or all of the object files have references to OCL function calls is to use ICC, and not LINK386, ILINK, etc.


To link an object file (.OBJ) which makes use of OCL, the following should be used:
To link an object file (.OBJ) which makes use of OCL, the following should be used:
* if you are using the project templates and WorkFrame that come with VisualAge C++, then
* if you are using the project templates and WorkFrame that come with VisualAge C++, then
*# click on <code>Tools</code>
*# click on <code>Tools</code>
Line 195: Line 174:
: See also [[#How to Compile]], [[#Static Linking]] and [[#Dynamic Linking]]
: See also [[#How to Compile]], [[#Static Linking]] and [[#Dynamic Linking]]


==Static linking==
===Static linking===
Static linking will combine the IBM Open Class Library files with your object files to create a stand-alone application. This means that you are not required to have a copy of the <code>X:\IBMCPP\DLL\DDE4*.DLL</code> files on your system in order to run the application.
Static linking will combine the IBM Open Class Library files with your object files to create a stand-alone application. This means that you are not required to have a copy of the <code>X:\IBMCPP\DLL\DDE4*.DLL</code> files on your system in order to run the application.


Line 216: Line 195:
*# make certain that the <code>/Gd-</code> option is specified
*# make certain that the <code>/Gd-</code> option is specified


; Note:
;Note: See also [[#Dynamic Linking]] and [[#How to Link]]
: See also [dynamic_linking.html Dynamic Linking] and [how_to_link.html How to Link]<font color="#ff0000"> </font>
;Note: Need info on rights, etc...are you allowed to distribute an application that was statically linked? Isn't there something in the docs? I haven't had the time to look it up yet - if someone has references handy, please let me know.
; Note:
: Need info on rights, etc...are you allowed to distribute an application that was statically linked? Isn't there something in the docs? I haven't had the time to look it up yet -- if someone has references handy, please let me know.
 


==Dynamic linking==
===Dynamic Linking===
Dynamic linking will setup your application to call the necessary OCL functions dynamically using DLLs. This assumes that the required DLL files are already referenced somewhere in LIBPATH before the application will run.
Dynamic linking will setup your application to call the necessary OCL functions dynamically using DLLs. This assumes that the required DLL files are already referenced somewhere in LIBPATH before the application will run.


Line 243: Line 219:
*# make certain that the /Gd+ option is specified.
*# make certain that the /Gd+ option is specified.


; Note:
;Note: See also [static_linking.html Static Linking] and [how_to_link.html How to Link]
: See also [static_linking.html Static Linking] and [how_to_link.html How to Link]<font color="#ff0000"> </font>
;Note: Need info on rights, etc...are you allowed to distribute the DLLs with an application that was dynamically linked? Isn't there something in the docs? I haven't had the time to look it up yet - if someone has references handy, please let me know.
; Note:
: Need info on rights, etc...are you allowed to distribute the DLLs with an application that was dynamically linked? Isn't there something in the docs? I haven't had the time to look it up yet -- if someone has references handy, please let me know.
 
=OCL - Miscellaneous=


==Application dies when starting==
==OCL - Miscellaneous==
===Application dies when starting===
If your application compiles and links without problems, but it then dies during startup (you may or may not see the frame window start to come up) then check for the following common mistakes:
If your application compiles and links without problems, but it then dies during startup (you may or may not see the frame window start to come up) then check for the following common mistakes:
* is more than one resource using the same number in your .RC or .DLG file?
* is more than one resource using the same number in your .RC or .DLG file?
* are you trying to allocate/create a resouce in your .CPP file -- say an IPushButton -- when in reality it has been defined as something else in your .RC or .DLG file?
* are you trying to allocate/create a resource in your .CPP file - say an IPushButton - when in reality it has been defined as something else in your .RC or .DLG file?
* Bill Law (law@netscape.com) also says: The most common occurrence is that your app is throwing an (uncaught) exception during construction of the first (frame) window. This terminates silently, unless you take steps to capture the exception information. To do that, follow the instructions provided in the on-line VACPP FAQ (in the section "Coding With User Interface Classes"->"Exceptions"->"Why Does My Program Just Exit").
* Bill Law (law@netscape.com) also says: The most common occurrence is that your app is throwing an (uncaught) exception during construction of the first (frame) window. This terminates silently, unless you take steps to capture the exception information. To do that, follow the instructions provided in the on-line VACPP FAQ (in the section "Coding With User Interface Classes"->"Exceptions"->"Why Does My Program Just Exit").


Line 260: Line 232:
* did you specify the type of application when linking? If the application is compiled with the default value of <code>/pmtype:vio</code> then your window will not come up. Make certain you use <code>/pmtype:pm</code> from the linker, or <code>/B" /pmtype:pm"</code> when linking directly from the compiler.
* did you specify the type of application when linking? If the application is compiled with the default value of <code>/pmtype:vio</code> then your window will not come up. Make certain you use <code>/pmtype:pm</code> from the linker, or <code>/B" /pmtype:pm"</code> when linking directly from the compiler.


==Application-modal windows==
===Application-modal windows===
To create an application modal dialog window, the parent and the owner of the window being created must be different. The parent should be the desktop window handle, while the owner should be the calling dialog window's handle. For example:
To create an application modal dialog window, the parent and the owner of the window being created must be different. The parent should be the desktop window handle, while the owner should be the calling dialog window's handle. For example:
  IFrameWindow *anotherDlg =  
  IFrameWindow *anotherDlg =  
  new IFrameWindow( MY_RES_ID,        /* resource id of new window */  
  new IFrameWindow( MY_RES_ID,        /* resource id of new window */  
Line 269: Line 240:
  anotherDlg->showModally();
  anotherDlg->showModally();


 
===System-modal windows===
 
==System-modal windows==
 
(Nothing here yet...feel free to submit something)
(Nothing here yet...feel free to submit something)


==How to convert a native PM item to OCL==
===How to convert a native PM item to OCL===
 
Most native PM windows have an equivalent in OCL, and an item that already exists on a window can at any time be "converted" to OCL. This is advantageous for example if some of the functionality you need has already been implemented using OCL. For example:
Most native PM windows have an equivalent in OCL, and an item that already exists on a window can at any time be "converted" to OCL. This is advantageous for example if some of the functionality you need has already been implemented using OCL. For example:
  > Can a pointer to a 'low-level' listbox be converted into a pointer to an
  > Can a pointer to a 'low-level' listbox be converted into a pointer to an
  > Open Class listbox?
  > Open Class listbox?
Line 286: Line 252:
Most of the OC UI controls have a constructor that takes the HWND of an
Most of the OC UI controls have a constructor that takes the HWND of an
existing control.  In this case, the constructor looks like
existing control.  In this case, the constructor looks like
  IListBox (const IWindowHandle &)
  IListBox (const IWindowHandle &)
   
   
  IWindowHandle is an "alias" for HWND.
  IWindowHandle is an "alias" for HWND.


[[Bill Law]] (law@netscape.com) also adds the following:
Bill Law (law@netscape.com) also adds the following:


Perhaps you should add that if an OCL window already exists for a given HWND, then constructing another one from its HWND will result in an exception being thrown.  Generally, if there is a chance that an existing OCL window exists (or you know that one does and you just want to locate it), then you can use IWindow::fromHandle to get the existing IWindow (or derived-class) object.  If that returns 0, then you can safely construct another IWindow (or derived-class) object.
Perhaps you should add that if an OCL window already exists for a given HWND, then constructing another one from its HWND will result in an exception being thrown.  Generally, if there is a chance that an existing OCL window exists (or you know that one does and you just want to locate it), then you can use IWindow::fromHandle to get the existing IWindow (or derived-class) object.  If that returns 0, then you can safely construct another IWindow (or derived-class) object.


==How to create a thread==
===How to create a thread===
There are different ways of creating threads using OCL, and the method chosen will often depend on what you want the thread to do.
There are different ways of creating threads using OCL, and the method chosen will often depend on what you want the thread to do.


Example of creating a thread to call an object method:
Example of creating a thread to call an object method:
 
MyDlgClass     *frame            = new MyDlgClass();
  MyDlgClass       *frame            = new MyDlgClass();
IThreadMemberFn *myThreadMemberFn = new IThreadMemberFn<MyDlgClass>(frame, MyDlgClass::doSomething));
  IThreadMemberFn   *myThreadMemberFn = new IThreadMemberFn<MyDlgClass>(frame, MyDlgClass::doSomething) );
IThread         *myThread        = new IThread(myThreadMemberFn);
  IThread           *myThread        = new IThread( myThreadMemberFn );


Example of creating a thread to call an entire class:
Example of creating a thread to call an entire class:
class MyThreadClass : public IThreadFn
...
int main()
{
    ...
    MyThreadClass  *myThreadFn = new MyThreadClass();
    IThread        *myThread  = new IThread( myThreadFn );


  class MyThreadClass : public IThreadFn
; Warning: When using IThreadFn as opposed to IThreadMemberFn, the class being created must inherit from IThreadFn, and must contain the method <code>run()</code>
  ...
; Note: See also [[#Index of Samples on Hobbes]]
  int main()
  {
      ...
      MyThreadClass  *myThreadFn = new MyThreadClass();
      IThread        *myThread  = new IThread( myThreadFn );
 
; Warning:
: When using IThreadFn as opposed to IThreadMemberFn, the class being created must inherit from IThreadFn, and must contain the method <code>run()</code>
; Note:
: See also [[#Index of Samples on Hobbes]]


==How to assign an icon to a window==
===How to assign an icon to a window===
In the .RC file, you must assign an icon to the same resource ID that the dialog window is using in the .DLG file, and then load it when you create the window. This is done as follows:
In the .RC file, you must assign an icon to the same resource ID that the dialog window is using in the .DLG file, and then load it when you create the window. This is done as follows:


In your .H file, you would have:
In your .H file, you would have:
   #define MY_DIALOG_RCID 0x1000
   #define MY_DIALOG_RCID 0x1000


In your .RC file, you would have:
In your .RC file, you would have:
   ICON MY_DIALOG_RCID myicon.ico
   ICON MY_DIALOG_RCID myicon.ico


In your .DLG file, you would have:
In your .DLG file, you would have:
   DLGTEMPLATE MY_DIALOG_RCID PRELOAD MOVEABLE DISCARDABLE
   DLGTEMPLATE MY_DIALOG_RCID PRELOAD MOVEABLE DISCARDABLE
   BEGIN
   BEGIN
Line 337: Line 295:


In your .CPP file, you would have:
In your .CPP file, you would have:
   IFrameWindow *myDlg = new IFrameWindow( MY_DIALOG_RCID );  // create the window
   IFrameWindow *myDlg = new IFrameWindow( MY_DIALOG_RCID );  // create the window
   myDlg->setIcon( MY_DIALOG_RCID );                          // set the icon
   myDlg->setIcon( MY_DIALOG_RCID );                          // set the icon
Line 344: Line 301:
: See also [[#How to Prevent the Minimized Icon From Being Overwritten]]
: See also [[#How to Prevent the Minimized Icon From Being Overwritten]]


==How to prevent the minimized icon from being overwritten==
===How to prevent the minimized icon from being overwritten===
If your dialog window contains or consists of a canvas, then when you minimize the window, the icon which is being used (<code>IFrameWindow::setIcon()</code>) will be drawn correctly on the screen. However, if you have some controls which are not on a canvas, then you will run into a problem where the minimized icon is being overwritten by some of your controls.
If your dialog window contains or consists of a canvas, then when you minimize the window, the icon which is being used (<code>IFrameWindow::setIcon()</code>) will be drawn correctly on the screen. However, if you have some controls which are not on a canvas, then you will run into a problem where the minimized icon is being overwritten by some of your controls.


This is a common problem -- I believe with native PM applications as well -- that can very easily be fixed.
This is a common problem - I believe with native PM applications as well - that can very easily be fixed.


In your application, you will need to create a command handler for your window to capture all of the system commands. This can be done by inheriting from <code>ICommandHandler</code>, and declaring the function <code>Boolean systemCommand( ICommandEvent &event );</code>. Then when you detect the <code>ISystemMenu::idMinimize</code> event, you need to <code>hide()</code> the offending controls. Likewise, when you detect the <code>ISystemMenu::idRestore</code> event, you need to <code>show()</code> the controls that have previously been hidden.
In your application, you will need to create a command handler for your window to capture all of the system commands. This can be done by inheriting from <code>ICommandHandler</code>, and declaring the function <code>Boolean systemCommand( ICommandEvent &event );</code>. Then when you detect the <code>ISystemMenu::idMinimize</code> event, you need to <code>hide()</code> the offending controls. Likewise, when you detect the <code>ISystemMenu::idRestore</code> event, you need to <code>show()</code> the controls that have previously been hidden.
Line 385: Line 342:
}
}
</PRE>
</PRE>
; Note:
;Note: See also [[#How to Assign an Icon to a Window]] and [[#Index of Samples on Hobbes]]
: See also [[#How to Assign an Icon to a Window]] and [[#Index of Samples on Hobbes]]


==How to print==
===How to print===
Support for printing using OCL calls has not yet been included. IBM has promised that this will be included "soon", but no date has been given.
Support for printing using OCL calls has not yet been included. IBM has promised that this will be included "soon", but no date has been given.


For now, you may want to refer to the <code>OS/2 Programming FAQ</code> for more information on traditionnal printing in OS/2. This FAQ can be found at <font color="#ff0000">anyone know where?</font>.
For now, you may want to refer to the <code>OS/2 Programming FAQ</code> for more information on traditional printing in OS/2. This FAQ can be found at ''anyone know where?''.


==Valuesets (WC_VALUESET)==
===Valuesets (WC_VALUESET)===
It seems that valuesets are not directly supported in OCL. You can still create them in DLGEDIT.EXE, and access them with OCL code, but with some limitations.
It seems that valuesets are not directly supported in OCL. You can still create them in DLGEDIT.EXE, and access them with OCL code, but with some limitations.


In your code, you can use the following:
In your code, you can use the following:
  IWindow *vs = new IWindow( MY_VALUESET_RCID, this );
  IWindow *vs = new IWindow( MY_VALUESET_RCID, this );


Thus, you can then change all of the standard window attributes using OCL calls, but all of the valueset-specific information will have to be handled using standard PM programming.
Thus, you can then change all of the standard window attributes using OCL calls, but all of the valueset-specific information will have to be handled using standard PM programming.
   
   
==Custom-drawing in a container==
===Custom-drawing in a container===
To draw your own items in a container (IContainerControl) you will need to make use of the ICnrDrawHandler class. For an example of how this can be done in a details-view container (same principal can be applied to other views) please see the OCL_CON2.ZIP example from Hobbes.
To draw your own items in a container (IContainerControl) you will need to make use of the ICnrDrawHandler class. For an example of how this can be done in a details-view container (same principal can be applied to other views) please see the OCL_CON2.ZIP example from Hobbes.


; Note:
; Note:
: See also [[#Index of Samples on Hobbes]]
: See also [[#Index of Samples on Hobbes]]


=OCL - Errors=
==OCL - Errors==
 
===Error EDC3086===
==Error EDC3086==
The error EDC3086 is caused by the compiler detecting OCL calls in a source file which was not compiled with the /Gm+ parameter.
The error EDC3086 is caused by the compiler detecting OCL calls in a source file which was not compiled with the /Gm+ parameter.


Line 418: Line 372:
: See also [[#How to Compile and Required Compiler Flag]]
: See also [[#How to Compile and Required Compiler Flag]]


==Error LNK2029==
===Error LNK2029===
The error LNK2029 is caused by the linker when you have OCL calls in your source, but you didn't compile with the <code>/Gm+</code> parameter. The error may look as follows:
The error LNK2029 is caused by the linker when you have OCL calls in your source, but you didn't compile with the <code>/Gm+</code> parameter. The error may look as follows:
CPPOOC3.LIB (iexcept.cpp) : error LNK2029: "_errno" : unresolved external


CPPOOC3.LIB (iexcept.cpp) : error LNK2029: "_errno" : unresolved external
Charlie Choc (cchoc@mindspring.com) says:
 
:Make sure you are compiling with the Gm+ option, the Open Class Library requires the multi-threaded otpion.  In a multi-thread environment _errno is a function, in a single thread environment it is an int.
[[Charlie Choc]] (cchoc@mindspring.com) says:
 
Make sure you are compiling with the Gm+ option, the Open Class Library requires the multi-threaded otpion.  In a multi-thread environment _errno is a function, in a single thread environment it is an int.
 
----


Another situation that will cause a LNK2029 error is when a method for a class has been declared, but not defined in any of the source files. For example, the linker will generate the following error:
Another situation that will cause a LNK2029 error is when a method for a class has been declared, but not defined in any of the source files. For example, the linker will generate the following error:
  test.obj(test.cpp) : error LNK2029: "{MyWindow}IVBase::virtual-fn-table-ptr" : unresolved external
  test.obj(test.cpp) : error LNK2029: "{MyWindow}IVBase::virtual-fn-table-ptr" : unresolved external


if the following source file is compiled & linked:
if the following source file is compiled & linked:
<blockquote>''(note that while the constructor has been declared '''and''' defined, the destructor was declared but accidently left out undefined)''</blockquote>
<blockquote>''(note that while the constructor has been declared '''and''' defined, the destructor was declared but accidently left out undefined)''</blockquote>
   #include <iframe.hpp>
   #include <iframe.hpp>
Line 442: Line 390:
         ~MyWindow();
         ~MyWindow();
   };
   };
 
   MyWindow::MyWindow() : IFrameWindow()
   MyWindow::MyWindow() : IFrameWindow()
   {  return; }
   {  return; }
 
   int main()
   int main()
   {  return 0; }
   {  return 0; }


; Note:
;Note: See also [[#Required Compiler Flag]] and [[#How to Link]]
: See also [[#Required Compiler Flag]] and [[#How to Link]]


==Error EDC0166, EDC0275, EDC0045 and EDC0046==
===Error EDC0166, EDC0275, EDC0045 and EDC0046===
If your source code has the extension .c and you are including some OCL #includes, then the compiler may generate many errors which seem to come from the IBMCPP include files. These errors are generated because the compiler assumes that .c files only contain C code, not C++, and the OCL include files require the compiler to be in the C++ mode.
If your source code has the extension .c and you are including some OCL #includes, then the compiler may generate many errors which seem to come from the IBMCPP include files. These errors are generated because the compiler assumes that .c files only contain C code, not C++, and the OCL include files require the compiler to be in the C++ mode.


Line 467: Line 414:
: See also [[#How to Compile]]
: See also [[#How to Compile]]


=OCL - Fixpacks and CSDs=
==OCL - Fixpacks and CSDs==
 
The latest CSDs (corrective service disks) available from IBM for VisualAge C++ can be downloaded for free from {{L-IBM|/ps/products/visualagecpp/fixes/}}
The latest CSDs (corrective service disks) available from IBM for VisualAge C++ can be downloaded for free from: [ftp://service.boulder.ibm.com/ps/products/visualagecpp/fixes/ <code>ftp://service.boulder.ibm.com/ps/products/visualagecpp/fixes</code>].


For users of the US English version of VisualAge for OS/2, you need all of the files located in: [ftp://service.boulder.ibm.com/ps/products/visualagecpp/fixes/v30os2/english-us/fixpak7 <code>ftp://service.boulder.ibm.com/ps/products/visualagecpp/fixes/v30os2/english-us/fixpak8</code>].
For users of the US English version of VisualAge for OS/2, you need all of the files located in {{L-IBM|/ps/products/visualagecpp/fixes/v30os2/english-us/fixpak7}}


For other language users or for the Win32 VAC++ version, you will need to go into the appropriate subdirectory specified from the first link noted above.
For other language users or for the Win32 VAC++ version, you will need to go into the appropriate subdirectory specified from the first link noted above.


; Note:
; Note: this fixpack represents more than 20MB of .ZIP files, so you may want to plan ahead before starting your download.
: this fixpack represents more than 20MB of .ZIP files, so you may want to plan ahead before starting your download.
; Note: the file called <tt>cts306.zip</tt> is generally not needed - this file is a source fix to the IBM Open Class Library Source Files, a separate product that can be purchased from IBM at a cost of many hundreds of dollars, and not included by default when you purchase VisualAge C++.
; Note:
: the file called <code>cts306.zip</code> is generally not needed -- this file is a source fix to the IBM Open Class Library Source Files, a seperate product that can be purchased from IBM at a cost of many hundreds of dollars, and not included by default when you purchase VisualAge C++.


To apply the fixpacks, follow the order prescribed by IBM (VAC++ v3.0 for OS/2):
To apply the fixpacks, follow the order prescribed by IBM (VAC++ v3.0 for OS/2):
# reboot
# reboot
# <code>CTC308</code>
# <tt>CTC308</tt>
# <code>CTO308</code>
# <tt>CTO308</tt>
# <code>CTW308</code>
# <tt>CTW308</tt>
# reboot
# reboot
# <code>CTV308</code>
# <tt>CTV308</tt>
# <code>CTD308</code>
# <tt>CTD308</tt>
# <code>CTU308</code>
# <tt>CTU308</tt>
# reboot
# reboot
# if you have the OpenClass source code, apply <code>CTS308</code> at any time
# if you have the OpenClass source code, apply <tt>CTS308</tt> at any time


=Contributors=
==Contributors==
This document is (will be?!) the result of input from many sources. These include the following people who have been kind enough to submit hints, tips, examples, and other contributions:
This document is (will be?!) the result of input from many sources. These include the following people who have been kind enough to submit hints, tips, examples, and other contributions:
*[[Stéphane Charette]]
*Charlie Choc
*Mark Anderson
*[[Dave Briccetti]]
*Bill Law
*Tsung-Hsun Yang


* [[Stéphane Charette]]
[[Category:C++ Class Libraries]]
* [[Charlie Choc]], cchoc@mindspring.com
* [[Mark Anderson]], os2team@romeop03.fishkill.ibm.com
* [[Dave Briccetti]]
* [[Bill Law]], law@netscape.com
* [[Tsung-Hsun Yang]], u7924811@cc.nctu.edu.tw
 
 
[[Category:Tools Articles]]

Latest revision as of 11:35, 16 September 2024

By Stéphane Charette

General Information

History of the Open Class Library FAQ

The revision history is as follows:

Version Comment Author Date
0.1 initial write-up in OS/2's IPF (.INF) format SC 1997-06-21
0.1a added table of files at Hobbes SC 1997-06-24
0.1b converted the FAQ to HTML format SC 1997-06-28
0.1d Added animation sample
Added LNK2029 information
Updated fixpak information
Created "Errors in IBM's include files"
SC 1997-09-05
0.1e Changed e-mail address
Added POV_Launch to the Hobbes index
Added custom-draw container information
SC 1997-11-02

How to obtain a copy of the FAQ

To obtain an HTML copy of the FAQ for local installation, download the file [ocl_faq.zip].

Unzip this file in its own directory (if using PKUNZIP, remember to use the /D option to create the subdirectories) and use your favourite web browser to access the files locally.

Where to obtain additional information

The on-line reference for OCL is located in your VisualAge folder, under the VisualAge C++ Information folder. The reference .INF file should be titled Open Class Library Reference (\IBMCPP\HELP\CLREF.INF) while a second .INF user's guide is called Open Class Library User's Guide (\IBMCPP\HELP\CPPCLSUG.INF).

The first book, Open Class Library Reference has all of the documented methods, objects, and necessary include files. The easiest way to find what you need is probably to click on Classes By Name, normally the second option from the top (may depend on the version of the documentation).

Note that one of the most useful .INF books which IBM ships with VisualAge can easily be overlooked; in the VisualAge C++ Information folder is a book called VisualAge C++ Frequently Asked Questions which deals with quite a few OCL topics.

Additional information on programming using OCL can be obtained from a variety of sources. There is an increase in books published (some of which by IBM) which deal with OCL, as well as numerous sources on the Internet.

For more information, consult:

Books which deal with OCL are:

OS/2 Class Library
Power GUI Programming with C/Set++
Written by Leon, Law, Love Tsuji & Olson
Published by John Wiley & Sons
ISBN 0-471-13117-2
(Obsolete and replaced by the following book)
Power GUI Programming with VisualAge C++
Written by Law, Love, Olson & Tsuji
Published by John Wiley & Sons
ISBN 0-471-16482-8
(recommended by Mark Anderson, os2team@romeop03.fishkill.ibm.com)

Index of samples on Hobbes

Starting mid-June, 1997, I have begun to upload to ftp://hobbes.nmsu.edu/pub/os2/dev/cplusplus a series of Open Class Library samples that I have written. The following table is the index of these samples.

Filename Description Classes Used
OCL_ANI1.ZIP animation sample IApplication, IColor, IDrawingCanvas, IEvent, IFrameWindow, IGBitmap, IGList, IRectangle, ITimer
OCL_CON1.ZIP details view container sample IApplication, IContainerColumn, IContainerControl, IContainerObject, IFrameWindow, IString
OCL_THR1.ZIP thread and timer sample (minimized icon fix explained) IApplication, ICommandEvent, ICommandHandler, IFrameWindow, IListBox, IPushButton, IString, ISystemMenu, IThread, IThreadFn, ITimer
OCL_ANI2.ZIP animation sample #2 IApplication, ICommandEvent, ICommandHandler, IColor, IControlEvent, IDrawingCanvas, IFrameWindow, IFrameEvent, IFrameHandler, IGBitmap, IGList, IGraphicContext, IMouseClickEvent, IMouseHandler, IPopUpMenu, ITimerMemberFn0
OCL_CON2.ZIP custom drawing in a details-view container IApplication, ICnrDrawHandler, IContainerColumn, IContainerControl, IContainerObject, IFrameWindow
PLNCH01G.ZIP POV front-end Some of almost all classes available, including threads, canvases, icons, bitmaps, standard controls, profiles and exceptions.
Note
See also #Where to Obtain Additional Information

OCL - Compiling

How to Compile

If you wish to correctly compile your OCL application, then the following should be used:

  • if you are using the project templates and WorkFrame that come with Visual Age, then
    1. click on Tools
    2. make certain that View is set to Actions
    3. expand the Compile subtree
    4. right-mouse-click on C++ Compiler
    5. select File Options
    6. select the Object tab
    7. select the Multithread option for Library selection (this sets the /Gm+ flag)
    8. click on OK
    9. close the tools setup
    10. regenerate the makefile and recompile
  • if you are compiling from the command-line, or using your own makefiles, then
    1. use the command icc.exe /Gm+ /C <other optional compiler flags> myfile.cpp
Note
See also #/Gm+, #How to Link, #Static Linking and #Dynamic Linking

Required compiler flag

There is one flag that absolutely must be specified when compiling source code which uses OCL calls. This flag is described as follows in the on-line help:

/Gm+
Link with multithread runtime libraries.

The default for ICC is to use /Gm- (no support for the multithreaded libraries) so the /Gm+ flag must be specified. Typical compiler behaviour when this flag is not specified is:

D:\IBMCPP\INCLUDE\ibase.hpp(226:3) : error EDC3086:
Error: Use of IBM Open Class Library requires the /Gm+ compiler option.
D:\IBMCPP\INCLUDE\ibase.hpp(227:3) : error EDC3086:
Check the makefile (or its profile) for a missing /Gm+ option.

Note: See also #How to Compile and #Error EDC3086

Errors in IBM's include files

If your source code has the extension .c and you are including some OCL #includes, then the compiler may generate many errors which seem to come from the IBMCPP include files. These errors are generated because the compiler assumes that .c files only contain C code, not C++, and the OCL include files require the compiler to be in the C++ mode.

To get around this problem, use the compiler flag /Tdp to tell the VAC++ to treat all files as C++ files.

Some of the errors you may be seeing include the following:

imsgtext.hpp(24:1) : error EDC0166: Definition of function class requires parentheses. 
imsgtext.hpp(24:7) : error EDC0275: Unexpected text IMessageText encountered. 
imsgtext.hpp(27:19) : error EDC0046: Syntax error. 
imsgtext.hpp(28:33) : error EDC0045: Undeclared identifier messageFileName. 
imsgtext.hpp(29:33) : error EDC0045: Undeclared identifier textInsert1.
Note
See also #How to Compile

OCL - Linking

How to Link

The recommended method of linking when some or all of the object files have references to OCL function calls is to use ICC, and not LINK386, ILINK, etc.

To link an object file (.OBJ) which makes use of OCL, the following should be used:

  • if you are using the project templates and WorkFrame that come with VisualAge C++, then
    1. click on Tools
    2. make certain that View is set to Actions
    3. right-mouse-click on Link
    4. click on Add
    5. make certain that:
      • general.class == Link
      • general.name == Link (OCL)
      • general.program == ICC.EXE
      • general.session == MONITOR
      • general.action applies to FILE, not PROJECT
      • types.source == LinkerIn
      • types.target == LinkerOut
      • support.name == CPPICL30
      • support.entrypoint == LINK
      • click on OK
    6. close the tools setup
    7. regenerate the makefile to use the new link method, recompile and link
  • if you are linking from the command-line, or using your own makefiles, then
    1. use the command icc.exe <other optional compiler flags> /B" /pmtype:pm" myfile.obj
Note
See also #How to Compile, #Static Linking and #Dynamic Linking

Static linking

Static linking will combine the IBM Open Class Library files with your object files to create a stand-alone application. This means that you are not required to have a copy of the X:\IBMCPP\DLL\DDE4*.DLL files on your system in order to run the application.

The side effect of using this will be that your application may appear to be quite enormous in size.

To use 'static linking' you must specify the /Gd- (this is the default) option when compiling your .CPP files. You can change this setting by one of the following methods:

  • if you are using the project templates and WorkFrame that come with VisualAge, then
    1. click on Tools
    2. make certain that View is set to Actions
    3. expand the Compile subtree
    4. right-mouse-click on C++ Compiler
    5. select File Options
    6. select the Object tab
    7. select the Static option for Library linkage
    8. click on OK
    9. close the tools setup
    10. regenerate the makefile and recompile
  • if you are compiling from the command-line, or using your own makefiles, then
    1. make certain that the /Gd- option is specified
Note
See also #Dynamic Linking and #How to Link
Note
Need info on rights, etc...are you allowed to distribute an application that was statically linked? Isn't there something in the docs? I haven't had the time to look it up yet - if someone has references handy, please let me know.

Dynamic Linking

Dynamic linking will setup your application to call the necessary OCL functions dynamically using DLLs. This assumes that the required DLL files are already referenced somewhere in LIBPATH before the application will run.

This is much faster to link, and the resulting application will be much smaller than using static linking. Of course, if the IBM VisualAge DLLs are not on the system which will be using this application, then it will fail to run. A typical application nearing 800Kb when linked statically may barely surpass 40Kb when linked dynamically.

To use 'dynamic linking' you must specify the /Gd+ (this is not the default) option when compiling your .CPP files. You can change this setting by one of the following methods:

  • if you are using the project templates and WorkFrame that come with Visual Age, then
    1. click on Tools
    2. make certain that View is set to Actions
    3. expand the Compile subtree
    4. right-mouse-click on C++ Compiler
    5. select File Options
    6. select the Object tab
    7. select the Dynamic option for Library linkage
    8. click on OK
    9. close the tools setup
    10. regenerate the makefile and recompile
  • if you are compiling from the command-line, or using your own makefiles, then
    1. make certain that the /Gd+ option is specified.
Note
See also [static_linking.html Static Linking] and [how_to_link.html How to Link]
Note
Need info on rights, etc...are you allowed to distribute the DLLs with an application that was dynamically linked? Isn't there something in the docs? I haven't had the time to look it up yet - if someone has references handy, please let me know.

OCL - Miscellaneous

Application dies when starting

If your application compiles and links without problems, but it then dies during startup (you may or may not see the frame window start to come up) then check for the following common mistakes:

  • is more than one resource using the same number in your .RC or .DLG file?
  • are you trying to allocate/create a resource in your .CPP file - say an IPushButton - when in reality it has been defined as something else in your .RC or .DLG file?
  • Bill Law (law@netscape.com) also says: The most common occurrence is that your app is throwing an (uncaught) exception during construction of the first (frame) window. This terminates silently, unless you take steps to capture the exception information. To do that, follow the instructions provided in the on-line VACPP FAQ (in the section "Coding With User Interface Classes"->"Exceptions"->"Why Does My Program Just Exit").

[Editor's note: the VACPP FAQ is D:\IBMCPP\HELP\CPPFAQ.INF]

  • did you specify the type of application when linking? If the application is compiled with the default value of /pmtype:vio then your window will not come up. Make certain you use /pmtype:pm from the linker, or /B" /pmtype:pm" when linking directly from the compiler.

Application-modal windows

To create an application modal dialog window, the parent and the owner of the window being created must be different. The parent should be the desktop window handle, while the owner should be the calling dialog window's handle. For example:

IFrameWindow *anotherDlg = 
new IFrameWindow( MY_RES_ID,         /* resource id of new window */ 
                  desktopWindow(),   /* parent window handle */ 
                  this );            /* owner window handle */ 
anotherDlg->showModally();

System-modal windows

(Nothing here yet...feel free to submit something)

How to convert a native PM item to OCL

Most native PM windows have an equivalent in OCL, and an item that already exists on a window can at any time be "converted" to OCL. This is advantageous for example if some of the functionality you need has already been implemented using OCL. For example:

> Can a pointer to a 'low-level' listbox be converted into a pointer to an
> Open Class listbox?

Dave Briccetti says:

Most of the OC UI controls have a constructor that takes the HWND of an existing control. In this case, the constructor looks like

IListBox (const IWindowHandle &)

IWindowHandle is an "alias" for HWND.

Bill Law (law@netscape.com) also adds the following:

Perhaps you should add that if an OCL window already exists for a given HWND, then constructing another one from its HWND will result in an exception being thrown. Generally, if there is a chance that an existing OCL window exists (or you know that one does and you just want to locate it), then you can use IWindow::fromHandle to get the existing IWindow (or derived-class) object. If that returns 0, then you can safely construct another IWindow (or derived-class) object.

How to create a thread

There are different ways of creating threads using OCL, and the method chosen will often depend on what you want the thread to do.

Example of creating a thread to call an object method:

MyDlgClass      *frame            = new MyDlgClass();
IThreadMemberFn *myThreadMemberFn = new IThreadMemberFn<MyDlgClass>(frame, MyDlgClass::doSomething));
IThread         *myThread         = new IThread(myThreadMemberFn);

Example of creating a thread to call an entire class:

class MyThreadClass : public IThreadFn
...
int main()
{
   ...
   MyThreadClass  *myThreadFn = new MyThreadClass();
   IThread        *myThread   = new IThread( myThreadFn );
Warning
When using IThreadFn as opposed to IThreadMemberFn, the class being created must inherit from IThreadFn, and must contain the method run()
Note
See also #Index of Samples on Hobbes

How to assign an icon to a window

In the .RC file, you must assign an icon to the same resource ID that the dialog window is using in the .DLG file, and then load it when you create the window. This is done as follows:

In your .H file, you would have:

  #define MY_DIALOG_RCID 0x1000

In your .RC file, you would have:

  ICON MY_DIALOG_RCID myicon.ico

In your .DLG file, you would have:

  DLGTEMPLATE MY_DIALOG_RCID PRELOAD MOVEABLE DISCARDABLE
  BEGIN
      DIALOG  "My Dialog Title", MY_DIALOG_RCID, ...

In your .CPP file, you would have:

  IFrameWindow *myDlg = new IFrameWindow( MY_DIALOG_RCID );   // create the window
  myDlg->setIcon( MY_DIALOG_RCID );                           // set the icon
Note
See also #How to Prevent the Minimized Icon From Being Overwritten

How to prevent the minimized icon from being overwritten

If your dialog window contains or consists of a canvas, then when you minimize the window, the icon which is being used (IFrameWindow::setIcon()) will be drawn correctly on the screen. However, if you have some controls which are not on a canvas, then you will run into a problem where the minimized icon is being overwritten by some of your controls.

This is a common problem - I believe with native PM applications as well - that can very easily be fixed.

In your application, you will need to create a command handler for your window to capture all of the system commands. This can be done by inheriting from ICommandHandler, and declaring the function Boolean systemCommand( ICommandEvent &event );. Then when you detect the ISystemMenu::idMinimize event, you need to hide() the offending controls. Likewise, when you detect the ISystemMenu::idRestore event, you need to show() the controls that have previously been hidden.

For example:

/* this is part pseudo-code and will not compile without modifications */
class myClass : public IFrameWindow, public ICommandHandler
{
   myClass() :                // constructor for class...
      IFrameWindow(...),      // ...inherit from IFrameWindow...
      ICommandHandler() {;};  // ...and from ICommandHandler
   Boolean systemCommand( ICommandEvent &event );  // inherited from ICommandHandler
};

int main()
{
   myClass *frame = new myClass();  // create class
   frame->setIcon( MY_ICON_RCID );  // set default icon
   frame->(ICommandHandler)handleEventsFor( frame );   // setup handler
   ...do some more stuff here...
   frame->(ICommandHandler)stopHandlingEventsFor( frame );  // stop handler
   return 0;
}

myClass::systemCommand( ICommandEvent &event )
{
   if( event.commandId() == ISystemMenu::idMinimize )
   {
      ...hide controls overwriting the icon by calling their hide() method...
   }
   if( event.commandId() == ISystemMenu::idRestore )
   {
      ...show controls overwriting the icon by calling their show() method...
   }
   return false;  // return as if the event hasn't been handled
}
Note
See also #How to Assign an Icon to a Window and #Index of Samples on Hobbes

How to print

Support for printing using OCL calls has not yet been included. IBM has promised that this will be included "soon", but no date has been given.

For now, you may want to refer to the OS/2 Programming FAQ for more information on traditional printing in OS/2. This FAQ can be found at anyone know where?.

Valuesets (WC_VALUESET)

It seems that valuesets are not directly supported in OCL. You can still create them in DLGEDIT.EXE, and access them with OCL code, but with some limitations.

In your code, you can use the following:

IWindow *vs = new IWindow( MY_VALUESET_RCID, this );

Thus, you can then change all of the standard window attributes using OCL calls, but all of the valueset-specific information will have to be handled using standard PM programming.

Custom-drawing in a container

To draw your own items in a container (IContainerControl) you will need to make use of the ICnrDrawHandler class. For an example of how this can be done in a details-view container (same principal can be applied to other views) please see the OCL_CON2.ZIP example from Hobbes.

Note
See also #Index of Samples on Hobbes

OCL - Errors

Error EDC3086

The error EDC3086 is caused by the compiler detecting OCL calls in a source file which was not compiled with the /Gm+ parameter.

You can fix this error by making certain you are compiling with the multithreaded libraries.

Note
See also #How to Compile and Required Compiler Flag

Error LNK2029

The error LNK2029 is caused by the linker when you have OCL calls in your source, but you didn't compile with the /Gm+ parameter. The error may look as follows:

CPPOOC3.LIB (iexcept.cpp) : error LNK2029: "_errno" : unresolved external

Charlie Choc (cchoc@mindspring.com) says:

Make sure you are compiling with the Gm+ option, the Open Class Library requires the multi-threaded otpion. In a multi-thread environment _errno is a function, in a single thread environment it is an int.

Another situation that will cause a LNK2029 error is when a method for a class has been declared, but not defined in any of the source files. For example, the linker will generate the following error:

test.obj(test.cpp) : error LNK2029: "{MyWindow}IVBase::virtual-fn-table-ptr" : unresolved external

if the following source file is compiled & linked:

(note that while the constructor has been declared and defined, the destructor was declared but accidently left out undefined)

  #include <iframe.hpp>
  class mywindow : public IFrameWindow
  {  public:
        MyWindow();
        ~MyWindow();
  };

  MyWindow::MyWindow() : IFrameWindow()
  {  return; }

  int main()
  {  return 0; }
Note
See also #Required Compiler Flag and #How to Link

Error EDC0166, EDC0275, EDC0045 and EDC0046

If your source code has the extension .c and you are including some OCL #includes, then the compiler may generate many errors which seem to come from the IBMCPP include files. These errors are generated because the compiler assumes that .c files only contain C code, not C++, and the OCL include files require the compiler to be in the C++ mode.

To get around this problem, use the compiler flag /Tdp to tell the VAC++ to treat all files as C++ files.

Some of the errors you may be seeing include the following:

imsgtext.hpp(24:1) : error EDC0166: Definition of function class requires parentheses. 
imsgtext.hpp(24:7) : error EDC0275: Unexpected text IMessageText encountered. 
imsgtext.hpp(27:19) : error EDC0046: Syntax error. 
imsgtext.hpp(28:33) : error EDC0045: Undeclared identifier messageFileName. 
imsgtext.hpp(29:33) : error EDC0045: Undeclared identifier textInsert1.
Note
See also #How to Compile

OCL - Fixpacks and CSDs

The latest CSDs (corrective service disks) available from IBM for VisualAge C++ can be downloaded for free from IBM: /ps/products/visualagecpp/fixes/

For users of the US English version of VisualAge for OS/2, you need all of the files located in IBM: /ps/products/visualagecpp/fixes/v30os2/english-us/fixpak7

For other language users or for the Win32 VAC++ version, you will need to go into the appropriate subdirectory specified from the first link noted above.

Note
this fixpack represents more than 20MB of .ZIP files, so you may want to plan ahead before starting your download.
Note
the file called cts306.zip is generally not needed - this file is a source fix to the IBM Open Class Library Source Files, a separate product that can be purchased from IBM at a cost of many hundreds of dollars, and not included by default when you purchase VisualAge C++.

To apply the fixpacks, follow the order prescribed by IBM (VAC++ v3.0 for OS/2):

  1. reboot
  2. CTC308
  3. CTO308
  4. CTW308
  5. reboot
  6. CTV308
  7. CTD308
  8. CTU308
  9. reboot
  10. if you have the OpenClass source code, apply CTS308 at any time

Contributors

This document is (will be?!) the result of input from many sources. These include the following people who have been kind enough to submit hints, tips, examples, and other contributions: