home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv4.zip / VACPP / IBMCPP / HELP / CPPFAQ.INF (.txt) < prev    next >
OS/2 Help File  |  1995-05-02  |  286KB  |  8,579 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. About this FAQ ΓòÉΓòÉΓòÉ
  3.  
  4. This FAQ provides answers to the questions that VisualAge C++ customers ask 
  5. most often about the product, how it works, and how to use it. 
  6.  
  7. When you encounter a problem using VisualAge C++, look here first for the 
  8. solution.  You can search for the information you need based on the symptoms of 
  9. your problem, or on the type of task you were trying to do when the problem 
  10. occurred.  For a list of other information that you might also find helpful, 
  11. see Other Information You Might Find Helpful. 
  12.  
  13. If the questions included here do not describe your problem, or if the answers 
  14. do not solve it, refer to What If I Still Have Questions?. Before you begin to 
  15. use this information, it would be helpful to understand how to navigate through 
  16. it. You can use the Table of Contents and Index facility to locate topics and 
  17. the Search facility to search the text of this document. You can use hypertext 
  18. links to acquire related information on the current topic.  Hypertext links 
  19. appear in a different color (which you can customize using the OS/2 Scheme 
  20. Palette). For example, here is a link to another panel: Communicating Your 
  21. Comments to IBM. By double-clicking on the text of the link or by pressing 
  22. Enter on a highlighted link, you will open a panel of related information. When 
  23. you open a panel, the first link has the focus; to shift the focus to other 
  24. links, use the Tab key. 
  25.  
  26. You should also understand: 
  27.  
  28.      How to Use the Contents 
  29.      How to Obtain Additional Information 
  30.      How to Use Action Bar Choices 
  31.      How to Cut and Paste Examples 
  32.  
  33.  
  34. ΓòÉΓòÉΓòÉ 1.1. Notices ΓòÉΓòÉΓòÉ
  35.  
  36. Copyright International Business Machines Corporation, 1995. All rights 
  37. reserved. 
  38.  
  39. Note to U.S. Government Users - Documentation related to restricted rights - 
  40. Use, duplication, or disclosure is subject to restrictions set forth in GSA ADP 
  41. Schedule Contract with IBM Corp. 
  42.  
  43. First Edition, May 1995. 
  44.  
  45. This edition applies to Version 3.0 of IBM VisualAge C++ for OS/2 (30H1664, 
  46. 30H1665, 30H1666) and to all subsequent releases and modifications until 
  47. otherwise indicated in new editions.  Make sure you are using the correct 
  48. edition for the level of the product. 
  49.  
  50. This publication could include technical inaccuracies or typographical errors. 
  51. Changes are periodically made to the information herein; any such changes will 
  52. be reported in subsequent revisions. 
  53.  
  54. Requests for publications and for technical information about IBM products 
  55. should be made to your IBM Authorized Dealer or your IBM Marketing 
  56. Representative. 
  57.  
  58. When you send information to IBM, you grant IBM a nonexclusive right to use or 
  59. distribute the information in any ways it believes appropriate without 
  60. incurring any obligation to you. 
  61.  
  62. Any reference to an IBM licensed program in this publication is not intended to 
  63. state or imply that only IBM's licensed program may be used. Any functionally 
  64. equivalent product, program, or service that does not infringe any of IBM's 
  65. intellectual property rights may be used instead of the IBM product, program, 
  66. or service. Evaluation and verification of operation in conjunction with other 
  67. products, except  those expressly designated by IBM, is the user's 
  68. responsibility. 
  69.  
  70. IBM may have patents or pending patent applications covering subject matter in 
  71. this document.  The furnishing of this document does not give you any license 
  72. to these patents.  You can send license inquiries, in writing, to the IBM 
  73. Director of Licensing. IBM Corporation, 500 Columbus Avenue, Thornwood, NY, 
  74. 10594, USA. 
  75.  
  76. This publication contains examples of data and reports used in daily business 
  77. operations.  To illustrate them as completely as possible, the examples include 
  78. the names of individuals, companies, brands, and products.  All of these names 
  79. are fictitious and any similarity to the names and addresses used by an actual 
  80. business enterprise is entirely coincidental. 
  81.  
  82.  
  83. ΓòÉΓòÉΓòÉ 1.2. Trademarks and Service Marks ΓòÉΓòÉΓòÉ
  84.  
  85. The following terms used in this publication are trademarks or service marks of 
  86. IBM Corporation in the United States or other countries: 
  87.  
  88.       AIX 
  89.       C/2 
  90.       C Set/2 
  91.       C Set ++ 
  92.       IBM 
  93.       Open Class 
  94.       OS/2 
  95.       OS/2 Warp 
  96.       Presentation Manager 
  97.       VisualAge 
  98.       WorkFrame 
  99.       Workplace Shell 
  100.  
  101.  Windows is a trademark of Microsoft Corporation. 
  102.  
  103.  Other company, product, and service names, which may be denoted by a double 
  104.  asterisk(**), may be trademarks or service marks of others. 
  105.  
  106.  
  107. ΓòÉΓòÉΓòÉ 1.3. How to Use the Contents ΓòÉΓòÉΓòÉ
  108.  
  109. When the Contents window first appears, some topics have a plus (+) sign beside 
  110. them. The plus sign indicates that additional topics are available. 
  111.  
  112. To expand the Contents if you are using a mouse, click on the plus sign.  If 
  113. you are using the keyboard, use the Up or Down Arrow key to highlight the 
  114. topic, and press the plus (+) key. For example, How to Use the Contents has a 
  115. plus sign beside it.  To see additional topics for that heading, click on the 
  116. plus sign or highlight that topic and press the plus (+) key. 
  117.  
  118. To view a topic, double-click on the topic (or press the Up or Down Arrow key 
  119. to highlight the topic, and then press the Enter key). 
  120.  
  121.  
  122. ΓòÉΓòÉΓòÉ 1.4. How to Obtain Additional Information ΓòÉΓòÉΓòÉ
  123.  
  124. After you select a topic, the information for that topic appears in a window. 
  125. Highlighted words or phrases indicate that additional information is available. 
  126. Certain words and phrases are highlighted in a different color from the 
  127. surrounding text. These are called hypertext terms. 
  128.  
  129. If you are using a mouse, double-click on the highlighted word.  If you are 
  130. using a keyboard, press the Tab key to move to the highlighted word, and then 
  131. press the Enter key.  Additional information then appears in a window. 
  132.  
  133.  
  134. ΓòÉΓòÉΓòÉ 1.5. How to Use Action Bar Choices ΓòÉΓòÉΓòÉ
  135.  
  136. Several choices are available for managing the information presented in this 
  137. document. There are three menus on the action bar:  the Services menu, the 
  138. Options menu, and the Help menu. 
  139.  
  140. The actions that are selectable from the Services menu operate on the active 
  141. window currently displayed on the screen. These actions include the following: 
  142.  
  143.  Placing Bookmarks 
  144.    You can set a placeholder so you can retrieve information of interest to 
  145.    you. 
  146.  
  147.  Searching for Information 
  148.    You can find occurrences of a word or phrase in the current topic, 
  149.    selected topics, or all topics. 
  150.  
  151.  Printing Information 
  152.    You can print one or more topics. You can also print a set of topics by 
  153.    first marking the topics in the Contents list. 
  154.  
  155.  Copying Information to a File 
  156.    You can copy a topic that you are viewing to the System Clipboard or to a 
  157.    file that you can edit. This method is particularly useful for copying 
  158.    syntax definitions and program samples into the application that you are 
  159.    developing. 
  160.  
  161.  Using the actions that are selectable from the Options menu, you can change 
  162.  the way your Contents list is displayed. To expand the Contents and show all 
  163.  levels for all topics, choose Expand all from the Options pull-down. You can 
  164.  also press the Ctrl and * keys together. 
  165.  
  166.  The actions that are selectable from the Help menu allow you to select 
  167.  different types of help information. 
  168.  
  169.  For information about any of the menu choices, highlight the choice in the 
  170.  menu and press F1. 
  171.  
  172.  
  173. ΓòÉΓòÉΓòÉ 1.5.1. Placing Bookmarks ΓòÉΓòÉΓòÉ
  174.  
  175. When you place a bookmark on a topic, it is added to a list of bookmarks you 
  176. have previously set.  You can view the list, and you can remove one or all 
  177. bookmarks from the list.  If you have not set any bookmarks, the list is empty. 
  178.  
  179. To set a bookmark, do the following: 
  180.  
  181.    1. Select a topic from the Contents. 
  182.    2. When that topic appears, select the Bookmark option from the Services 
  183.       menu. 
  184.    3. If you want to change the name used for the bookmark, type the new name 
  185.       in the field. 
  186.    4. Click on the Place radio button (or press the Up or Down Arrow key to 
  187.       select it). 
  188.    5. Click on OK (or select it and press Enter). The bookmark is then added to 
  189.       the bookmark list. 
  190.  
  191.  
  192. ΓòÉΓòÉΓòÉ 1.5.2. Searching for Information ΓòÉΓòÉΓòÉ
  193.  
  194. You can specify a word or phrase to be searched.  You can also limit the search 
  195. to a set of topics by first marking the topics in the Contents list. 
  196.  
  197. To search for a word or phrase in all topics, do the following: 
  198.  
  199.    1. Select the Search option from the Services menu. 
  200.    2. Type the word or words to be searched for. 
  201.    3. Click on All sections (or press the Up or Down Arrow keys to select it). 
  202.    4. Click on Search (or select it and press Enter) to begin the search. 
  203.    5. The list of topics where the word or phrase appears is displayed. 
  204.  
  205.  
  206. ΓòÉΓòÉΓòÉ 1.5.3. Printing Information ΓòÉΓòÉΓòÉ
  207.  
  208. You can print one or more topics, the index, or the table of contents.  Make 
  209. sure that your printer is connected to the serial port, configured correctly, 
  210. and ready for input. To print: 
  211.  
  212.    1. Select Print from the Services pull-down. 
  213.    2. Select what you want to print. Note that the This section and Marked 
  214.       sections choices are only available if you are viewing a topic or if you 
  215.       have marked topics, respectively.  To mark topics in the table of 
  216.       contents, press the Ctrl key and click on the topics, or use the arrow 
  217.       keys. 
  218.    3. Select Print to print what you've chosen on your printer. 
  219.  
  220.  
  221. ΓòÉΓòÉΓòÉ 1.5.4. Copying Information to a File ΓòÉΓòÉΓòÉ
  222.  
  223. You can copy a topic that you are viewing in two ways: 
  224.  
  225.      Copy copies the topic that you are viewing into the System Clipboard.  If 
  226.       you are using a Presentation Manager (PM) editor (for example, the 
  227.       Enhanced Editor) that copies or cuts (or both) to the System Clipboard, 
  228.       and pastes to the System Clipboard, you can easily add the copied 
  229.       information to your program source module. 
  230.  
  231.      Copy to file copies the topic that you are viewing into a temporary file 
  232.       named TEXT.TMP.  You can later edit that file by using any editor. 
  233.       TEXT.TMP is placed in the directory where your viewable document resides. 
  234.  
  235.  To copy a topic, do the following: 
  236.  
  237.    1. Expand the Contents list and select a topic. 
  238.    2. When the topic appears, select Copy to file from the Services menu. 
  239.    3. The system puts the text pertaining to that topic into the temporary file 
  240.       TEXT.TMP. 
  241.  
  242.  
  243. ΓòÉΓòÉΓòÉ 1.6. How to Cut and Paste Examples ΓòÉΓòÉΓòÉ
  244.  
  245. You can copy examples (or information) from this FAQ to compile, link, and run 
  246. them, or to paste them into your own code. 
  247.  
  248. To copy an example or information: 
  249.  
  250.    1. Make the topic you want to copy the active window. 
  251.  
  252.    2. From the Services menu, select Copy to file. The text in that topic is 
  253.       placed in the temporary file TEXT.TMP, in the same directory as this 
  254.       reference. 
  255.  
  256.    3. You can then modify or use TEXT.TMP as you want. 
  257.  
  258.  
  259. ΓòÉΓòÉΓòÉ 1.7. Other Information You Might Find Helpful ΓòÉΓòÉΓòÉ
  260.  
  261. This product provides a number of online guides and references that we hope 
  262. you'll find helpful as you develop applications. This information includes 
  263. User's Guides, References, and How Do I help that gives you specific 
  264. instructions for performing common tasks. You can get to this online 
  265. information from the Information folder inside the main product folder.  You 
  266. can also get to it from the Help menu in any of the components of the product. 
  267.  
  268.  
  269. ΓòÉΓòÉΓòÉ 1.8. Communicating Your Comments to IBM ΓòÉΓòÉΓòÉ
  270.  
  271. If there is something you like, or dislike, about this book, please let us 
  272. know.  You can use one of the methods listed below to send your comments to 
  273. IBM.  Please be sure to include the complete title of the publication that you 
  274. are commenting on. 
  275.  
  276. The comments you send should only pertain to the information in this document 
  277. and its presentation.  To request additional publications or to ask questions 
  278. or make comments about the functions of IBM products or systems, you should 
  279. talk to your IBM representative or you authorized IBM remarketer. 
  280.  
  281. When you send comments to IBM, you grant IBM a nonexclusive right to use or 
  282. distribute your comments in any way it believes appropriate without incurring 
  283. any obligation to you. 
  284.  
  285. You can send your comments to IBM in the following ways: 
  286.  
  287.      By mail to the following address: 
  288.  
  289.             IBM Canada Ltd. Laboratory
  290.             Information Development
  291.             2G/345/1150/TOR
  292.             1150 EGLINTON AVENUE EAST
  293.             NORTH YORK, ONTARIO
  294.             CANADA M3C 1H7
  295.  
  296.      By FAX to the following number: 
  297.  
  298.         -  United States and Canada: (416) 448-6161 
  299.         -  Other countries (+1) 416-448-6161 
  300.  
  301.      By electronic mail to one of the following IDs.  Be sure to include your 
  302.       entire network address if you wish to get a reply. 
  303.  
  304.         -  Internet: torrcf@vnet.ibm.com 
  305.         -  IBMLink: toribm(torrcf) 
  306.         -  IBM/PROFS: torolab4(torrcf) 
  307.         -  IBMMAIL: ibmmail(caibmwt9) 
  308.  
  309.  
  310. ΓòÉΓòÉΓòÉ 2. General Questions about VisualAge C++ ΓòÉΓòÉΓòÉ
  311.  
  312. This section answers some general questions about VisualAge C++. 
  313.  
  314.      How Do I Get Code Fixes for VisualAge C++? 
  315.      What Operating Systems Does It Support? 
  316.      What Are the Minimum Hardware Requirements? 
  317.      How Do I Rebuild My VisualAge C++ Desktop Folders? 
  318.      Can I Get the Class Library Source Code? 
  319.      What Documentation Exists for the User Interface Classes? 
  320.      Can I Mix Object Files from Different Compilers? 
  321.      What Are the Library Naming Conventions? 
  322.      What Does Mangling Mean? 
  323.  
  324.  
  325. ΓòÉΓòÉΓòÉ 2.1. How Do I Get Code Fixes for VisualAge C++? ΓòÉΓòÉΓòÉ
  326.  
  327. Question: 
  328.  
  329. I think I have found a problem with the compiler or one of the tools. How do I 
  330. get a fix for this problem? 
  331.  
  332. Answer: 
  333.  
  334. Fixes for problems with VisualAge C++ components are provided in corrective 
  335. service diskettes (CSDs). 
  336.  
  337. Note:  CSDs are not really diskettes.  However, you can create diskettes from 
  338. them.  You can also apply the fixes in other ways. 
  339.  
  340. CSDs are available from CompuServe (GO OS2DF1), from the IBM PC Company 
  341. Bulletin Board System (919-517-0001), and from 
  342. ftp://software.watson.ibm.com/pub/cset. CSDs are cumulative; you only need to 
  343. apply the most recent one to get all the updates that have been made. 
  344.  
  345. If you apply the CSDs and your problem persists, report your problem to 
  346. VisualAge C++ Service and Support. For instructions on how to report problems, 
  347. see What If I Still Have Questions?. 
  348.  
  349.  
  350. ΓòÉΓòÉΓòÉ 2.2. What Operating Systems Does It Support? ΓòÉΓòÉΓòÉ
  351.  
  352. Question: 
  353.  
  354. Can VisualAge C++  generate code for DOS or Windows? What other operating 
  355. systems does it support? 
  356.  
  357. Answer: 
  358.  
  359. VisualAge C++ generates only 32-bit code for OS/2 2.11 and higher, including 
  360. the OS/2 Warp family. It does not generate DOS, Windows, or 16-bit code. 
  361. VisualAge C++ runs only under OS/2 2.11 and higher. 
  362.  
  363. C Set ++ and its class libraries are also available for the AIX and Solaris** 
  364. operating systems. 
  365.  
  366.  
  367. ΓòÉΓòÉΓòÉ 2.3. What Are the Minimum Hardware Requirements? ΓòÉΓòÉΓòÉ
  368.  
  369. Question: 
  370.  
  371. What are the minimum hardware requirements for VisualAge C++? 
  372.  
  373. Answer: 
  374.  
  375. The minimum requirements are: 
  376.  
  377.  Processor 
  378.       386; 486 is recommended. If you have a 386 processor, a 387 math 
  379.       coprocessor is also recommended. 
  380.  
  381.  Memory (RAM) 
  382.  
  383.            8M for C development (12M recommended) 
  384.            12M for C++ development (16M recommended) 
  385.            16M for visual C++ development (24M recommended) 
  386.  
  387.       Note:  In some cases, you may be able to run VisualAge C++ with less RAM 
  388.       than stated, but the performance will suffer. 
  389.  
  390.  Disk Space 
  391.       Approximately 170MB for a complete installation (110MB for the tools, 
  392.       60MB for sample programs and documentation). When you install 
  393.       VisualAge C++, the installation program tells you how much space is 
  394.       required for individual components. 
  395.  
  396.  Swap Space 
  397.  
  398.            10MB for C development 
  399.            30MB for C++ development 
  400.  
  401.  
  402. ΓòÉΓòÉΓòÉ 2.4. How Do I Rebuild My VisualAge C++ Desktop Folders? ΓòÉΓòÉΓòÉ
  403.  
  404. Question: 
  405.  
  406. How can I rebuild my desktop icons for VisualAge C++ without reinstalling? 
  407.  
  408. Answer: 
  409.  
  410. Run the CPPDESK command from the main VisualAge C++ directory (IBMCPP, if you 
  411. used the defaults). 
  412.  
  413.  
  414. ΓòÉΓòÉΓòÉ 2.5. Can I Get the Class Library Source Code? ΓòÉΓòÉΓòÉ
  415.  
  416. Question: 
  417.  
  418. Can I get the source code for the class libraries?  How? 
  419.  
  420. Answer: 
  421.  
  422. The source code for the IBM Open Class Library is available as a separate 
  423. product.  You can order it the same way you ordered VisualAge C++.  Its part 
  424. number (order number) is 30H1667. Corrective service is available for the 
  425. source code as well as for VisualAge C++, so you can maintain the source and 
  426. executable files at the same level. (For information on getting corrective 
  427. service, see How Do I Get Code Fixes for VisualAge C++?.) 
  428.  
  429.  
  430. ΓòÉΓòÉΓòÉ 2.6. What Documentation Exists for the User Interface Classes? ΓòÉΓòÉΓòÉ
  431.  
  432. Question: 
  433.  
  434. What documentation is there for the User Interface classes? 
  435.  
  436. Answer: 
  437.  
  438. The Open Class Library User's Guide and Open Class Library Reference that ship 
  439. with VisualAge C++ document the entire IBM Open Class Library, including the 
  440. User Interface classes. You can find these books in the VisualAge C++ 
  441. Information folder. 
  442.  
  443. The most complete separate publication is OS/2 C++ Class Library: Power GUI 
  444. Programming with C Set ++, by Kevin Leong, William Law, Robert Love, Hiroshi 
  445. Tsuji, and Bruce Olson. The publisher is John Wiley and Sons, Inc., and the 
  446. ISBN number is 0-471-13117-2. (Note that until recently, the publisher was Van 
  447. Nostrand Reinhold and the ISBN number 0-442-01795-2.) The book comes with a 
  448. diskette full of samples. The authors are architects and leading developers of 
  449. the User Interface class library. 
  450.  
  451. Note:  This book was written based on Version 2.1 of the class library. It does 
  452. not include information about new classes and features that have been added to 
  453. VisualAge C++ Version 3.0. 
  454.  
  455. Some technical articles have also been published in "OS/2 Developer", including 
  456. an article on INoteBook in the January/February 1994 edition, and two articles 
  457. that discuss creating new control classes in the September/October 1994 
  458. edition. These articles are also based on Version 2.1. 
  459.  
  460. IBM also offers educational courses for VisualAge C++ and the User Interface 
  461. class library.  For more information about current course offerings, in North 
  462. America, contact IBM Education and Training at 1-800-IBM-TEAC (1-800-426-8322). 
  463. Outside of North America, contact your local IBM office or supplier. 
  464.  
  465. Note:  The 1-800 number for Canada is being changed to 1-800-IBM-TEAC.  If you 
  466. call from Canada and this number is not yet in service, call the previous 
  467. number, 1-800-661-2131. 
  468.  
  469.  
  470. ΓòÉΓòÉΓòÉ 2.7. Can I Mix Object Files from Different Compilers? ΓòÉΓòÉΓòÉ
  471.  
  472. Question: 
  473.  
  474. Can I mix object (.OBJ) files compiled with an earlier version of C Set ++ with 
  475. VisualAge C++ .OBJ files? What about .OBJ files from other compilers, such as 
  476. Borland? 
  477.  
  478. Answer: 
  479.  
  480. You can link .OBJ files created with C Set ++ Version 2.0 or 2.1 with 
  481. VisualAge C++ .OBJ files. (Note that this does not apply to .OBJ files created 
  482. with a beta version of VisualAge C++.) 
  483.  
  484. You cannot link .OBJ files created using different compilers. You must 
  485. recompile your source files using the same compiler. 
  486.  
  487. However, you can call between executable modules (EXEs and DLLs) compiled with 
  488. different compilers or different versions of a compiler, providing: 
  489.  
  490.      The modules do not share a runtime environment. 
  491.      The calling conventions match. 
  492.      Only C or extern "C" functions are called. 
  493.  
  494.  For example, if you have a VisualAge C++ executable and a Borland DLL, and the 
  495.  above conditions are met, you can then call code from the Borland DLL, import 
  496.  and export data from it, and so on. 
  497.  
  498.  You cannot directly call C++ functions compiled with a different compiler 
  499.  because each compiler makes different assumptions about runtime environment 
  500.  and uses different algorithms for mangling C++ names. To call a C++ function, 
  501.  you must declare it as extern "C". 
  502.  
  503.  If you are linking with C Set ++ V2.x object files that use templates, you 
  504.  must compile your VisualAge C++ source files using the /Gk option and link 
  505.  using the /OLDCPP option to ensure the templates resolve correctly. (If you 
  506.  use icc to invoke the linker, specify /Gk /Tdp to pass the /OLDCPP linker 
  507.  option.) You must specify these options because template resolution methods 
  508.  changed for VisualAge C++. 
  509.  
  510.  Note:  You can mix C and C++ object modules from the same compiler and use a 
  511.  common runtime DLL. 
  512.  
  513.  
  514. ΓòÉΓòÉΓòÉ 2.8. What Are the Library Naming Conventions? ΓòÉΓòÉΓòÉ
  515.  
  516. Question: 
  517.  
  518. What are the naming conventions used for the static and dynamic runtime and 
  519. class libraries? 
  520.  
  521. Answer: 
  522.  
  523. The naming conventions for the libraries have changed for VisualAge C++ Version 
  524. 3.0. They now indicate the product version and platform, as well as a new 
  525. product prefix. 
  526.  
  527. You do not have to specify libraries at link time. The compiler imbeds 
  528. information in your .OBJ files about the runtime and class libraries to link 
  529. with, based on the compiler options you specify and the #pragma library 
  530. directives in the header files you include. 
  531.  
  532. The new convention for the C runtime libraries (which also include the I/O 
  533. Stream class library) is: 
  534.  
  535.   CPPpivvt
  536. where: 
  537.  
  538.  p   Is the platform or operating system. 
  539.  i   Is the library identifier. 
  540.  vv  Is the version number. 
  541.  t   Is the type of library 
  542.  
  543.  The resulting library names are: 
  544.  
  545.   ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  546.    Character         Significance
  547.    Position
  548.   ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  549.  
  550.  
  551.    1-3 4   5   6-7 8
  552.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  553.    CPP                 Product prefix
  554.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  555.        O               OS/2 platform
  556.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  557.            S           Single-thread environment
  558.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  559.            M           Multithread environment
  560.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  561.            N           No runtime environment (subsystem)
  562.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  563.                30      Version number (3.0)
  564.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  565.                    I   Import library
  566.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  567.                    O   Object library (contains initialization routines)
  568.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  569.                        Statically bound library (no eighth letter)
  570.  
  571.  The new convention for the class libraries, as well as for the Performance 
  572.  Analyzer libraries, .OBJ, and device driver, is: 
  573.  
  574.     CPPpiivt
  575.  where: 
  576.  
  577.  p   Is the platform or operating system. 
  578.  ii  Is the library identifier. 
  579.  v   Is the version number. 
  580.  t   Is the type of library. 
  581.  
  582.  The resulting library, .OBJ, and device driver names are: 
  583.  
  584.   ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  585.    Character         Significance
  586.    Position
  587.   ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  588.  
  589.  
  590.    1-3 4   5-6 7   8
  591.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  592.    CPP                 Product prefix
  593.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  594.        O               OS/2 platform
  595.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  596.            DI          Data Access IDL library
  597.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  598.            DS          Data Access static SQL library
  599.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  600.            OB          Open Class Base library (Collection, Data Types)
  601.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  602.            OC          Open Class library (single import library)
  603.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  604.            OD          Open Class DDE library
  605.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  606.            OM          Open Class Multimedia library
  607.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  608.            OR          Open Class resource DLLs
  609.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  610.            OU          Open Class User Interface base library
  611.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  612.            OV          Open Class Visual library
  613.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  614.            OX          Complex library
  615.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  616.            OY          Complex multithread library
  617.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  618.            PA          Performance Analyzer
  619.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  620.            SQ          Data Access resource DLLs
  621.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  622.            TR          Integration DLL
  623.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  624.            Vn          Open Class Visual sample library n
  625.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  626.                3       Version number 3.0
  627.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  628.                    I   Import library
  629.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  630.                    O   Object library (for building import libraries)
  631.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  632.                        Statically bound library (no eighth letter)
  633.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  634.                    U   U.S. English version of resource library
  635.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  636.                    J   Japanese version of resource library
  637.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  638.                    K   Korean version of resource library
  639.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  640.                    T   Taiwanese version of resource library
  641.    ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  642.                    P   Simplified Chinese version of resource library
  643.  
  644.  
  645. ΓòÉΓòÉΓòÉ 2.9. What Does Mangling Mean? ΓòÉΓòÉΓòÉ
  646.  
  647. Question: 
  648.  
  649. I have seen a number of references to mangling in the C++ information.  What 
  650. does it mean? 
  651.  
  652. Answer: 
  653.  
  654. When a C++ compiler compiles a program, it encodes all class, member, and 
  655. function names, as well as certain other identifiers, to include type and 
  656. scoping information. This is called mangling. Different compilers use different 
  657. mangling schemes. 
  658.  
  659. The linker uses the encoded or mangled name to ensure type-safe linkage. These 
  660. mangled names are used in the object files and in the final executable file. 
  661. Tools or code that references identifiers in these files must use the mangled 
  662. names, not the original names used in the source code. To decode or demangle 
  663. the names for VisualAge C++, you can use the functions defined in <demangle.h> 
  664. or the CPPFILT utility. For more information about demangling, see "Demangling 
  665. (Decoding) C++ Function Names" in the Programming Guide. For information about 
  666. CPPFILT, see the User's Guide. 
  667.  
  668.  
  669. ΓòÉΓòÉΓòÉ 3. Using Documentation and Help ΓòÉΓòÉΓòÉ
  670.  
  671. This section answers questions about the online and hardcopy information and 
  672. the online help: 
  673.  
  674.      How Do I Close the How Do I Panel? 
  675.      Where Is the Chapter on Compiler Options? 
  676.  
  677.  
  678. ΓòÉΓòÉΓòÉ 3.1. How Do I Close the How Do I Panel? ΓòÉΓòÉΓòÉ
  679.  
  680. Question: 
  681.  
  682. How do I close the How Do I panel?  When I click on the system icon, there is 
  683. no Close choice. 
  684.  
  685. Answer: 
  686.  
  687. To close the How Do I panel, press F3. 
  688.  
  689. You can also click mouse button 2 on the window to bring up a context menu for 
  690. it. From the context menu, select Exit. 
  691.  
  692. The other help functions (such as Search and Print) are also available from 
  693. this menu. 
  694.  
  695.  
  696. ΓòÉΓòÉΓòÉ 3.2. Where Is the Chapter on Compiler Options? ΓòÉΓòÉΓòÉ
  697.  
  698. Question: 
  699.  
  700. There used to be a chapter on compiler options in the Programming Guide, but I 
  701. can't find it now. Where is it? 
  702.  
  703. Answer: 
  704.  
  705. This chapter has been moved to the User's Guide, along with other information 
  706. about how to use the compiler and VisualAge C++ tools. 
  707.  
  708.  
  709. ΓòÉΓòÉΓòÉ 4. Using WorkFrame ΓòÉΓòÉΓòÉ
  710.  
  711. This section provides answers to commonly-asked questions about the 
  712. VisualAge C++ integrated development environment, WorkFrame. 
  713.  
  714.      How Do I Create a WorkFrame Project? 
  715.      How Do I Create a New Source File in a Project? 
  716.      How Do I Change What a Double-Click Does in My Project? 
  717.      How Can I Share Projects over a LAN? 
  718.      How Do I Copy a Project or Profile to Diskette? 
  719.      How Do I Set the Default Action for a Class? 
  720.      Why Doesn't Double-Clicking on Error Messages Work? 
  721.      Can I Inherit Environments from Multiple Projects? 
  722.      Why Is My Project's Inherited Environment Not What I Expect? 
  723.      Where Are Options for Inherited Actions Stored? 
  724.      Where Are My Migrated Profiles? 
  725.  
  726.  
  727. ΓòÉΓòÉΓòÉ 4.1. How Do I Create a WorkFrame Project? ΓòÉΓòÉΓòÉ
  728.  
  729. Question: 
  730.  
  731. How do I create a WorkFrame project? 
  732.  
  733. Answer: 
  734.  
  735. The easiest way to create a project is to use Project Smarts or the WorkFrame 
  736. Project template in the OS/2 Templates folder. 
  737.  
  738. If you already have files that you want to put in a project, or if you are 
  739. familiar with WorkFrame and want to build a project from scratch, use the 
  740. WorkFrame Project template. Open the Templates folder, select the WorkFrame 
  741. Project template, and drag it onto your desktop. 
  742.  
  743. If you are not familiar with WorkFrame, or if you're unsure how to set up a 
  744. certain type of project (a PM application, for example), use Project Smarts. 
  745. Project Smarts is a catalog of project skeletons for common types of 
  746. applications. Double-click on the Project Smarts object in the VisualAge C++ 
  747. folder to display the catalog.  Select the type of project you want to create, 
  748. then select the Create button. 
  749.  
  750.  
  751. ΓòÉΓòÉΓòÉ 4.2. How Do I Create a New Source File in a Project? ΓòÉΓòÉΓòÉ
  752.  
  753. Question: 
  754.  
  755. I have a project, but I want to add a new source file to it. How do I do that? 
  756.  
  757. Answer: 
  758.  
  759. Drag a data file template (from the Templates folder) onto the project.  You 
  760. can also create a project-scoped EDIT action in the Actions Profile with no 
  761. options, so that it brings up the editor with no file loaded. 
  762.  
  763. You can also use the command line to copy a file or invoke the editor on a new 
  764. file in the directory pointed to by the project. 
  765.  
  766.  
  767. ΓòÉΓòÉΓòÉ 4.3. How Do I Change What a Double-Click Does in My Project? ΓòÉΓòÉΓòÉ
  768.  
  769. Question: 
  770.  
  771. How do I change the default action associated with double-clicking on files in 
  772. my project? 
  773.  
  774. Answer: 
  775.  
  776. To change the default double-click action, you need to change the priority of 
  777. the project's actions in the Tools Setup. 
  778.  
  779. The priority is a numeric value from 0 to 99, with 99 being the highest 
  780. priority, specified on the Support page of the action's Settings notebook. 
  781. Actions in the list of actions are sorted in order of priority; the higher it 
  782. appears in the list, the higher its priority. 
  783.  
  784. When you double-click on a file, WorkFrame identifies all actions that match 
  785. that file name, and performs the action with the highest priority. Only actions 
  786. that are valid for that type of source file are considered.  For example, if 
  787. you set the VisualAge C++ Compiler action so that the only valid source files 
  788. are .cpp files, the Compiler will never be invoked by double-clicking on any 
  789. other type of file, regardless of the Compiler action's priority. 
  790.  
  791. A file's default action is always listed first on its pop-up menu.  (Pop-up 
  792. menu items are sorted by priority.) 
  793.  
  794. To change the default action for a file, select Change from the action's pop-up 
  795. menu to display its Settings notebook, and then change the priority value on 
  796. the Support page. Make sure the action you want to use is valid for the type of 
  797. file. 
  798.  
  799. Note:  If a file or object has no WorkFrame actions associated with it, or if 
  800. it a WorkFrame project, double-clicking on it performs the default Workplace 
  801. Shell Open action. 
  802.  
  803.  
  804. ΓòÉΓòÉΓòÉ 4.4. How Can I Share Projects over a LAN? ΓòÉΓòÉΓòÉ
  805.  
  806. Question: 
  807.  
  808. How can I share my WorkFrame projects with others over a LAN? 
  809.  
  810. Answer: 
  811.  
  812. You can easily share projects over a LAN by locating the project file itself on 
  813. the LAN, and then shadowing it to the client desktops. 
  814.  
  815. Your project source files can reside on the LAN, and you can copy project 
  816. WorkPlace Shell objects over the LAN (by dragging the project onto a remote 
  817. Drives folder and then dragging it out again onto the target machine).  Ensure 
  818. that your target machine is set up similar to your original machine (for 
  819. example, your source is in the same location; inherited projects, if any, also 
  820. exist; the executable files are present; and so on). If you are sharing code 
  821. over the LAN, you may find a source-control product such as CMVC for OS/2 
  822. helpful. 
  823.  
  824.  
  825. ΓòÉΓòÉΓòÉ 4.5. How Do I Copy a Project or Profile to Diskette? ΓòÉΓòÉΓòÉ
  826.  
  827. Question: 
  828.  
  829. I want to move my projects and profiles to a second machine that is not 
  830. connected to the LAN.  How do I copy my projects and profiles to a diskette, 
  831. and then to the new machine? 
  832.  
  833. Answer: 
  834.  
  835. There are two methods for copying projects and profiles to diskette: 
  836.  
  837.    1. Drag the project or profile icon from your desktop and drop in onto the 
  838.       icon for your diskette drive (make sure you have a diskette in the 
  839.       drive). On the target machine, insert the diskette, double-click on the 
  840.       icon for the diskette drive, and drag the project or profile icon to the 
  841.       desktop. 
  842.  
  843.    2. Compress the project or profile file using a compression program that 
  844.       preserves extended file attributes (such as the public domain zip and 
  845.       unzip programs). Project files and profiles are found in the \DESKTOP 
  846.       directory on your boot drive. Copy the compressed files onto the 
  847.       diskette, and then uncompress the files under the \DESKTOP directory on 
  848.       the target machine. 
  849.  
  850.  
  851. ΓòÉΓòÉΓòÉ 4.6. How Do I Set the Default Action for a Class? ΓòÉΓòÉΓòÉ
  852.  
  853. Question: 
  854.  
  855. How do I set the default action for a class (such as COMPILE)? 
  856.  
  857. Answer: 
  858.  
  859. The default action for a class is simply the action that has the highest 
  860. priority within that class. 
  861.  
  862. The priority is a numeric value from 0 to 99, with 99 being the highest 
  863. priority, specified on the Support page of the action's Settings notebook. 
  864. Actions in the list of actions are sorted in order of priority; the higher it 
  865. appears in the list, the higher its priority. 
  866.  
  867. To make an action the default, change the priority value in its Settings 
  868. notebook so that the value is higher than the other actions in that class. (To 
  869. display the Settings notebook, select Change from the action's pop-up menu.) 
  870.  
  871. Note that the default action for a class also depends on the type of file that 
  872. it is invoked on. For example, suppose the Resource Compile action has the 
  873. highest priority among COMPILE actions.  Resource Compile is only valid for .rc 
  874. files.  If you invoke COMPILE on a .cpp file, WorkFrame skips the Resource 
  875. Compile action because it is not valid for the type of file.  WorkFrame 
  876. performs the action with the highest priority that is valid for a .cpp file. 
  877.  
  878. In most cases, the default action for a class is not important. However, it is 
  879. important for the EDIT class. When you double-click on error messages in the 
  880. monitor box, or invoke the editor from one of the other tools, the default Edit 
  881. action (and default editor) is used. 
  882.  
  883.  
  884. ΓòÉΓòÉΓòÉ 4.7. Why Doesn't Double-Clicking on Error Messages Work? ΓòÉΓòÉΓòÉ
  885.  
  886. Question: 
  887.  
  888. I thought that double-clicking on an error in the monitor window was supposed 
  889. to launch the editor and load the source file that has the error.  Why doesn't 
  890. this work for me? 
  891.  
  892. Answer: 
  893.  
  894.      Make sure the error message was generated for a source file. For error 
  895.       messages generated by tools like the linker, double-clicking on the 
  896.       message does not work because you cannot edit the object file for which 
  897.       the message was generated. 
  898.      If you added or changed the action that generated the message, and it 
  899.       uses the WorkFrame default action support DLL, ensure the error template 
  900.       is specified correctly. 
  901.      If the error message uses unqualified file names, the editor may not be 
  902.       able to load the file. If this is the case, go to your Project view and 
  903.       edit the file from there. 
  904.      If the messages were generated by the Make action, and the make file you 
  905.       used was not generated by WorkFrame (or you edited the file), the make 
  906.       file may not contain information the WorkFrame needs to determine what 
  907.       tool should parse the errors. WorkFrame puts special tags before each 
  908.       OS/2 command in the make file to indicate the tool to call. 
  909.  
  910.       If you use the Build action instead of Make, this problem does not occur. 
  911.       If you don't want to use Build, either regenerate your make file using 
  912.       WorkFrame, or add the tags to your own make file. The tags have the 
  913.       format: 
  914.  
  915.                @echo WF::class::action
  916.  
  917.       where class is the action class (such as COMPILE), and action is the 
  918.       action name (such as VisualAge C++). 
  919.  
  920.  
  921. ΓòÉΓòÉΓòÉ 4.8. Can I Inherit Environments from Multiple Projects? ΓòÉΓòÉΓòÉ
  922.  
  923. Question: 
  924.  
  925. Can I inherit environments from multiple projects? 
  926.  
  927. Answer: 
  928.  
  929. Yes.  Specify the list of projects in the Inheritance page of the project's 
  930. Settings notebook. 
  931.  
  932.  
  933. ΓòÉΓòÉΓòÉ 4.9. Why Is My Project's Inherited Environment Not What I Expect? ΓòÉΓòÉΓòÉ
  934.  
  935. Question: 
  936.  
  937. My project inherits from more than one project.  One of the actions, variables, 
  938. or types is not what I expected.  Why? 
  939.  
  940. Answer: 
  941.  
  942. When you inherit from multiple projects, conflicts can occur between the 
  943. different environments.  The rules that WorkFrame uses to resolve these 
  944. conflicts are described in the WorkFrame section of the User's Guide. 
  945.  
  946.  
  947. ΓòÉΓòÉΓòÉ 4.10. Where Are Options for Inherited Actions Stored? ΓòÉΓòÉΓòÉ
  948.  
  949. Question: 
  950.  
  951. When I inherit an action from another project's environment, are the options 
  952. copied from the base action stored locally with my new project?  Or do they 
  953. remain with the project where the action was originally defined? 
  954.  
  955. Answer: 
  956.  
  957. You have a choice.  By default, the options remain with the base project, but 
  958. you can also copy the options and store them locally.  You can change the 
  959. options of an inherited action, but then you will be changing the options for 
  960. other projects that also inherit the action.  If the options are stored 
  961. locally, you can decide to use the inherited options instead by deleting the 
  962. local options.  (Select Options->Delete from the action's pop-up menu.) 
  963.  
  964.  
  965. ΓòÉΓòÉΓòÉ 4.11. Where Are My Migrated Profiles? ΓòÉΓòÉΓòÉ
  966.  
  967. Question: 
  968.  
  969. I just migrated my projects and profiles from WorkFrame/2 V2.1. I found the new 
  970. projects, but I cannot find the profiles. Did the migration for the profiles 
  971. fail? 
  972.  
  973. Answer: 
  974.  
  975. In VisualAge C++ V3.0, WorkFrame projects and profiles are merged.  Your 
  976. migrated profiles have been merged into your migrated projects. 
  977.  
  978.  
  979. ΓòÉΓòÉΓòÉ 5. Creating Applications with the Visual Builder ΓòÉΓòÉΓòÉ
  980.  
  981. This section answers questions you may have about using the Visual Builder to 
  982. construct parts and applications. 
  983.  
  984.      How Can I Determine Which Connections Are Executed? 
  985.      How Can I Tell What Parameters an Action Can Take? 
  986.      How Do I Support Different Display Resolutions? 
  987.      Do I Have to Hardcode Limits for Fields? 
  988.      Why Are My Container Columns Invisible? 
  989.      Why Can't I Select Parts in the Group Box? 
  990.      How Should I Update a Composite Part? 
  991.      Why Can't I Tear Off a Nonvisual Part's Attribute? 
  992.      Why Doesn't My Drop-Down Combo Box Drop Down? 
  993.      Why Does My Part Get Compiler Errors? 
  994.      Why Does My Part Get Unresolved External Link Errors? 
  995.  
  996.  
  997. ΓòÉΓòÉΓòÉ 5.1. How Can I Determine Which Connections Are Executed? ΓòÉΓòÉΓòÉ
  998.  
  999. Question: 
  1000.  
  1001. My application doesn't run as I expected. Is there a way to determine which 
  1002. connections are being executed? 
  1003.  
  1004. Answer: 
  1005.  
  1006. Yes.  The Visual Builder generates trace macros in its connection classes to 
  1007. indicate when a connection has been triggered. To view this information: 
  1008.  
  1009.    1. When you compile the generated source code for your parts, define the 
  1010.       IC_TRACE_DEVELOP macro. 
  1011.  
  1012.    2. Enable tracing for the class libraries by entering 
  1013.  
  1014.               SET ICLUI TRACE=ON
  1015.       (You could also set this variable in your CONFIG.SYS file.) 
  1016.  
  1017.    3. Indicate where the trace information should be sent by setting the ICLUI 
  1018.       TRACETO environment variable.  For example: 
  1019.  
  1020.               SET ICLUI TRACETO=STDERR
  1021.       sends the information to stderr, which you can then redirect to a file. 
  1022.  
  1023.  For more details on tracing, see the ITrace class information in the Open 
  1024.  Class Library Reference. 
  1025.  
  1026.  Once you have enabled tracing, look for the following possible problems: 
  1027.  
  1028.      Initializing attribute-to-attribute connections can execute other 
  1029.       connections that are dependent on the target attribute. 
  1030.  
  1031.      A connection involving an attribute as the source might not have been 
  1032.       executed because the attribute does not have an event identification 
  1033.       defined for it. 
  1034.  
  1035.      A connection involving an attribute might not have been executed because 
  1036.       the attribute-changed event happens only when the attribute's value 
  1037.       changes. For example, setting the value of a Boolean attribute to true 
  1038.       when the current value is already true might not execute the 
  1039.       attribute-changed event. Another example is when the attribute is a 
  1040.       pointer to an object and the pointer does not change but the contents of 
  1041.       the object does. If your application must execute an event when the 
  1042.       attribute's set member function is called, add a notification event. 
  1043.  
  1044.      If your application is getting an old attribute value instead of a new 
  1045.       one, the attribute's set member function might be executing its 
  1046.       attribute-changed event before the value actually changes. Make sure you 
  1047.       update the attribute's value before you signal the attribute-changed 
  1048.       event. 
  1049.  
  1050.      Whenever an action executes an event, the event happens before the 
  1051.       actionResult value is set for the action. For example, Object Factory 
  1052.       parts have a new action that instantiates an object of the type defined 
  1053.       for the factory part. The new action starts an event called newEvent 
  1054.       before the result of new is returned, so actionResult still contains the 
  1055.       old value. 
  1056.  
  1057.  
  1058. ΓòÉΓòÉΓòÉ 5.2. How Can I Tell What Parameters an Action Can Take? ΓòÉΓòÉΓòÉ
  1059.  
  1060. Question: 
  1061.  
  1062. I have an incomplete connection.  How can I tell what parameters an action 
  1063. takes and what default values the parameters can be initialized to? 
  1064.  
  1065. Answer: 
  1066.  
  1067. Select the target part that the action is defined for. From its context menu, 
  1068. select Browse feature implementations. The Browse feature implementation window 
  1069. shows the full signature of the action, including its return type. You can then 
  1070. see what parameters an action supports, the type of each parameter, and any 
  1071. default values. 
  1072.  
  1073.  
  1074. ΓòÉΓòÉΓòÉ 5.3. How Do I Support Different Display Resolutions? ΓòÉΓòÉΓòÉ
  1075.  
  1076. Question: 
  1077.  
  1078. How should I build my application views to ensure they display correctly on 
  1079. different display resolutions and monitors (VGA, SVGA, and so on)? 
  1080.  
  1081. Answer: 
  1082.  
  1083. Build your views using a multicell canvas (IMultiCellCanvas) as the client 
  1084. instead of a canvas (ICanvas). 
  1085.  
  1086.  
  1087. ΓòÉΓòÉΓòÉ 5.4. Do I Have to Hardcode Limits for Fields? ΓòÉΓòÉΓòÉ
  1088.  
  1089. Question: 
  1090.  
  1091. I initialize many parts in my views through the parts' settings editors. How 
  1092. can I avoid hardcoding values for fields, such as the limit field for the entry 
  1093. field part? 
  1094.  
  1095. Answer: 
  1096.  
  1097. Create a separate file for your application and use #define directives to 
  1098. define macros for your field lengths. For example, for an entry field for 
  1099. names, you might define a macro NAME_LENGTH to 50. You would then specify 
  1100. #NAME_LENGTH for the entry field's Limit field. 
  1101.  
  1102. To ensure that your view will compile, add the name of the file that contains 
  1103. the #define directives to the Required include files field in the Class Editor. 
  1104.  
  1105.  
  1106. ΓòÉΓòÉΓòÉ 5.5. Why Are My Container Columns Invisible? ΓòÉΓòÉΓòÉ
  1107.  
  1108. Question: 
  1109.  
  1110. Some of the container columns that I dropped on a container aren't visible. 
  1111. Why? 
  1112.  
  1113. Answer: 
  1114.  
  1115. When you build a container using the Composition Editor, the Visual Builder 
  1116. shows only those columns that fit within the container. To access the rest of 
  1117. the columns, either resize the container to a larger size, or select Tabbing 
  1118. and Depth Order from the context menu of the container. From the Tabbing and 
  1119. Depth Order window, you can open the settings notebook of any of the container 
  1120. columns listed by double-clicking on their names. You can delete a column by 
  1121. selecting Delete from the context menu of a column. 
  1122.  
  1123. Also, if you define several container columns and then change the view type to 
  1124. something other than showDetailsView, your columns may become invisible. You 
  1125. can always enable your users to switch the view type of a container at run time 
  1126. (for example, from a menu bar). 
  1127.  
  1128.  
  1129. ΓòÉΓòÉΓòÉ 5.6. Why Can't I Select Parts in the Group Box? ΓòÉΓòÉΓòÉ
  1130.  
  1131. Question: 
  1132.  
  1133. I dropped a group box or outline box and sized it so that it contains other 
  1134. visual parts that I added to my view. Now I can't select the visual parts that 
  1135. the group box or outline box contains.  Why? 
  1136.  
  1137. Answer: 
  1138.  
  1139. The visual parts inside the group or outline box are siblings of the box, not 
  1140. children of it. Because you created the box after the visual parts it contains, 
  1141. the depth order of the box is lower than those of the contained visual parts. 
  1142.  
  1143. To change the depth order, select Tabbing and Depth Order from the context menu 
  1144. of the parent of these parts (that is, the canvas that contains them). Then 
  1145. select and drag the group box or outline box and drop it so that it appears 
  1146. before all of the visual parts you want it to contain. 
  1147.  
  1148. To avoid this problem, create the group box or outline box first and then place 
  1149. the other parts on top of it. 
  1150.  
  1151.  
  1152. ΓòÉΓòÉΓòÉ 5.7. How Should I Update a Composite Part? ΓòÉΓòÉΓòÉ
  1153.  
  1154. Question 
  1155.  
  1156. I am editing a visual part, and need to update one of the composite parts it 
  1157. contains. What is the easiest way to update the composite part? 
  1158.  
  1159. Answer: 
  1160.  
  1161.    1. Edit the part you want to change. (You can leave the first edit session 
  1162.       open.) 
  1163.  
  1164.    2. Update the composite part, save it, and close the second edit session. 
  1165.       Note that the changes will not appear in your first edit session until 
  1166.       you close and reopen the session. 
  1167.  
  1168.  
  1169. ΓòÉΓòÉΓòÉ 5.8. Why Can't I Tear Off a Nonvisual Part's Attribute? ΓòÉΓòÉΓòÉ
  1170.  
  1171. Question: 
  1172.  
  1173. I created a nonvisual part with an attribute that is a pointer to a collection 
  1174. object.  I want to tear off this attribute to make connections to some of its 
  1175. actions, but I can't.  Why not? 
  1176.  
  1177. Answer: 
  1178.  
  1179. Collections are implemented using C++ template classes. When you tear off an 
  1180. attribute, Visual Builder creates a variable part and sets it to the type of 
  1181. the torn-off attribute. However, variables that represent template-based 
  1182. classes are not currently supported. 
  1183.  
  1184. To avoid the need to tear off attributes, implement actions to work with the 
  1185. collection attribute directly in your nonvisual part. 
  1186.  
  1187.  
  1188. ΓòÉΓòÉΓòÉ 5.9. Why Doesn't My Drop-Down Combo Box Drop Down? ΓòÉΓòÉΓòÉ
  1189.  
  1190. Question: 
  1191.  
  1192. Why doesn't my drop-down combo box drop down? 
  1193.  
  1194. Answer: 
  1195.  
  1196. Make sure a default height is specified on the Size/Position settings page. 
  1197. You must set the height to a value higher than 0. 
  1198.  
  1199.  
  1200. ΓòÉΓòÉΓòÉ 5.10. Why Does My Part Get Compiler Errors? ΓòÉΓòÉΓòÉ
  1201.  
  1202. Question: 
  1203.  
  1204. I constructed my application using the Composition Editor, but when I try to 
  1205. compile it, the compiler generates errors. Shouldn't any constructed part 
  1206. compile without error? 
  1207.  
  1208. Answer: 
  1209.  
  1210. The Composition Editor does not prevent you from making connections that will 
  1211. not compile correctly.  You must ensure you match types correctly on 
  1212. attribute-to-attribute connections and parameter connections. The easiest way 
  1213. to avoid incompatible-type errors is to browse feature implementations using 
  1214. the Composition Editor's contextual menu. 
  1215.  
  1216.  
  1217. ΓòÉΓòÉΓòÉ 5.11. Why Does My Part Get Unresolved External Link Errors? ΓòÉΓòÉΓòÉ
  1218.  
  1219. Question: 
  1220.  
  1221. When I compile and link my part, the linker generates unresolved external 
  1222. errors.  Why? 
  1223.  
  1224. Answer: 
  1225.  
  1226. This could be caused by one of the following: 
  1227.  
  1228.      Visual Builder uses template classes to implement variable parts, 
  1229.       collections, collection-view list boxes, and collection-view combo boxes. 
  1230.       When you compile, information required to resolve the templates is put 
  1231.       into the TEMPINC subdirectory (under the directory where your part code 
  1232.       resides). If you made changes to any template-based parts, delete the 
  1233.       contents of TEMPINC before you recompile to ensure that you are not using 
  1234.       the old template information. 
  1235.  
  1236.      If you compiled your nonvisual parts separately to create a DLL, you must 
  1237.       link the .LIB file for that DLL into your application to resolve 
  1238.       references to the nonvisual parts. You can either: 
  1239.  
  1240.         -  In the Class Editor, add the .LIB file name for each nonvisual part 
  1241.            contained in the DLL. 
  1242.         -  Put a #pragma library directive in the header file for your 
  1243.            nonvisual parts.  This directive tells the compiler and linker to 
  1244.            link in the library specified.  #pragma library is described in the 
  1245.            Language Reference. 
  1246.  
  1247.  
  1248. ΓòÉΓòÉΓòÉ 6. Editing with the VisualAge C++ Editor ΓòÉΓòÉΓòÉ
  1249.  
  1250. This section answers questions about how to use the VisualAge C++ Editor. 
  1251.  
  1252.      How Can I Make the Editor Behave Like My Favorite Editor? 
  1253.      What Is the Gray Area Shown at the Top of My File? 
  1254.      Why Do I Have Multiple Copies of the Error Log? 
  1255.      Can I Extract the Text in a Marked Block? 
  1256.      How Do I Put the Contents of a Line in a Macro? 
  1257.      How Do I Issue an OS/2 Command from a Macro? 
  1258.      How Do I Debug a REXX Macro? 
  1259.      How Do I Unload the Editor from Memory? 
  1260.      How Can I Get File or Quit to Invoke My Macro? 
  1261.  
  1262.  
  1263. ΓòÉΓòÉΓòÉ 6.1. How Can I Make the Editor Behave Like My Favorite Editor? ΓòÉΓòÉΓòÉ
  1264.  
  1265. Question: 
  1266.  
  1267. How can I make the Editor behave like my favourite editor and other editors on 
  1268. the market (such as Brief)?. 
  1269.  
  1270. Answer: 
  1271.  
  1272. In the Options menu, the Key behavior choice cascades to a menu of commonly 
  1273. used editors. Select from this menu to make the Editor behave like the selected 
  1274. editor. This affects only the current document in the current edit session. 
  1275.  
  1276. To save the behavior for all documents across sessions, select Save key 
  1277. behavior from the Key behavior cascade. To customize the behavior of any subset 
  1278. of keys, use the Customize choice from the Options menu. 
  1279.  
  1280.  
  1281. ΓòÉΓòÉΓòÉ 6.2. What Is the Gray Area Shown at the Top of My File? ΓòÉΓòÉΓòÉ
  1282.  
  1283. Question: 
  1284.  
  1285. What is the gray area shown at the top of my file, and why is it a different 
  1286. size for different files? 
  1287.  
  1288. Answer: 
  1289.  
  1290. An edit window is created based on the size and position of the last window 
  1291. size and position (even from another session). The area in which the file is 
  1292. displayed is fixed until you change it. If the file loaded into the window is 
  1293. not large enough to fill the edit area, the gray area fills the remaining 
  1294. space. As the file size increases, the gray area diminishes. When the file 
  1295. fills the window and scrolling is required, the gray area disappears. 
  1296.  
  1297.  
  1298. ΓòÉΓòÉΓòÉ 6.3. Why Do I Have Multiple Copies of the Error Log? ΓòÉΓòÉΓòÉ
  1299.  
  1300. Question: 
  1301.  
  1302. I start the editor from the command line.  In every directory where I start it, 
  1303. it creates a new error log file. Why?  How do I specify one location for this 
  1304. file? 
  1305.  
  1306. Answer: 
  1307.  
  1308. The editor uses the environment variable TMPDIR to determine where to create 
  1309. the error log. Make sure you have specified a valid drive and directory for 
  1310. this variable.  If you want to specify only a drive, you must follow it with a 
  1311. backslash, for example: 
  1312.  
  1313.   SET TMPDIR=f:/
  1314.  
  1315.  
  1316. ΓòÉΓòÉΓòÉ 6.4. Can I Extract the Text in a Marked Block? ΓòÉΓòÉΓòÉ
  1317.  
  1318. Question: 
  1319.  
  1320. I have a block of marked text.  Can I extract or query the text in the block? 
  1321.  
  1322. Answer: 
  1323.  
  1324. There is no direct way to extract or query the text marked by the current 
  1325. block. However, you can write a macro to extract the text. You need to: 
  1326.  
  1327.    1. Determine what document has the selected block of text (BLOCKDOC). 
  1328.    2. Determine the BLOCKTYPE. 
  1329.    3. Determine what you need to extract, based on the BLOCKTYPE. For example, 
  1330.       for a RECTANGLE: 
  1331.         a. Find the columns spanned by the rectangle (BLOCKSTART and BLOCKEND). 
  1332.         b. Determine how many elements the block crosses (BLOCKLENGTH). 
  1333.    4. Position the cursor on the first included element (BLOCK FIND). 
  1334.    5. Extract the content of the element. 
  1335.    6. Throw away the characters not included. 
  1336.    7. Move to the next element and extract its content. 
  1337.    8. Repeat the above two steps (6 and 7) until finished. 
  1338.  
  1339.  Your macro might contain the following statements: 
  1340.  
  1341.     QUERY BLOCKTYPE
  1342.     QUERY BLOCKDOC
  1343.     BLOCK FIND
  1344.     BLOCK FIND END
  1345.     QUERY BLOCKSTART
  1346.     QUERY BLOCKLENGTH
  1347.     QUERY BLOCKEND
  1348.     EXTRACT CONTENT
  1349.  
  1350.  
  1351. ΓòÉΓòÉΓòÉ 6.5. How Do I Put the Contents of a Line in a Macro? ΓòÉΓòÉΓòÉ
  1352.  
  1353. Question: 
  1354.  
  1355. How do I put the contents of a line or editor variable in a macro? 
  1356.  
  1357. Answer: 
  1358.  
  1359. Use the extract command. The command extract content puts the content of the 
  1360. current line into the REXX variable content. You can also use the command 
  1361. extract content into x to extract the line's content into the variable x. 
  1362.  
  1363.  
  1364. ΓòÉΓòÉΓòÉ 6.6. How Do I Issue an OS/2 Command from a Macro? ΓòÉΓòÉΓòÉ
  1365.  
  1366. Question: 
  1367.  
  1368. How do I issue an OS/2 command from a REXX macro? 
  1369.  
  1370. Answer: 
  1371.  
  1372. Use the REXX ADDRESS command.  For details on how to use this command, see the 
  1373. REXX Information in the OS/2 Information folder. 
  1374.  
  1375.  
  1376. ΓòÉΓòÉΓòÉ 6.7. How Do I Debug a REXX Macro? ΓòÉΓòÉΓòÉ
  1377.  
  1378. Question: 
  1379.  
  1380. One of my editor macros fails with an error code.  How can I debug it to find 
  1381. out what's wrong? 
  1382.  
  1383. Answer: 
  1384.  
  1385. To debug a REXX macro, use the REXX trace utility and the editor's Macro Log 
  1386. (from the Window menu). If you put TRACE ALL as the first statement in your 
  1387. REXX macro, the Macro Log displays every REXX statement executed. If you put 
  1388. TRACE ?ALL as the first statement, the editor prompts you with the REXX Trace 
  1389. Read dialog for each statement, in addition to displaying them in the Macro 
  1390. Log. 
  1391.  
  1392.  
  1393. ΓòÉΓòÉΓòÉ 6.8. How Do I Unload the Editor from Memory? ΓòÉΓòÉΓòÉ
  1394.  
  1395. Question: 
  1396.  
  1397. I noticed that after I close my editor session, the editor remains loaded in 
  1398. memory for some time afterwards.  Why does this happen, and how can I unload it 
  1399. from memory? 
  1400.  
  1401. Answer: 
  1402.  
  1403. The editor remains in memory so that startup is faster when you edit your next 
  1404. file. Closing the editor from the OS/2 Window list only closes the document 
  1405. being edited. To close the editor itself and unload it from memory, use the 
  1406. command: 
  1407.  
  1408.    lxpm /cm exit
  1409.  
  1410. or select Close editor from the Windows menu. 
  1411.  
  1412. There is also an editor parameter, TIMOUT, that you can query and set from the 
  1413. command line, from an editor macro, or from a program. 
  1414.  
  1415. The default setting is five minutes; five minutes after the last edit window is 
  1416. closed, the editor closes itself. If you set it to 0, the editor closes 
  1417. immediately after the last edit window is closed, regardless of whether you 
  1418. select Close Editor or not. 
  1419.  
  1420. See the Editor Command Reference for more details on setting and querying 
  1421. parameters. 
  1422.  
  1423.  
  1424. ΓòÉΓòÉΓòÉ 6.9. How Can I Get File or Quit to Invoke My Macro? ΓòÉΓòÉΓòÉ
  1425.  
  1426. Question: 
  1427.  
  1428. When I save a file or quit out of the editor, I want my own macro to be invoked 
  1429. first before the editor saves the file or exits.  Can I do this? 
  1430.  
  1431. Answer: 
  1432.  
  1433. Yes. The easiest way is to define a synonym for these functions. For example, 
  1434. if your macro is called mymacro.lx: 
  1435.  
  1436.   SYNONYM.QUIT mymacro quit
  1437.   SYNONUM.QQUIT mymacro qquit
  1438.   SYNONYM.SAVE mymacro save
  1439. (Note that the File action is the Save and Quit actions put together.) 
  1440.  
  1441. Then in your mymacro.lx, issue the command 
  1442.  
  1443.   'LXN' parm
  1444. at the end of your processing. 
  1445.  
  1446. Alternatively, you could define the following synonym: 
  1447.  
  1448.   SYNONYM.QUIT MULT; mymacro quit ; LXN QUIT
  1449. which does not require you to add the extra command to mymacro.lx. 
  1450.  
  1451.  
  1452. ΓòÉΓòÉΓòÉ 7. Coding in C/C++ ΓòÉΓòÉΓòÉ
  1453.  
  1454. This section addresses questions you may have in creating your source files, 
  1455. including the correct use of operators, functions, and programming techniques. 
  1456.  
  1457.      How Does malloc Allocate Memory? 
  1458.      How Do Signal and Exception Handling Work in DLLs? 
  1459.      How Do I Export C++ Members from a DLL? 
  1460.      Can I Export an Empty Class? 
  1461.      How Do I Use C Objects in C++ Programs? 
  1462.      How Do I Call C++ Functions from C Code? 
  1463.      How Can I Share a Data Segment? 
  1464.      Should I Use Automatic Local Variables or new? 
  1465.      Can I Throw an Exception in One Thread and Catch It in Another? 
  1466.      What Are the Equivalent Calling Conventions in C++? 
  1467.      What Calling Convention Should I Use for Multiple Languages? 
  1468.      Can I Use Library Extensions at the ANSI/ISO Language Level? 
  1469.      Should I Use DosCreateThread or _beginthread? 
  1470.      Can I Use C Functions on a File Opened with DosOpen? 
  1471.      Can I Change the Parent's Environment from a Child Process? 
  1472.      How Can I Perform Port Input/Output? 
  1473.      Can Signals Be Raised Across Processes? 
  1474.      What Should I Call in _DLL_InitTerm? 
  1475.  
  1476.  
  1477. ΓòÉΓòÉΓòÉ 7.1. How Does malloc Allocate Memory? ΓòÉΓòÉΓòÉ
  1478.  
  1479. Question: 
  1480.  
  1481. How does malloc allocate memory internally, and how much overhead does it 
  1482. require? Should I use malloc or DosAllocMem? 
  1483.  
  1484. Answer: 
  1485.  
  1486. malloc adds 8 bytes to the requested size (16 bytes if you are using debug 
  1487. memory management), and then rounds the resulting size to the next multiple of 
  1488. 16 bytes. Of this, at most 16 bytes is used by malloc and the other memory 
  1489. management functions for internal information. 
  1490.  
  1491. Note:  Do not code your program to rely on the underlying implementation of any 
  1492. function. The implementation could change, which would then cause your program 
  1493. to fail. 
  1494.  
  1495. In most cases, there is no benefit to calling DosAllocMem over malloc. In 
  1496. previous releases of C Set ++, we recommended you call DosAllocMem for large 
  1497. blocks of memory; however, with the changes to runtime memory management in 
  1498. this release, malloc is equally efficient with large blocks. 
  1499.  
  1500.  
  1501. ΓòÉΓòÉΓòÉ 7.2. How Do Signal and Exception Handling Work in DLLs? ΓòÉΓòÉΓòÉ
  1502.  
  1503. Question: 
  1504.  
  1505. How do signal handling and exception handling work in DLLs? 
  1506.  
  1507. Answer: 
  1508.  
  1509. You must clearly differentiate between OS/2 exception handlers and C signal 
  1510. handlers.  In VisualAge C++, the #pragma handler directive registers the OS/2 
  1511. exception handler.  The signal function registers a C signal handler.  To 
  1512. correctly generate signals from OS/2 exceptions, VisualAge C++ must have its 
  1513. own OS/2 exception handler registered. 
  1514.  
  1515. To automatically register C signal handlers, use the signal function. The 
  1516. default C exception handler _Exception converts OS/2 exceptions into C signals, 
  1517. and calls C signal handlers that are registered by signal. _Exception is 
  1518. automatically registered for the main function; you must explicitly register it 
  1519. for every DLL entry point using #pragma handler. 
  1520.  
  1521. You can also use #pragma handler to register your own exception handler for a 
  1522. function.  For example, to register handler as the exception handler for 
  1523. blivet, specify #pragma(blivet, handler). 
  1524.  
  1525. Note: 
  1526.  
  1527. For more information on signal and exception handling, see the Programming 
  1528. Guide. 
  1529.  
  1530.  
  1531. ΓòÉΓòÉΓòÉ 7.3. How Do I Export C++ Members from a DLL? ΓòÉΓòÉΓòÉ
  1532.  
  1533. Question: 
  1534.  
  1535. How do I export C++ member functions from a DLL? The _Export keyword is not 
  1536. valid in the function prototype. 
  1537.  
  1538. Answer: 
  1539.  
  1540. Specify the _Export keyword in either the class definition or the function 
  1541. definition, as in the following example: 
  1542.  
  1543.   class A {
  1544.      void _Export fun1();
  1545.   };
  1546.  
  1547.   void _Export A::fun1() {
  1548.       return;
  1549.   }
  1550.  
  1551.  
  1552. ΓòÉΓòÉΓòÉ 7.4. Can I Export an Empty Class? ΓòÉΓòÉΓòÉ
  1553.  
  1554. Question: 
  1555.  
  1556. Can I export an empty class and use it somewhere else? 
  1557.  
  1558. Answer: 
  1559.  
  1560. You can only export member functions, static data members, and instances of 
  1561. classes. 
  1562.  
  1563.  
  1564. ΓòÉΓòÉΓòÉ 7.5. How Do I Use C Objects in C++ Programs? ΓòÉΓòÉΓòÉ
  1565.  
  1566. Question: 
  1567.  
  1568. I am having a problem linking my C++ code with C objects. Why does the linker 
  1569. say that there is an unresolved external reference to the C objects? 
  1570.  
  1571. Answer: 
  1572.  
  1573. You must tell the C++ compiler that an external name uses C naming conventions 
  1574. by using extern "C" when you declare the function. Otherwise, the C++ compiler 
  1575. mangles the name. (For an explanation of what "mangles" means, see What Does 
  1576. Mangling Mean?.) Note that using the keywords for calling conventions (_System, 
  1577. _Optlink, and so on) in your function definition is equivalent to defining the 
  1578. function as extern "C". 
  1579.  
  1580.  
  1581. ΓòÉΓòÉΓòÉ 7.6. How Do I Call C++ Functions from C Code? ΓòÉΓòÉΓòÉ
  1582.  
  1583. Question: 
  1584.  
  1585. I know that I can call C functions from a C++ file using extern "C" 
  1586. declarations, but how do I call a C++ routine in a .CPP file from a C file? 
  1587.  
  1588. Answer: 
  1589.  
  1590. Define the C++ function as extern "C" in your C++ code, and call it from the C 
  1591. code. Note that C functions compiled with the C compiler cannot directly call 
  1592. C++ member functions. To get around this, add an extern "C" function in your 
  1593. C++ code that calls your C++ member function. Then call that extra function 
  1594. from your C code. 
  1595.  
  1596.  
  1597. ΓòÉΓòÉΓòÉ 7.7. How Can I Share a Data Segment? ΓòÉΓòÉΓòÉ
  1598.  
  1599. Question: 
  1600.  
  1601. I want multiple copies of my DLL to share a single data segment.  How do I do 
  1602. that? 
  1603.  
  1604. Answer: 
  1605.  
  1606. To share a data segment: 
  1607.  
  1608.    1. Use #pragma data_seg to name the data segment you want to share. 
  1609.    2. Specify DATA MULTIPLE NONSHARED in the .DEF file for your DLL. 
  1610.    3. Put a SEGMENTS statement in the .DEF file specifying that the named 
  1611.       segment is SINGLE SHARED. 
  1612.    4. If you need to initialize data structures in the shared segment, you will 
  1613.       need to add to your DLL initialization routine.  Remember that this 
  1614.       routine is run for each instance of your DLL, so you will need to ensure 
  1615.       your data structures are only initialized once.  For more information 
  1616.       about DLL initialization, see "Building DLLs" in the Programming Guide. 
  1617.  
  1618.  
  1619. ΓòÉΓòÉΓòÉ 7.8. Should I Use Automatic Local Variables or new? ΓòÉΓòÉΓòÉ
  1620.  
  1621. Question: 
  1622.  
  1623. When should I use automatic local variables, and when should I use the new 
  1624. operator to create variables? 
  1625.  
  1626. Answer: 
  1627.  
  1628. When you can, use automatic variables.  Because they are automatically 
  1629. destroyed when the block in which they were declared ends, you do not have to 
  1630. delete them and the stack space is returned. For example, a loop counter would 
  1631. typically be an automatic variable. 
  1632.  
  1633. However, if you need the variable to remain in existence outside that block, 
  1634. use new.  (Alternatively, you could declare the variable as static or extern.) 
  1635.  
  1636. Remember that automatic variables use stack space. If you are limited to a 
  1637. small stack, which is common when you write threads, you may need to use new 
  1638. and delete for large variables that would typically be automatic. 
  1639.  
  1640.  
  1641. ΓòÉΓòÉΓòÉ 7.9. Can I Throw an Exception in One Thread and Catch It in Another? ΓòÉΓòÉΓòÉ
  1642.  
  1643. Question: 
  1644.  
  1645. Can I throw an exception in one thread and catch it in another? 
  1646.  
  1647. Answer: 
  1648.  
  1649. No.  You can only catch exceptions that are thrown from your own thread of 
  1650. execution.  If you try to throw an exception from one thread to another, the 
  1651. exception will not be caught, and your application will end. 
  1652.  
  1653.  
  1654. ΓòÉΓòÉΓòÉ 7.10. What Are the Equivalent Calling Conventions in C++? ΓòÉΓòÉΓòÉ
  1655.  
  1656. Question: 
  1657.  
  1658. I know about the VisualAge C++ calling conventions and keywords for C programs. 
  1659. Are the conventions the same in C++?  How do I use them? 
  1660.  
  1661. Answer: 
  1662.  
  1663. The calling conventions in C++ are almost the same as in C. The difference is 
  1664. in the default convention. 
  1665.  
  1666. By default, C functions have _Optlink linkage; C++ functions have C++ linkage. 
  1667. C++ linkage behaves like _Optlink, but the two conventions are not equivalent; 
  1668. C++ linkage also includes name mangling and overloading. 
  1669.  
  1670. Using the C linkage keywords declares that function as a C function.  Be 
  1671. careful that you don't use linkage keywords for member functions. 
  1672.  
  1673. You can also use the following qualifiers in your function declarations, listed 
  1674. with their equivalent keywords: 
  1675.  
  1676.  C++ Qualifier            Corresponding C Calling Convention 
  1677.  
  1678.  extern "C"               Default C linkage (_Optlink unless you change it to 
  1679.                           _System) 
  1680.  
  1681.  extern "C++"             _Optlink with name mangling, overloading 
  1682.  
  1683.  extern "SYSTEM"          _System 
  1684.  
  1685.  extern "OPTLINK"         _Optlink 
  1686.  
  1687.  extern "PASCAL"          _Pascal 
  1688.  
  1689.  extern "FAR16 CDECL"     _Far16 _Cdecl 
  1690.  
  1691.  extern "FAR16 PASCAL"    _Far16 _Pascal 
  1692.  
  1693.  extern "FAR16 FASTCALL"  _Far16 _Fastcall 
  1694.  
  1695.  
  1696. ΓòÉΓòÉΓòÉ 7.11. What Calling Convention Should I Use for Multiple Languages? ΓòÉΓòÉΓòÉ
  1697.  
  1698. Question: 
  1699.  
  1700. I have some functions in a DLL that I want to call from applications written in 
  1701. other languages like Pascal and COBOL. What calling convention should I use for 
  1702. these functions? 
  1703.  
  1704. Answer: 
  1705.  
  1706. All compilers on OS/2 have to support system linkage (usually referred to in 
  1707. VisualAge C++ as _System) so they can call OS/2 APIs. If you are creating a 
  1708. general-purpose DLL, you should code all 32-bit entry points with the _System 
  1709. calling convention. Other compilers do not support VisualAge C++'s _Optlink 
  1710. convention. 
  1711.  
  1712. If you have any 16-bit entry points, you should use the _Far16 _Pascal calling 
  1713. convention for them. 
  1714.  
  1715.  
  1716. ΓòÉΓòÉΓòÉ 7.12. Can I Use Library Extensions at the ANSI/ISO Language Level? ΓòÉΓòÉΓòÉ
  1717.  
  1718. Question: 
  1719.  
  1720. I have to compile my program with the language level set to ANSI to set the 
  1721. __STDC__ macro and ensure ANSI/ISO conformance. However, I also want to use 
  1722. some of the VisualAge C++ library functions that are not part of the ANSI/ISO 
  1723. standard, like _beginthread. Can I do this? 
  1724.  
  1725. Answer: 
  1726.  
  1727. You cannot use the VisualAge C++ library extensions and the ANSI/ISO language 
  1728. level together. However, you can define the __EXTENDED__ macro on the compiler 
  1729. invocation command to include the definitions for the library extensions when 
  1730. you have the language level set to ANSI/ISO.  The compiler will generate a 
  1731. warning, but should work correctly. Defining the macro this way still provides 
  1732. ANSI/ISO conformance checking (type checking, for example), but allows your 
  1733. program to use non-standard library functions. 
  1734.  
  1735.  
  1736. ΓòÉΓòÉΓòÉ 7.13. Should I Use DosCreateThread or _beginthread? ΓòÉΓòÉΓòÉ
  1737.  
  1738. Question: 
  1739.  
  1740. Can I use VisualAge C++ runtime functions from a thread created by 
  1741. DosCreateThread rather than by _beginthread? 
  1742.  
  1743. Answer: 
  1744.  
  1745. Yes, but there are extra steps you need to take to use DosCreateThread that you 
  1746. do not need to use _beginthread. To use DosCreateThread to create threads that 
  1747. can use the VisualAge C++ runtime: 
  1748.  
  1749.    1. Put a #pragma handler directive in your code for the thread function so 
  1750.       that the VisualAge C++ exception handler is registered for the thread. 
  1751.  
  1752.    2. If you are using floating-point math, call _fpreset at the beginning of 
  1753.       the thread function.  This call ensures that the floating-point chip is 
  1754.       in the correct state for the thread. 
  1755.  
  1756.    3. Terminate the thread with _endthread so that the thread-specific storage 
  1757.       is freed correctly. VisualAge C++ does not create thread-specific storage 
  1758.       until the first function that requires it is called. 
  1759.  
  1760.       Note:  Do not use DosExit to end your threads; it does not correctly 
  1761.       terminate the runtime, which can cause problems when you start another 
  1762.       thread. 
  1763.  
  1764.  When you use _beginthread, you do not have to follow these steps.  It performs 
  1765.  the required initialization and termination actions for you. 
  1766.  
  1767.  If you are writing C++ code, you can also use the IThread class from the User 
  1768.  Interface Class Library. See How Do I Start A Thread? for more details. 
  1769.  
  1770.  Note:  If you are using the subsystem library (with the /Rn compiler option), 
  1771.  the functions _beginthread, _endthread, and _fpreset are not available. You 
  1772.  must use DosCreateThread to create a new thread, and you must write your own 
  1773.  initialization, termination, and exception handling code. 
  1774.  
  1775.  
  1776. ΓòÉΓòÉΓòÉ 7.14. Can I Use C Functions on a File Opened with DosOpen? ΓòÉΓòÉΓòÉ
  1777.  
  1778. Question: 
  1779.  
  1780. I want to use DosOpen to open files so I can specify file inheritance 
  1781. information, but can I then use C library functions (like fread) on those 
  1782. files? 
  1783.  
  1784. Answer: 
  1785.  
  1786. After you open the file with DosOpen, use _fdopen to convert your OS/2 file 
  1787. handle to a C stream pointer. You can then use the C stream library functions 
  1788. on that file. Note that you must then close that file with fclose. 
  1789.  
  1790. You can also accomplish the same thing by opening the file with a C function 
  1791. (like fopen), and then setting the inheritance bit with 
  1792. DosSetFHState(fileno(file)). However, this does not work if you have other 
  1793. requirements, like sharing or caching, the DosSetFHState cannot handle. 
  1794.  
  1795.  
  1796. ΓòÉΓòÉΓòÉ 7.15. Can I Change the Parent's Environment from a Child Process? ΓòÉΓòÉΓòÉ
  1797.  
  1798. Question: 
  1799.  
  1800. Can my child process change the environment settings for its parent process and 
  1801. have them remain in effect? 
  1802.  
  1803. Answer: 
  1804.  
  1805. No.  However, you can code the child process to write out a .CMD file, and then 
  1806. call that file from the invoking process to pick up the environment changes. 
  1807.  
  1808.  
  1809. ΓòÉΓòÉΓòÉ 7.16. How Can I Perform Port Input/Output? ΓòÉΓòÉΓòÉ
  1810.  
  1811. Question: 
  1812.  
  1813. I want to perform port input and output.  Are there functions that can read to 
  1814. and write from ports? 
  1815.  
  1816. Answer: 
  1817.  
  1818. VisualAge C++ includes the functions inp, inpd, inpw, outp, outpd, and outpw 
  1819. that you can use to do port input and output. However, you can only use these 
  1820. functions in code that runs at ring zero (namely, device drivers). 32-bit 
  1821. application code cannot perform direct I/O. 
  1822.  
  1823. If your 32-bit application requires direct port I/O, you need to create a 
  1824. 16-bit input/output parameter list (IOPL) segment. (IOPL does not apply to 
  1825. 32-bit segments.) The functions that perform the direct I/O must reside in this 
  1826. segment. One way to create the segment is include the port I/O functions from 
  1827. C/2 in a 16-bit DLL. However, it may be more efficient to link them directly to 
  1828. your 32-bit code or even to write the functions directly in assembler. 
  1829.  
  1830.  
  1831. ΓòÉΓòÉΓòÉ 7.17. Can Signals Be Raised Across Processes? ΓòÉΓòÉΓòÉ
  1832.  
  1833. Question: 
  1834.  
  1835. Can signals be raised asynchronously (process to process)? 
  1836.  
  1837. Answer: 
  1838.  
  1839. The only signals that can be raised in another process are the following: 
  1840.  
  1841.  Signal    OS/2 API to use 
  1842.  SIGTERM   DosKillProcess 
  1843.  SIGINT    DosSendSignalException 
  1844.  SIGBREAK  DosSendSignalException 
  1845.  This is a limitation of 32-bit OS/2. 
  1846.  
  1847.  
  1848. ΓòÉΓòÉΓòÉ 7.18. What Should I Call in _DLL_InitTerm? ΓòÉΓòÉΓòÉ
  1849.  
  1850. Question: 
  1851.  
  1852. I am writing my own _DLL_InitTerm function. What should I call in it to 
  1853. correctly initialize and terminate the runtime environment? 
  1854.  
  1855. Answer: 
  1856.  
  1857. What you need to call depends on the runtime library you use, and on how you 
  1858. link to it (statically or dynamically). 
  1859.  
  1860. If you use the single- or multithread library: 
  1861.  
  1862. If your DLL statically links to the runtime library, you must call the 
  1863. following functions in the order shown: 
  1864.  
  1865.  _CRT_init      Initializes runtime environment. 
  1866.  __ctordtorInit Initializes static C++ objects. 
  1867.  __ctordtorTerm Terminates static C++ objects. 
  1868.  _CRT_term      Terminates the runtime environment. 
  1869.  
  1870.  If your DLL dynamically links to the runtime, you don't need to (and 
  1871.  shouldn't) call _CRT_init and _CRT_term. The runtime library DLL initializes 
  1872.  and terminates itself. 
  1873.  
  1874.  If you use the subsystem library 
  1875.  
  1876.  If your DLL statically links to the subsystem runtime, call the following 
  1877.  functions in the order shown: 
  1878.  
  1879.  _rmem_init 
  1880.       Initializes the runtime memory allocation functions. 
  1881.  
  1882.       Note:  If your DLL uses tiled memory, call _tmem_init instead of 
  1883.       _rmem_init to initialize the functions for tiled memory. 
  1884.  
  1885.  __ctordtorInit 
  1886.       Initializes static C++ objects. 
  1887.  
  1888.  __ctordtorTerm 
  1889.       Terminates static C++ objects. 
  1890.  
  1891.  _rmem_term 
  1892.       Terminates the runtime memory allocation functions. 
  1893.  
  1894.       Note:  If your DLL uses tiled memory, call _tmem_term instead of 
  1895.       _rmem_term to terminate the functions for tiled memory. 
  1896.  
  1897.  If your DLL dynamically links to the runtime library, you don't need to (and 
  1898.  shouldn't) call _rmem_init and _rmem_term (or _tmem_init and _tmem_term). The 
  1899.  runtime library DLL initializes and terminates the functions itself. 
  1900.  
  1901.  
  1902. ΓòÉΓòÉΓòÉ 8. Coding with the Data Type Classes ΓòÉΓòÉΓòÉ
  1903.  
  1904. This section discusses questions you might have about the IString, IDate, and 
  1905. ITime classes. 
  1906.  
  1907.      What Is the Maximum Length of an IString? 
  1908.      How Do I Convert an IString to char* ? 
  1909.      Can an IString Contain Null Characters? 
  1910.      How Should I Handle Date and Time in a Container? 
  1911.  
  1912.  
  1913. ΓòÉΓòÉΓòÉ 8.1. What Is the Maximum Length of an IString? ΓòÉΓòÉΓòÉ
  1914.  
  1915. Question: 
  1916.  
  1917. Is there a limit on the size of an IString?  What is the maximum length? 
  1918.  
  1919. Answer: 
  1920.  
  1921. The theoretical maximum size of an IString object is UINT_MAX - 1 (UINT_MAX is 
  1922. defined in <limits.h>). In practical terms, the limit of IString size is the 
  1923. size of the largest memory block that can be allocated on your system. 
  1924.  
  1925.  
  1926. ΓòÉΓòÉΓòÉ 8.2. How Do I Convert an IString to char* ? ΓòÉΓòÉΓòÉ
  1927.  
  1928. Question: 
  1929.  
  1930. How do you access the actual string contained in an object of type IString, and 
  1931. how do you convert between an IString and a regular char* string? 
  1932.  
  1933. Answer: 
  1934.  
  1935. IString provides an operator char*, so you can cast an IString to a char* 
  1936. either implicitly or explicitly. IString also provides a constructor that 
  1937. accepts a char* argument, so you could code something like: 
  1938.  
  1939.   IString foo("testing");
  1940.   foo = "this is a test";
  1941.  
  1942. You should treat the char* value as const char*, because changes you make using 
  1943. char* can corrupt the IString object. IString does not convert to a const char* 
  1944. for backwards compatibility. 
  1945.  
  1946.  
  1947. ΓòÉΓòÉΓòÉ 8.3. Can an IString Contain Null Characters? ΓòÉΓòÉΓòÉ
  1948.  
  1949. Question: 
  1950.  
  1951. Can an IString contain a null character other than the terminating null 
  1952. character? 
  1953.  
  1954. Answer: 
  1955.  
  1956. Yes, it can.  For example, you can set an IString to "Static text\0More text 
  1957. after NULL". If you cast that IString to a char*: 
  1958.  
  1959.   char* pChar = (char*)nullString;  // nullString is the IString object
  1960.  
  1961. pChar will also point to "Static text\0More text after NULL". However, if you 
  1962. pass pChar to functions that expect a terminating null character, such as the C 
  1963. library string functions, those functions will interpret the null as the 
  1964. terminating null character for the string and stop reading after "Static text". 
  1965.  
  1966. You can use the indexOf and subString functions of IString to extract the 
  1967. null-terminated strings: 
  1968.  
  1969.   int nullIndex;
  1970.  
  1971.   IString str("This is a string\0Hi there\0Last One\0", 35);
  1972.   int startPos = 1;
  1973.   while ( nullIndex = str.indexOf('\0', startPos) ) {
  1974.       cout << str.subString(startPos, nullIndex - startPos) << endl;
  1975.       startPos = nullIndex + 1;
  1976.   }
  1977.  
  1978.  
  1979. ΓòÉΓòÉΓòÉ 9. Coding with the Collection Classes ΓòÉΓòÉΓòÉ
  1980.  
  1981. This section answers questions you may have about using the Collection class 
  1982. library. 
  1983.  
  1984.      Why Does elementAt Not Work Correctly for My Cursor? 
  1985.      Why Do I Get Errors in <istdops.h>? 
  1986.      Why Do I Get an Error Returning the Key Element? 
  1987.      Why Do I Get Unexpected Results When I Add a Key? 
  1988.      Why Do I Get Linker Errors about Undefined Key Functions? 
  1989.      Why Is My Exception Output Traced When the Exception Is Caught? 
  1990.      Why Do I Get an Error about Undeclared Element Types? 
  1991.      Why Do I Get Compiler Errors about Multiply-Defined Symbols? 
  1992.      Why Do I Get Linker Errors for Multiply-Defined Symbols? 
  1993.      Why Do I Get Messages about Needing Constructors? 
  1994.      Why Do I Get Unresolved External References for Symbols I Don't Use? 
  1995.  
  1996.  
  1997. ΓòÉΓòÉΓòÉ 9.1. Why Does elementAt Not Work Correctly for My Cursor? ΓòÉΓòÉΓòÉ
  1998.  
  1999. Question: 
  2000.  
  2001. When I use cursors, I get unexpected results. For example, elementAt sometimes 
  2002. fails for the cursor or returns an unexpected element. 
  2003.  
  2004. Answer: 
  2005.  
  2006. You have used an undefined cursor.  Cursors become undefined when an element is 
  2007. added to or removed from the collection. 
  2008.  
  2009. You must rebuild your cursor with an appropriate operation (for example, 
  2010. locate()) before you use it again.  Rebuilding is especially important for 
  2011. removing all elements with a given property from a collection.  Elements cannot 
  2012. be removed by coding a cursor iteration. Use the removeAll() function that 
  2013. takes a predicate function as its argument. 
  2014.  
  2015. For more information about cursors, see the Open Class Library User's Guide. 
  2016.  
  2017.  
  2018. ΓòÉΓòÉΓòÉ 9.2. Why Do I Get Errors in <istdops.h>? ΓòÉΓòÉΓòÉ
  2019.  
  2020. Question: 
  2021.  
  2022. I get several different compiler error messages about undefined keys, unmatched 
  2023. hash types, and operators that aren't allowed. All the errors point to 
  2024. <istdops.h>.  Why do I get these errors? 
  2025.  
  2026. Answer: 
  2027.  
  2028. Compiler error messages indicating a problem in <istdops.h> are related to the 
  2029. element and key-type functions that you must define for your elements. These 
  2030. functions depend on the collection and implementation variant you are using. 
  2031. The compilation errors you describe occur when the key() function, the hash() 
  2032. function, operator==, or operator< are required for your elements, but are 
  2033. defined with the wrong interface or not defined at all. Whether arguments are 
  2034. defined as const is significant.  Compiler messages do not always point 
  2035. directly to the incorrect function. For example, a compare function with 
  2036. non-const arguments results in the compilation error: 
  2037. The "<" operator is not allowed between "const ..". 
  2038.  
  2039. Verify which element and key-type functions are required for the implementation 
  2040. variant of the collection you are using. You can find this information for each 
  2041. collection in the Open Class Library Reference in the section pertaining to the 
  2042. collection under the heading "Template Arguments and Required Functions". 
  2043.  
  2044. For more information about element and key-type functions, see the Open Class 
  2045. Library User's Guide. 
  2046.  
  2047. Note that the same problem may be produced if function declarations and 
  2048. definitions are not correctly separated between .h files and .cpp files. This 
  2049. situation is described in detail in Why Do I Get an Error about Undeclared 
  2050. Element Types?. 
  2051.  
  2052.  
  2053. ΓòÉΓòÉΓòÉ 9.3. Why Do I Get an Error Returning the Key Element? ΓòÉΓòÉΓòÉ
  2054.  
  2055. Question: 
  2056.  
  2057. When I try to return the key value, I get a compiler message warning about the 
  2058. use of a local variable or temporary in a return expression.  Why? 
  2059.  
  2060. Answer: 
  2061.  
  2062. Your global-name-space function key() returns the key by value instead of by 
  2063. reference. A temporary variable is created for the key within the 
  2064. operator-class function key. The operator class function key returns the key by 
  2065. reference. Returning a reference to a temporary variable causes unpredictable 
  2066. results. 
  2067.  
  2068. The key function must return a reference and must also take a reference 
  2069. argument.  If the key function calls other functions to access the key, it must 
  2070. call those functions with a reference to the object as an argument, and those 
  2071. functions must return a reference to the key. 
  2072.  
  2073. Verify that the global name-space function key correctly returns a key const& 
  2074. instead of key. 
  2075.  
  2076. For more information on element and key-type functions, see the Open Class 
  2077. Library User's Guide. 
  2078.  
  2079.  
  2080. ΓòÉΓòÉΓòÉ 9.4. Why Do I Get Unexpected Results When I Add a Key? ΓòÉΓòÉΓòÉ
  2081.  
  2082. Question: 
  2083.  
  2084. I am trying to add an element into a unique key collection (a key set or map). 
  2085. I am sure that the collection does not already contain an element with this 
  2086. key.  However, I either get the IKeyAlreadyExistsException, or the element is 
  2087. not added and the cursor is positioned to a different element.  Why? 
  2088.  
  2089. Answer: 
  2090.  
  2091. Your global-name-space function key() returns the key by value instead of by 
  2092. reference. If you compile with a higher warning level, you will get compiler 
  2093. error messages about this as described in Why Do I Get an Error Returning the 
  2094. Key Element?. A temporary variable is created for the key within the 
  2095. operator-class function key. The operator class function key returns the key by 
  2096. reference. Returning a reference to a temporary variable causes unpredictable 
  2097. results. 
  2098.  
  2099. The key function must return a reference and must also take a reference 
  2100. argument.  If the key function calls other functions to access the key, it must 
  2101. call those functions with a reference to the object as an argument, and those 
  2102. functions must return a reference to the key. 
  2103.  
  2104. Verify that the global name-space function key correctly returns a key const& 
  2105. instead of key. 
  2106.  
  2107. For more information on element and key-type functions, see the Open Class 
  2108. Library User's Guide. 
  2109.  
  2110.  
  2111. ΓòÉΓòÉΓòÉ 9.5. Why Do I Get Linker Errors about Undefined Key Functions? ΓòÉΓòÉΓòÉ
  2112.  
  2113. Question: 
  2114.  
  2115. When I link my object files, I get an error message that a key function is 
  2116. undefined.  Why? 
  2117.  
  2118. Answer: 
  2119.  
  2120. You are using a collection class that requires the element class to provide a 
  2121. key, and you chose to use the method of using a global key() function. You are 
  2122. using collection class methods in a .CPP file, but the .H file with the same 
  2123. name as the .CPP file does not contain a declaration (prototype) of the global 
  2124. key function. 
  2125.  
  2126. While compiling the .CPP file, which uses methods of the collection class, the 
  2127. compiler has created or modified a temporary .CPP file in the TEMPINC 
  2128. directory.  During the link step, this .CPP file is compiled to resolve 
  2129. references to template code. The error message you encounter refers to this 
  2130. compilation. 
  2131.  
  2132. The .CPP file in the TEMPINC directory contains include directives for the 
  2133. collection class template code. It also contains include directives for a .H 
  2134. file of the same name as the .CPP file that uses the collection class methods. 
  2135. The template code in <istdops.h> requires that the global key() function be 
  2136. known at compilation time.  The only file that is included at this time is the 
  2137. .H file with the same name as your .CPP file.  The problem is that the .CPP 
  2138. file is not included at this time, so a definition or declaration of the global 
  2139. key() function in this file is not recognized by the compiler. 
  2140.  
  2141. You must declare the global key() function in the .H file with the same name as 
  2142. the .CPP file that uses the collection class methods.  The definition of the 
  2143. global key() function should be in the .CPP file. If you are not sure which .H 
  2144. file is meant by the message, look in the .CPP file found in the TEMPINC 
  2145. directory. 
  2146.  
  2147.  
  2148. ΓòÉΓòÉΓòÉ 9.6. Why Is My Exception Output Traced When the Exception Is Caught? ΓòÉΓòÉΓòÉ
  2149.  
  2150. Question: 
  2151.  
  2152. Why is my exception tracing output printed to stderr when the exception has 
  2153. already been caught? 
  2154.  
  2155. Answer: 
  2156.  
  2157. For each exception raised, the trace function write() of class 
  2158. IException::TraceFn is called and writes information about the raised exception 
  2159. to standard error. This trace function write() is called whether the related 
  2160. exception is caught or not. 
  2161.  
  2162. To suppress the trace output, provide your own IException::TraceFn::write() 
  2163. tracing function by subclassing IException::TraceFn and register the subclass 
  2164. with setTraceFunction(). For more information about exception tracing, see the 
  2165. Open Class Library User's Guide. 
  2166.  
  2167.  
  2168. ΓòÉΓòÉΓòÉ 9.7. Why Do I Get an Error about Undeclared Element Types? ΓòÉΓòÉΓòÉ
  2169.  
  2170. Question: 
  2171.  
  2172. I am compiling a file that uses templates and I am getting a compiler error 
  2173. that an element or one of its required element functions is not declared.  Why? 
  2174.  
  2175. Answer: 
  2176.  
  2177. The element type or element function is defined locally to the .cpp file that 
  2178. contains the template instantiation with the element type as its argument. The 
  2179. prelink phase is executed only by using the header files. Therefore, your 
  2180. declaration local to a .cpp file is not recognized and causes these compilation 
  2181. errors. 
  2182.  
  2183. Move the corresponding declarations to a separate header file and include the 
  2184. header file from the .cpp file. 
  2185.  
  2186.  
  2187. ΓòÉΓòÉΓòÉ 9.8. Why Do I Get Compiler Errors about Multiply-Defined Symbols? ΓòÉΓòÉΓòÉ
  2188.  
  2189. Question: 
  2190.  
  2191. Why do I get compiler errors about symbols being defined multiple times? 
  2192.  
  2193. Answer: 
  2194.  
  2195. The template instantiation needs to include the type declarations it received 
  2196. as arguments. Your header files containing type declarations used in template 
  2197. classes may automatically be included several times. 
  2198.  
  2199. Protect your header files against multiple inclusion by using the following 
  2200. preprocessor macros at the beginning and end of your header files: 
  2201.  
  2202.    #ifndef _MYHEADER_H_
  2203.    #define _MYHEADER_H_ 1
  2204.    .
  2205.    .
  2206.    .
  2207.    #endif
  2208.  
  2209. Where _MYHEADER_H_ is an identifier unique to each header file and representing 
  2210. the header file's name. 
  2211.  
  2212.  
  2213. ΓòÉΓòÉΓòÉ 9.9. Why Do I Get Linker Errors for Multiply-Defined Symbols? ΓòÉΓòÉΓòÉ
  2214.  
  2215. Question: 
  2216.  
  2217. Why do I get linker errors about symbols being defined multiple times? 
  2218.  
  2219. Answer: 
  2220.  
  2221. The template instantiation needs to include the type declarations it received 
  2222. as arguments. Your header files containing type declarations used in template 
  2223. classes might automatically be included several times. 
  2224.  
  2225. Verify that you did not define functions in the header files that declare types 
  2226. used in templates. If you did, you must move them from the header file into a 
  2227. separate .cpp file or make them inline. 
  2228.  
  2229.  
  2230. ΓòÉΓòÉΓòÉ 9.10. Why Do I Get Messages about Needing Constructors? ΓòÉΓòÉΓòÉ
  2231.  
  2232. Question: 
  2233.  
  2234. Why does the compiler say that I need a constructor for my template class? 
  2235.  
  2236. Answer: 
  2237.  
  2238. Compiler error messages indicating a problem with constructors for a collection 
  2239. are typically related to the constructors defined for your element. Here the 
  2240. default constructor for the element is missing. 
  2241.  
  2242. Define the default constructor for the element class. 
  2243.  
  2244. For more information about element and key-type functions, see the Open Class 
  2245. Library User's Guide. The element and key-type functions required for each 
  2246. collection are listed for each collection type in the sections entitled 
  2247. "Template Arguments and Required Functions". 
  2248.  
  2249.  
  2250. ΓòÉΓòÉΓòÉ 9.11. Why Do I Get Unresolved External References for Symbols I Don't Use? ΓòÉΓòÉΓòÉ
  2251.  
  2252. Question: 
  2253.  
  2254. When I link my program, I get errors about unresolved external references for 
  2255. symbols that I don't use or know about.  Why? 
  2256.  
  2257. Answer: 
  2258.  
  2259. A possible reason for unresolved external references during linking is that 
  2260. template code cannot be correctly resolved. To ensure templates resolve 
  2261. correctly, invoke the linker using icc with the /Tdp option. 
  2262.  
  2263.  
  2264. ΓòÉΓòÉΓòÉ 10. Coding with User Interface Classes ΓòÉΓòÉΓòÉ
  2265.  
  2266. This section answers questions about the User Interface class library and how 
  2267. to use it. Because of the scope of the User Interface library, this section is 
  2268. broken down into the following topics: 
  2269.  
  2270.      Base Window and Events 
  2271.      Handlers 
  2272.      Frame Windows 
  2273.      Canvas Classes 
  2274.      Container Control 
  2275.      Text and Button Controls 
  2276.      Listbox and Combobox Controls 
  2277.      Notebook Control 
  2278.      Other Controls 
  2279.      Menus 
  2280.      Creating Help with IHelpWindow 
  2281.      Application and Resources 
  2282.      Threads 
  2283.      Fonts and Colors 
  2284.      Font and File Dialogs 
  2285.      Direct Manipulation (Drag and Drop) 
  2286.      Dynamic Data Exchange (DDE) 
  2287.      Exceptions 
  2288.      Internationalization 
  2289.      Extending the User Interface Class Library 
  2290.      Graphics and Drawing 
  2291.  
  2292.  
  2293. ΓòÉΓòÉΓòÉ 10.1. Base Window and Events ΓòÉΓòÉΓòÉ
  2294.  
  2295. This section discusses general window and event topics: 
  2296.  
  2297.      What Does IWindow::setAutoDeleteObject Do? 
  2298.      How Should I Number Window IDs? 
  2299.      What is the Difference between Sending and Posting Messages? 
  2300.      How Do I Access the Value of IHandle Objects? 
  2301.      How Do Owner and Parent Relationships Work? 
  2302.  
  2303.  
  2304. ΓòÉΓòÉΓòÉ 10.1.1. What Does IWindow::setAutoDeleteObject Do? ΓòÉΓòÉΓòÉ
  2305.  
  2306. Question: 
  2307.  
  2308. What does setAutoDeleteObject do, and when should I use it? Is it only for 
  2309. IWindow instances created by operator new, or for all instances? 
  2310.  
  2311. Answer: 
  2312.  
  2313. The setAutoDeleteObject function is only for windows created with new.  It 
  2314. causes code in the User Interface dispatcher to call delete for the C++ object 
  2315. some time after the underlying presentation system window has been destroyed. 
  2316.  
  2317. In general, if you create something with the new operator, you must also delete 
  2318. it.  This is true of IWindow objects also.  However, you can use 
  2319. setAutoDeleteObject( true ) to have the User Interface class library delete the 
  2320. object for you if it is difficult to keep track of the IWindow object you 
  2321. created. One place where setAutoDeleteObject is useful is the creation of a 
  2322. modeless secondary or child frame window. 
  2323.  
  2324. When you use setAutoDeleteObject(true), do not call delete yourself for the 
  2325. object. 
  2326.  
  2327.  
  2328. ΓòÉΓòÉΓòÉ 10.1.2. How Should I Number Window IDs? ΓòÉΓòÉΓòÉ
  2329.  
  2330. Question: 
  2331.  
  2332. What numbering scheme shoud I use for window IDs? Do they have to start from a 
  2333. specific number?  Is there an upper limit? 
  2334.  
  2335. Answer: 
  2336.  
  2337. The safest way to program is to use window IDs that are unique on a per-frame 
  2338. window basis.  You can then easily provide unique contextual help for all 
  2339. windows and identify the window under the mouse from a WM_CONTROLPOINTER 
  2340. message. If you don't use unique IDs, you'll need to know how you call 
  2341. functions like IWindow::windowWithId and functions that call it (such as 
  2342. IControlEvent::controlWindow). PM reserves some window IDs for windows that it 
  2343. creates, making it more difficult to ensure that your window IDs are unique. 
  2344.  
  2345. For client windows, you should always use a window ID of 0x8008 (preferably by 
  2346. using either the constant FID_CLIENT from <pmwin.h> or IC_FRAME_CLIENT_ID from 
  2347. <icconst.h>). If you don't, IFrameWindow::setClient changes the value of the ID 
  2348. to this, meaning that any code that relied on the value you set will not work 
  2349. correctly. 
  2350.  
  2351. Avoid using all other FID_* window IDs from <pmwin.h> for child windows of a 
  2352. frame. 
  2353.  
  2354. Although window IDs in PM APIs are unsigned long types, PM only honors the low 
  2355. word. Therefore, keep your window IDs below 65535. 
  2356.  
  2357.  
  2358. ΓòÉΓòÉΓòÉ 10.1.3. What is the Difference between Sending and Posting Messages? ΓòÉΓòÉΓòÉ
  2359.  
  2360. Question: 
  2361.  
  2362. What is the difference between sending a message and posting one? 
  2363.  
  2364. Answer: 
  2365.  
  2366. When a message is sent (sendEvent), the sender is blocked until the receiver 
  2367. processes the message and returns.  If the sender and receiver are on the same 
  2368. thread,  a direct function call is made to the receiver.  If the sender and 
  2369. receiver are on different threads, the message is placed on a private area of 
  2370. the receiver's message queue.  In either case, the sender is blocked until the 
  2371. receiver processes the message and returns. 
  2372.  
  2373. When a message is posted, the message is placed on the receiver's message 
  2374. queue.  The poster's thread then continues without waiting for a reply. 
  2375.  
  2376.  
  2377. ΓòÉΓòÉΓòÉ 10.1.4. How Do I Access the Value of IHandle Objects? ΓòÉΓòÉΓòÉ
  2378.  
  2379. Question: 
  2380.  
  2381. How do I use the Value operator from the IHandle class to get the handle value 
  2382. from an IMessageQueueHandle object? 
  2383.  
  2384. Answer: 
  2385.  
  2386. In PM, Value is defined in a typedef to be an unsigned long value.  Therefore, 
  2387. operator Value is really operator unsigned long, so you can use an IHandle or 
  2388. IMessageQueueHandle object as an unsigned long and not have to call any 
  2389. functions. 
  2390.  
  2391. In general, the IHandle-derived classes contain conversion operators that 
  2392. define conversions to the underlying system object. Usually you can use the 
  2393. IHandle objects in system calls where the corresponding system type is 
  2394. expected. 
  2395.  
  2396. In PM, the underlying type for HWND, HMQ, and most of the other handle objects 
  2397. is unsigned long. In the Motif version, the underlying types are typically 
  2398. pointers to an X or Motif structure (such as Widget, which is really a 
  2399. _WidgetRec*). 
  2400.  
  2401.  
  2402. ΓòÉΓòÉΓòÉ 10.1.5. How Do Owner and Parent Relationships Work? ΓòÉΓòÉΓòÉ
  2403.  
  2404. Question: 
  2405.  
  2406. As a new programmer in the PM environment, I still don't understand the 
  2407. concepts of parent and owner as they relate to window controls. Can you please 
  2408. explain? 
  2409.  
  2410. Answer: 
  2411.  
  2412. The most important thing to remember is that parent and child relates to the 
  2413. display hierarchy of the windows in your application, and owner and owned 
  2414. relates to the control hierarchy. The display hierarchy deals with things like 
  2415. clipping and Z-order control. The control hierarchy deals with messages going 
  2416. between the owned and owner windows. 
  2417.  
  2418. The parent window is normally used for window location. For example, most frame 
  2419. windows have a parent of the desktop so that they can appear anywhere on the 
  2420. desktop. If a window is a child of another winodw, then it is only visible 
  2421. inside the parent window.  (That is, a window is clipped to its parent.) 
  2422.  
  2423. Many messages are passed up the owner chain for processing. In PM, changes to 
  2424. presentation parameters (such as color or font) are passed down the owner 
  2425. chain. When you move an owner window, all of the windows that it owns are 
  2426. usually moved as well. 
  2427.  
  2428. A window with the desktop as parent and owner is considered a primary window. 
  2429. A window with the desktop as parent but with another window as owner is 
  2430. considered a secondary window. A window whose parent and owner are another 
  2431. window or windows is considered a child window. 
  2432.  
  2433.  
  2434. ΓòÉΓòÉΓòÉ 10.2. Handlers ΓòÉΓòÉΓòÉ
  2435.  
  2436. This section discusses handlers, including common problems that can be solved 
  2437. using a handler. 
  2438.  
  2439.      How Do I Change the Mouse Pointer? 
  2440.      How Do I Capture Mouse Movement? 
  2441.      How Do I Send and Handle User-Defined Messages? 
  2442.      Which Handler Should I Use? 
  2443.      How Do I Find the IWindow from a Handler? 
  2444.      How Do I Replace Events? 
  2445.      How Are Keystrokes Processed? 
  2446.  
  2447.  
  2448. ΓòÉΓòÉΓòÉ 10.2.1. How Do I Change the Mouse Pointer? ΓòÉΓòÉΓòÉ
  2449.  
  2450. Question: 
  2451.  
  2452. I want to change the pointer icon while the pointer is over my application 
  2453. window.  How do I do this? 
  2454.  
  2455. Answer: 
  2456.  
  2457. Use the IMouseHandler class or the IFrameWindow::setMousePointer function. 
  2458.  
  2459.  
  2460. ΓòÉΓòÉΓòÉ 10.2.2. How Do I Capture Mouse Movement? ΓòÉΓòÉΓòÉ
  2461.  
  2462. Question: 
  2463.  
  2464. I need to be aware of any mouse movement that occurs while the mouse pointer is 
  2465. on top of my application window. Is there a way to be informed about mouse 
  2466. movements? 
  2467.  
  2468. Answer: 
  2469.  
  2470. Yes.  VisualAge C++ Open Class Library Version 3.0 includes a handler to 
  2471. capture mouse movements. Derive from IMouseHandler and override the mouseMoved 
  2472. function to be informed of mouse movements. 
  2473.  
  2474.  
  2475. ΓòÉΓòÉΓòÉ 10.2.3. How Do I Send and Handle User-Defined Messages? ΓòÉΓòÉΓòÉ
  2476.  
  2477. Question: 
  2478.  
  2479. How do I dispatch and capture my own user-defined messages to an event handler? 
  2480. How do I create a handler to capture the message? 
  2481.  
  2482. Answer: 
  2483.  
  2484. When you create a handler and call its handleEventsFor function, all messages 
  2485. dispatched to the handler's windows are sent to the handler's 
  2486. dispatchHandlerEvent function. To handle messages differently, override this 
  2487. function and capture whatever user or system messages you want to handle. You 
  2488. must also return true or false to indicate whether other handlers should 
  2489. receive the message, and call setResult on the event passed to 
  2490. dispatchHandlerEvent if you need to pass information back to PM or to the 
  2491. sender of the event. 
  2492.  
  2493. To dispatch a message to a window: 
  2494.  
  2495.      Use the postEvent or sendEvent functions of IWindow or IWindowHandle to 
  2496.       post or send an event to a specific window. 
  2497.      Use IMessageQueueHandle::postEvent to post an event to a specific message 
  2498.       queue. 
  2499.  
  2500.  For example, if you have attached your handler to an IWindow window, send 
  2501.  messages to it with: 
  2502.  
  2503.      mywindow.sendEvent( USER_MESSAGE )
  2504.  
  2505.  This sends USER_MESSAGE to mywindow, which then causes your handler to run. 
  2506.  Your dispatchHandlerEvent function should look for USER_MESSAGE and do 
  2507.  whatever it needs to with it. 
  2508.  
  2509.  One case where a user message handler is useful is to process the messages 
  2510.  sent to an object window (IObjectWindow).  Object windows are useful in cases 
  2511.  where you have application-defined events that may take a long time to 
  2512.  process.  Because object windows are invisible and never get the input focus, 
  2513.  you will not block user input going to other windows while you process these 
  2514.  events.  To use an object window, create a separate thread using IThread and 
  2515.  in it: 
  2516.  
  2517.    1. Create an IObjectWindow, 
  2518.    2. Create a user message handler, 
  2519.    3. Attach this handler to the object window, 
  2520.    4. Call IThread::current().processMsgs(). 
  2521.  
  2522.  Your main thread simply posts WM_USER events to the object window.  You need 
  2523.  to somehow pass back a handle for the object window to your main thread and 
  2524.  possibly pass in a window handle to the object window so it can communicate 
  2525.  back.  You can use a user handler on the main thread to accept communications 
  2526.  from the object window. 
  2527.  
  2528.  For an example of a WM_USER message handler, click below: 
  2529.  
  2530.  Example 
  2531.  
  2532.  For more details on handlers, see the Open Class Library User's Guide. The 
  2533.  HELLO6 sample program also has an example of a user-defined handler that 
  2534.  handles WM_TIMER messages. 
  2535.  
  2536.  
  2537. ΓòÉΓòÉΓòÉ <hidden> Example of WM_USER Message Handler ΓòÉΓòÉΓòÉ
  2538.  
  2539. Here is an example of a WM_USER message handler that you could add to a frame 
  2540. window.  When you want to post a message to the frame window, you do something 
  2541. like: 
  2542.  
  2543.      #define WM_DATA_IS_READY WM_USER + 100
  2544.  
  2545.     myFrameWindow->postEvent(WM_DATA_IS_READY );
  2546.  
  2547. The handler would look like this: 
  2548.  
  2549. ----------------------------- iusrhdr.hpp -----------------------
  2550. #ifndef _IUSERHDR_
  2551.   #define _IUSERHDR_
  2552.  
  2553. #include <ihandler.hpp>
  2554. #include <ievent.hpp>
  2555.  
  2556. #pragma pack(4)
  2557.  
  2558. class IUserHandler : public IHandler {
  2559. public:
  2560.   IUserHandler   ( );
  2561. virtual
  2562.  ~IUserHandler   ( );
  2563.  
  2564. virtual Boolean
  2565.   dispatchHandlerEvent ( IEvent& event );
  2566.  
  2567. protected:
  2568. virtual Boolean
  2569.   user         ( IEvent& event ) = 0;
  2570. };
  2571.  
  2572. #pragma pack()
  2573.  
  2574. #endif
  2575.  
  2576. --------------------------- iusrhdr.cpp ----------------------------
  2577. #define INCL_WINMESSAGEMGR
  2578. #include <os2.h>
  2579. #include <iuserhdr.hpp>
  2580.  
  2581. IUserHandler :: IUserHandler ( )
  2582.   : IHandler ( )
  2583. {  }
  2584.  
  2585. IUserHandler :: ~IUserHandler ( )
  2586. {  }
  2587.  
  2588. Boolean  IUserHandler :: dispatchHandlerEvent ( IEvent & evt )
  2589. {
  2590.    Boolean bRc = false;
  2591.    switch (evt.eventId())
  2592.    {
  2593.       case WM_DATA_IS_READY:
  2594.       {
  2595.          bRc = user(evt);
  2596.          break;
  2597.       }
  2598.       default:
  2599.          break;
  2600.    } /* endswitch */
  2601.  
  2602.    return bRc;
  2603. }
  2604.  
  2605.  
  2606. ΓòÉΓòÉΓòÉ 10.2.4. Which Handler Should I Use? ΓòÉΓòÉΓòÉ
  2607.  
  2608. Question: 
  2609.  
  2610. How do I decide which handler class to use for a particular event? Is there a 
  2611. cross reference of handler classes and the messages they process? 
  2612.  
  2613. Answer: 
  2614.  
  2615. There is a table in the Open Class Library User's Guide chapter on handlers and 
  2616. events that lists some of the events and the handlers they are dispatched to. 
  2617. The VisualAge C++ documentation does not include a cross-reference between the 
  2618. handler classes and the system (PM) messages they process. 
  2619.  
  2620. OS/2 C++ Class Library: Power GUI Programming with C Set ++ also contains a 
  2621. listing of the handler classes and recommendations on where you might use them, 
  2622. as well as a handler-to-PM-message cross-reference. (Note that this book does 
  2623. not include information about additions to Version 3.0 of the library.) 
  2624.  
  2625. If you have the Open Class Library Source Code product, you can determine the 
  2626. messages processed by a handler by examining the dispatchHandlerEvents function 
  2627. implementation. However, do not depend on this being constant; future library 
  2628. enhancements may alter the message set handled by a handler class. 
  2629.  
  2630.  
  2631. ΓòÉΓòÉΓòÉ 10.2.5. How Do I Find the IWindow from a Handler? ΓòÉΓòÉΓòÉ
  2632.  
  2633. Question: 
  2634.  
  2635. If more than one control is attached to the the same event handler, how do I 
  2636. find the IWindow object relating to the current event? 
  2637.  
  2638. Answer: 
  2639.  
  2640. When in a handler callback function, event.window() returns the window the 
  2641. message was dispatched to. 
  2642.  
  2643. If the event was not an IControlEvent, event.window() returns the window 
  2644. itself. 
  2645.  
  2646. For an IControlEvent, event.window() returns the owner of the control. You can 
  2647. then call IControlEvent::controlWindow to get the control window pointer. Once 
  2648. you have the window pointer, you can call IWindow::id to find the window's ID. 
  2649. You can also get the ID of a control in an event derived from IControlEvent by 
  2650. calling controlId. 
  2651.  
  2652.  
  2653. ΓòÉΓòÉΓòÉ 10.2.6. How Do I Replace Events? ΓòÉΓòÉΓòÉ
  2654.  
  2655. Question: 
  2656.  
  2657. How do I replace an event that comes to my application with a different event? 
  2658.  
  2659. Answer: 
  2660.  
  2661. Typically you would implement a handler to replace the event. Detect the 
  2662. specific event you want to replace, and then send or post the replacement event 
  2663. or message to the window. Return a value of true to indicate that the original 
  2664. event should not be passed on to any more handlers or to any window procedures. 
  2665.  
  2666. However, any time you do this, you need to ensure that you don't cause an 
  2667. endless loop.  You may need to add a check to your handler to detect that an 
  2668. event is not to be replaced again or reposted. 
  2669.  
  2670. Alternatively, when you detect the event to replace, you can build your 
  2671. replacement event, then pass it to IWindow::defaultProcedure, and return a 
  2672. value of true.  The difference is that the replacement event won't come back 
  2673. through your handler, although it will also bypass all previous and subsequent 
  2674. handlers. Therefore, any other handlers attached to your window cannot process 
  2675. the replacement event. 
  2676.  
  2677. You can also call IWindow::dispatchRemainingHandlers to bypass handlers that 
  2678. have already been called, so that only subsequent handlers (and optionally, 
  2679. IWindow::defaultProcedure) are called. 
  2680.  
  2681.  
  2682. ΓòÉΓòÉΓòÉ 10.2.7. How Are Keystrokes Processed? ΓòÉΓòÉΓòÉ
  2683.  
  2684. Question: 
  2685.  
  2686. How are keystrokes processed? 
  2687.  
  2688. Answer: 
  2689.  
  2690. The normal processing for keystrokes is that the window (control) with the 
  2691. input focus has the first opportunity to process the key.  If that window 
  2692. doesn't process it, then the key is passed up to its owner window. The owner 
  2693. window can then process the key.  If not processed, it again goes up the owner 
  2694. chain.  The cycle continues until the keystroke is processed or until no 
  2695. windows are left in the owner chain. 
  2696.  
  2697. You need to consider this behavior when using an IKeyboardHandler in your 
  2698. application. For example, IMultiLineEdit processes PageUp and PageDown to 
  2699. scroll the data.  If you want the IMultiLineEdit to ignore these keys, create a 
  2700. keyboard handler that provides an implementation for the virtualKeyPress 
  2701. function. In the handler, look specifically for IKeyboardEvent::pageUp and 
  2702. IKeyboardEvent::pageDown virtual keys. You can route these keystrokes to the 
  2703. owner window of the MLE by calling: 
  2704.  
  2705.    event.window()->owner()->sendEvent( event );
  2706.  
  2707. Then return true to indicate that PageUp or PageDown should not be given to the 
  2708. MLE to process.  For all other cases, return false. This will have the effect 
  2709. of disabling the MLE scrolling.  You could use such a setup when the MLE's 
  2710. owner is an IViewPort that will be handling the scrolling. 
  2711.  
  2712.  
  2713. ΓòÉΓòÉΓòÉ 10.3. Frame Windows ΓòÉΓòÉΓòÉ
  2714.  
  2715. This section discusses frame windows, dialog templates, and related topics. 
  2716.  
  2717.      How Do I Set the Title of a Frame Window? 
  2718.      How Can I Intercept a Request to Close a Frame Window? 
  2719.      What Is the IFrameWindow Client Window? 
  2720.      Why Is the Client ID Changed? 
  2721.      How Do I Set Up an IFrameWindow within an IFrameWindow? 
  2722.      Can I Use a Frame as a Client Window? 
  2723.      Can I Have Automatic Resizing for Dialogs? 
  2724.      Why Doesn't My Control Defined in a DLG Resource Work? 
  2725.      Should I Use Canvas Classes or Dialog Templates? 
  2726.      Can I Set the Minimum Size of an IFrameWindow? 
  2727.      How Do I Access the Scroll Bars on an IFrameWindow? 
  2728.      Why Does My Dialog Overwrite the Parent Notebook? 
  2729.      Why Doesn't My Application End when the Frame is Closed? 
  2730.      How Do I Exit IApplication::current().run() ? 
  2731.  
  2732.  
  2733. ΓòÉΓòÉΓòÉ 10.3.1. How Do I Set the Title of a Frame Window? ΓòÉΓòÉΓòÉ
  2734.  
  2735. Question: 
  2736.  
  2737. How can my application read and set the titlebar text of an existing 
  2738. IFrameWindow object? 
  2739.  
  2740. Answer: 
  2741.  
  2742. Use the ITitle class.  Create an ITitle object from the IFrameWindow, and then 
  2743. use objectText() and setObjectText(), or text() and setText(). to read and 
  2744. change the frame window's title, respectively. 
  2745.  
  2746.  
  2747. ΓòÉΓòÉΓòÉ 10.3.2. How Can I Intercept a Request to Close a Frame Window? ΓòÉΓòÉΓòÉ
  2748.  
  2749. Question: 
  2750.  
  2751. When the user closes my application with the system menu, I need to intercept 
  2752. the close request so I can display a confirmation message. How can I do this? 
  2753.  
  2754. Answer: 
  2755.  
  2756. The command you want to intercept is SC_CLOSE.  You can use the PM constant 
  2757. SC_CLOSE or the ISystemMenu::idClose constant. To use SC_CLOSE, derive a 
  2758. handler from ICommandHandler and provide a systemCommand function similar to 
  2759. this: 
  2760.  
  2761. Boolean MyCommandHandler::systemCommand(ICommandEvent& cmdEvt)
  2762.    {
  2763.    if ( cmdEvt.commandId() == SC_CLOSE )
  2764.       {
  2765.       // ask for confirmation from user ...
  2766.       if ( response != IMessageBox::yes )
  2767.           return true;     // let it close
  2768.       }
  2769.    return false;           // don't close
  2770.    }
  2771.  
  2772. Attach this command handler to your IFrameWindow. 
  2773.  
  2774. Another way to do this is to attach your own IFrameHandler to your frame 
  2775. window, providing your own implementation of the virtual closed() function. 
  2776. This function will be called when the frame window is closed. (It keys off a 
  2777. WM_CLOSE, WM_SYSCOMMAND, or SC_CLOSE command). 
  2778.  
  2779.  
  2780. ΓòÉΓòÉΓòÉ 10.3.3. What Is the IFrameWindow Client Window? ΓòÉΓòÉΓòÉ
  2781.  
  2782. Question: 
  2783.  
  2784. I want to create a window with a number of child controls in it. I thought of 
  2785. using canvases, but don't know what to use for a client window.  What should I 
  2786. do? 
  2787.  
  2788. Answer: 
  2789.  
  2790. You can make almost any control the client of your frame.  The client window is 
  2791. just the window that fills up the client area (the portion of the frame not 
  2792. occupied by frame controls).  It can be any type of control; canvases are 
  2793. especially useful if you want your child controls to behave like dialogs (with 
  2794. Tab key support and so on). 
  2795.  
  2796.  
  2797. ΓòÉΓòÉΓòÉ 10.3.4. Why Is the Client ID Changed? ΓòÉΓòÉΓòÉ
  2798.  
  2799. Question: 
  2800.  
  2801. I have a dialog that I create specifying an ID of 0x11FE.  My dialog has an 
  2802. ISelectHandler attached to it.  When my enter() method is called, the 
  2803. controlId() method returns 0x8008. What is happening? 
  2804.  
  2805. Answer: 
  2806.  
  2807. The ID 0x8008 is the value of the constant FID_CLIENT (and IC_FRAME_CLIENT_ID). 
  2808. The frame forces its client to have that ID so it knows the window is the 
  2809. client window. If you use a different value, IFrameWindow::setClient changes 
  2810. the window ID for you. The client window's ID must remain FID_CLIENT, or the 
  2811. frame won't format correctly or correctly dispatch events to the client window. 
  2812.  
  2813. You can obtain the FID_CLIENT definition from <pmwin.h>. IC_FRAME_CLIENT_ID is 
  2814. defined in <icconst.h>. 
  2815.  
  2816.  
  2817. ΓòÉΓòÉΓòÉ 10.3.5. How Do I Set Up an IFrameWindow within an IFrameWindow? ΓòÉΓòÉΓòÉ
  2818.  
  2819. Question: 
  2820.  
  2821. I have created a primary window using IFrameWindow.  I also created a second 
  2822. IFrameWindow as a child of the primary window, using the primary window as both 
  2823. its parent and owner. How do I prevent the child frame from being positioned 
  2824. over the menu bar of my primary window? 
  2825.  
  2826. Answer: 
  2827.  
  2828. You need to add a client area window to the parent frame, and make the client 
  2829. the parent of the child frame.  This will also keep the child frame from 
  2830. overwriting the borders of the parent frame. 
  2831.  
  2832.  
  2833. ΓòÉΓòÉΓòÉ 10.3.6. Can I Use a Frame as a Client Window? ΓòÉΓòÉΓòÉ
  2834.  
  2835. Question: 
  2836.  
  2837. Can I use a frame window as the client window of another frame?  I tried to do 
  2838. this, but saw strange results. 
  2839.  
  2840. Answer: 
  2841.  
  2842. A frame window does not work well as a client window because of certain aspects 
  2843. of PM's frame-window procedure. 
  2844.  
  2845. A PM frame window sends itself certain messages like WM_FORMATFRAME and 
  2846. WM_UPDATEFRAME, and expects to receive these messages only from itself. It also 
  2847. forwards these messages to its client window (as part of the frame-client 
  2848. message protocol). 
  2849.  
  2850. If the client window is a frame window, the client expects these messages to 
  2851. come only from itself.  When it receives them from the parent frame window 
  2852. instead, the resulting processing can give unexpected results. 
  2853.  
  2854. Accelerator keys and WM_HELP messages are also likely to be processed by the 
  2855. client frame, rather than its parent, which might not be what you expect. 
  2856.  
  2857.  
  2858. ΓòÉΓòÉΓòÉ 10.3.7. Can I Have Automatic Resizing for Dialogs? ΓòÉΓòÉΓòÉ
  2859.  
  2860. Question: 
  2861.  
  2862. If I use the Dialog Editor to build my dialog and then create an IFrameWindow 
  2863. from it, will the controls reflow when the main window is sized? Can I make the 
  2864. dialog fill the whole client area in the main window? 
  2865.  
  2866. Answer: 
  2867.  
  2868. If you use a dialog template to lay out the controls, there is no "reflowing" 
  2869. when you size the frame.  The dialog will fill the whole frame. The dialog 
  2870. controls will be sized and positioned as you specified in the dialog template. 
  2871.  
  2872. Automatic sizing is only done on the client window of an IFrameWindow. You can 
  2873. use the canvas classes to construct windows with dialog behavior that are also 
  2874. resized when the frame is resized. 
  2875.  
  2876. Typically there is no client window in dialogs that are generated using the 
  2877. Dialog Editor.  However, if your dialog template does happen to have a window 
  2878. with an ID of FID_CLIENT (0x8008), IFrameWindow::client will return it 
  2879. regardless of whether you've called setClient. You still have to use one of the 
  2880. User Interface classes as a wrapper for your client window so that there is an 
  2881. IWindow pointer to return to you. You can use IFrameWindow::clientHandle to get 
  2882. back a window handle even if you haven't wrappered the client window with a 
  2883. User Interface class. 
  2884.  
  2885.  
  2886. ΓòÉΓòÉΓòÉ 10.3.8. Why Doesn't My Control Defined in a DLG Resource Work? ΓòÉΓòÉΓòÉ
  2887.  
  2888. Question: 
  2889.  
  2890. I want to create a combo box that is read-only.  I instantiated an 
  2891. IComboBox::Style class, set it to dropDownListType, and passed it to the combo 
  2892. box constructor, but the user can still change the entry field part of the 
  2893. combo box without using the list box control. What should I do? 
  2894.  
  2895. Answer: 
  2896.  
  2897. The combo box is defined in a PM dialog template.  The first constructor 
  2898. creates a new combo box control, which is 0-sized, so you can't see it. Your 
  2899. code is acting on this 0-sized combo box, not the visible one created by the 
  2900. dialog template. 
  2901.  
  2902. The second constructor correctly wraps the combo box created by the dialog box. 
  2903. Because the type of the combo box can only be specified when the control is 
  2904. created, you must change how the combo box is defined in the dialog template. 
  2905.  
  2906. Both constructors create an IComboBox C++ object.  The first also creates a 
  2907. combo box control.  The second requires an existing control that will be 
  2908. represented by the IComboBox object. 
  2909.  
  2910.  
  2911. ΓòÉΓòÉΓòÉ 10.3.9. Should I Use Canvas Classes or Dialog Templates? ΓòÉΓòÉΓòÉ
  2912.  
  2913. Question: 
  2914.  
  2915. I am creating some PM dialogs. Should I use the Dialog Editor to create dialog 
  2916. templates (.DLG files), or should I create them inline in code using the canvas 
  2917. classes? 
  2918.  
  2919. Answer: 
  2920.  
  2921. If you are targeting your application only for OS/2 in a relatively homogeneous 
  2922. environment, the Dialog Editor and Resource Compiler provide a quick way to 
  2923. create the dialogs. 
  2924.  
  2925. However, many applications written today require that you consider support for 
  2926. portabilility, multiple monitor resolutions, fonts, and national language. When 
  2927. these factors come into play, maintaining the dialog resources becomes a major 
  2928. undertaking.  Using the canvas classes may prove more effective in cases where 
  2929. one or more of these factors are important. 
  2930.  
  2931. The canvas classes provide layout support that can dynamically change based on 
  2932. language, fonts, and so on.  You lay your controls out on a canvas aligned 
  2933. relative to one another in a row and column type gridding, and the class 
  2934. handles the rest. 
  2935.  
  2936. Take a look at the Hello World sample (HELLO6 in particular) for an example of 
  2937. how this works.  It shows an example of the same application using different 
  2938. language resources.  By bringing each one up, you can see how the same code 
  2939. will handle the language changes. You can also drop fonts onto the canvas, and 
  2940. you will see how it handles that as well. 
  2941.  
  2942. The portability of dialog resources is also very limited.  The canvas classes 
  2943. are fully supported in the Motif version of the User Interface classes (shipped 
  2944. with C Set ++ for AIX), but dialog templates are not supported at all. 
  2945.  
  2946. Refer to the chapter on Creating Dialogs in the Open Class Library User's 
  2947. Guide. 
  2948.  
  2949.  
  2950. ΓòÉΓòÉΓòÉ 10.3.10. Can I Set the Minimum Size of an IFrameWindow? ΓòÉΓòÉΓòÉ
  2951.  
  2952. Question: 
  2953.  
  2954. I have a frame window with a client window that is an instance of 
  2955. IMultiCellCanvas.  Thus it has a minimum size. When I resize the frame window 
  2956. with the mouse, it is resized but the client does not become smaller than its 
  2957. minimum size, so part of the client window is not visible. 
  2958.  
  2959. Is there a way to force a frame window not to become smaller than the minimum 
  2960. size of its client window? 
  2961.  
  2962. Answer: 
  2963.  
  2964. There is no direct support in the library for making the frame window behave in 
  2965. this way. You may be able to control this behavior by creating a handler that 
  2966. processes the WM_QUERYTRACKINFO message to limit resizing using the mouse. 
  2967.  
  2968. If you are initially sizing the frame, you can query the minimum size of the 
  2969. client window and use the size obtained to size the frame using the 
  2970. IFrameWindow::moveSizeToClient function. 
  2971.  
  2972.  
  2973. ΓòÉΓòÉΓòÉ 10.3.11. How Do I Access the Scroll Bars on an IFrameWindow? ΓòÉΓòÉΓòÉ
  2974.  
  2975. Question: 
  2976.  
  2977. If I create a frame window with the IFrameWindow::horizontalScroll and 
  2978. IFrameWindow::verticalScroll styles, are there any ways to access these 
  2979. scrollbars? 
  2980.  
  2981. Answer: 
  2982.  
  2983. In PM, you can construct IScrollBar objects for them as follows: 
  2984.  
  2985.   IScrollBar* vert = new IScrollBar( FID_VERTSCROLL, &frameWindow );
  2986.   IScrollBar* horz = new IScrollBar( FID_HORZSCROLL, &frameWindow );
  2987.  
  2988. (The window IDs, FID_VERTSCROLL and FID_HORZSCROLL are defined in <pmwin.h>.) 
  2989.  
  2990. If you do the above, you have to provide the scrolling support yourself. You 
  2991. can use the IScrollBar and IScrollHandler classes to provide this support. 
  2992.  
  2993. Alternatively, you can use an IViewPort as your client window, in place of the 
  2994. frame scroll bars.  Generally IViewPort does not require you to provide any 
  2995. code for it to scroll a window. 
  2996.  
  2997.  
  2998. ΓòÉΓòÉΓòÉ 10.3.12. Why Does My Dialog Overwrite the Parent Notebook? ΓòÉΓòÉΓòÉ
  2999.  
  3000. Question: 
  3001.  
  3002. I'm adding a dialog page to a notebook. When I run my code, the dialog pops up 
  3003. on the screen overwriting parts of the notebook. When I turn to that notebook 
  3004. page, the dialog appears normally.  What am I doing wrong? 
  3005.  
  3006. Answer: 
  3007.  
  3008. Be sure that your dialog does not have a WS_VISIBLE style.  If this style is 
  3009. set, the dialog will be drawn over its parent (the notebook) when it is loaded. 
  3010.  
  3011.  
  3012. ΓòÉΓòÉΓòÉ 10.3.13. Why Doesn't My Application End when the Frame is Closed? ΓòÉΓòÉΓòÉ
  3013.  
  3014. Question: 
  3015.  
  3016. I used to end my application by calling IFrameWindow::close, but after I added 
  3017. an IObjectWindow, it only closes my frame window and leaves the executable 
  3018. still running.  The last things I added were my frame window but leaves .EXE 
  3019. still running. What is happening? 
  3020.  
  3021. Answer: 
  3022.  
  3023. The problem you are seeing is probably caused by the object window.  When you 
  3024. create an instance of IObjectWindow, the library flags this window as a primary 
  3025. window (just like a frame window that is a child of the desktop). 
  3026. IApplication::current().run() will not complete processing until all primary 
  3027. windows have been closed.  Try adding a call to setParent for the object 
  3028. window; this should cause the library to remove the primary flag for the 
  3029. window. 
  3030.  
  3031.   myObjectWindow->setParent(IWindow::objectWindow());
  3032.  
  3033.  
  3034. ΓòÉΓòÉΓòÉ 10.3.14. How Do I Exit IApplication::current().run() ? ΓòÉΓòÉΓòÉ
  3035.  
  3036. Question: 
  3037.  
  3038. I have a simple application that calls IApplication::current().run(). I want to 
  3039. override the command function of ICommandHandler so that when the user selects 
  3040. an exit button, the application is terminated. What is the correct way to 
  3041. terminate my main window if I want more actions to be executed when the user 
  3042. chooses the exit button? 
  3043.  
  3044. Answer: 
  3045.  
  3046. Call IFrameWindow::close when the application is to be terminated. This 
  3047. function closes the frame and, if it is the primary frame window, exits the 
  3048. event loop. Exiting the event loop causes IApplication::current().run() to 
  3049. return to the caller. 
  3050.  
  3051. Note that this technique can also be applied to IFrameWindow objects that are 
  3052. running on secondary threads. 
  3053.  
  3054. When an IFrameWindow is not involved, such as when you are using an 
  3055. IObjectWindow, you can call IThread::stopProcessingMsgs to exit the event loop. 
  3056.  
  3057.  
  3058. ΓòÉΓòÉΓòÉ 10.4. Canvas Classes ΓòÉΓòÉΓòÉ
  3059.  
  3060. This section answers questions about the canvas classes: ICanvas, ISetCanvas, 
  3061. IMultiCellCanvas, ISplitCanvas, and IViewPort. 
  3062.  
  3063.      Can I Resize an IViewPort Child Window? 
  3064.      How Do I Center a Control on a Canvas? 
  3065.      How Do Tabbing and Cursor Movement Work? 
  3066.      Why Does My Canvas Work with new But Not with Solid Objects? 
  3067.      How Do I Get a Fixed Column Size for an IMultiCellCanvas? 
  3068.      Does Changing the Minimum Size Affect Control Behavior? 
  3069.      How Do I Draw Separator Lines in an IMultiCellCanvas? 
  3070.      Why Doesn't removeFromCell Remove the Window Text? 
  3071.      How Many Windows Does IViewPort Have? 
  3072.      How Do I Align an IComboBox in an IMultiCellCanvas? 
  3073.  
  3074.  
  3075. ΓòÉΓòÉΓòÉ 10.4.1. Can I Resize an IViewPort Child Window? ΓòÉΓòÉΓòÉ
  3076.  
  3077. Question: 
  3078.  
  3079. I want to create an IViewPort that resizes the child window when the size of 
  3080. the viewport is greater than the minimum size of the child.  When one of the 
  3081. dimensions for the viewport is greater than the corresponding dimensions of the 
  3082. child window's minumum size, the scroll bar is removed and the child is resized 
  3083. along that dimension. When the viewport's dimension is less than the child 
  3084. window's minumum size, the scroll bar must reappear. 
  3085.  
  3086. How can I do this? 
  3087.  
  3088. Answer: 
  3089.  
  3090. The following code creates a resize handler that you can attach to any viewport 
  3091. to perform the function you describe. The code is for a viewport that scrolls a 
  3092. multicell canvas, but you could also use it for other types of windows. Further 
  3093. discussion of this and other canvas tricks be found in chapter 15 of OS/2 C++ 
  3094. Class Library: Power GUI Programming with C Set ++. A complete program using 
  3095. code similar to that below is on the disk that comes with that book. 
  3096.  
  3097. class SizeHandlerForViewPortWithMultiCell : public IResizeHandler {
  3098. public:
  3099. virtual SizeHandlerForViewPortWithMultiCell
  3100.  &handleEventsFor       ( IViewPort* viewport ),
  3101.  &stopHandlingEventsFor ( IViewPort* viewport );
  3102.  
  3103. protected:
  3104. virtual Boolean
  3105.   windowResize          ( IResizeEvent& event );
  3106.  
  3107. private:
  3108. virtual IHandler
  3109.  &handleEventsFor       ( IWindow* window  ),
  3110.  &stopHandlingEventsFor ( IWindow* window  );
  3111. };
  3112.  
  3113. Boolean SizeHandlerForViewPortWithMultiCell :: windowResize
  3114.                                        ( IResizeEvent& event )
  3115. {
  3116.   IViewPort* viewport = (IViewPort*)event.window();
  3117.   IMultiCellCanvas* canvas =
  3118.       (IMultiCellCanvas*)IWindow::windowWithHandle
  3119.                                     ( viewport->viewWindow() );
  3120.   if (canvas)
  3121.   {
  3122.      ISize newSize = event.newSize();
  3123.      ISize minChildSize = canvas->minimumSize();
  3124.      ISize childSize = canvas->size();
  3125.  
  3126.      ISize newChildSize = newSize;  // Grow to viewport size.
  3127.      if (newSize.width() < minChildSize.width())
  3128.      {     // Don't shrink child smaller than its minimum size.
  3129.         newChildSize.setWidth( minChildSize.width() );
  3130.      }                  // (Let the viewport scroll it.)
  3131.      else if (newSize.height() < minChildSize.height())
  3132.      {         // Allow room for vertical scroll bar if needed.
  3133.         newChildSize.setWidth( newSize.width() -
  3134.                viewport->verticalScrollBar()->size().width() );
  3135.         if (newChildSize.width() < minChildSize.width())
  3136.         {  // Don't shrink child smaller than its minimum size.
  3137.            newChildSize.setWidth( minChildSize.width() );
  3138.         }               // (Let the viewport scroll it.)
  3139.      }
  3140.  
  3141.      if (newSize.height() < minChildSize.height())
  3142.      {     // Don't shrink child smaller than its minimum size.
  3143.         newChildSize.setHeight( minChildSize.height() );
  3144.      }                  // (Let the viewport scroll it.)
  3145.      else if (newSize.width() < minChildSize.width())
  3146.      {      // Allow room for horizontal scroll bar if needed.
  3147.         newChildSize.setHeight( newSize.height() -
  3148.             viewport->horizontalScrollBar()->size().height() );
  3149.         if (newChildSize.height() < minChildSize.height())
  3150.         {  // Don't shrink child smaller than its minimum size.
  3151.            newChildSize.setHeight( minChildSize.height() );
  3152.         }               // (Let the viewport scroll it.)
  3153.      }
  3154.  
  3155.      if (newChildSize != childSize)
  3156.      {           // Need to resize the child multi-cell canvas.
  3157.         canvas->sizeTo( newChildSize );
  3158.      }
  3159.   }
  3160.   return false;         // Let viewport also process this.
  3161. }
  3162.  
  3163. SizeHandlerForViewPortWithMultiCell&
  3164.   SizeHandlerForViewPortWithMultiCell :: handleEventsFor
  3165.                                          ( IViewPort* viewport )
  3166. {
  3167.   IASSERTPARM( viewport != 0 );
  3168.   IResizeHandler::handleEventsFor( viewport );
  3169.  
  3170.   IMultiCellCanvas* canvas =
  3171.       (IMultiCellCanvas*)IWindow::windowWithHandle
  3172.                                     ( viewport->viewWindow() );
  3173.   if (canvas)           // Don't leave canvas with 0 size.
  3174.   {                     // Have viewport deal with real size.
  3175.      canvas->sizeTo( ISize( 1, 1 ));
  3176.   }
  3177.   return *this;
  3178. }
  3179.  
  3180. SizeHandlerForViewPortWithMultiCell&
  3181.   SizeHandlerForViewPortWithMultiCell :: stopHandlingEventsFor
  3182.                                          ( IViewPort* viewport )
  3183. {
  3184.   IASSERTPARM( viewport != 0 );
  3185.   IResizeHandler::stopHandlingEventsFor( viewport );
  3186.   return *this;
  3187. }
  3188.  
  3189. IHandler&
  3190.   SizeHandlerForViewPortWithMultiCell :: handleEventsFor
  3191.                                             ( IWindow* window  )
  3192. {                       // Private to hide version in IHandler.
  3193.   window;
  3194.   ITHROWLIBRARYERROR( IC_MEMBER_ACCESS_ERROR,
  3195.                       IErrorInfo::invalidRequest,
  3196.                       IException::recoverable );
  3197.   return *this;
  3198. }
  3199.  
  3200. IHandler&
  3201.   SizeHandlerForViewPortWithMultiCell :: stopHandlingEventsFor
  3202.                                             ( IWindow* window  )
  3203. {                       // Private to hide version in IHandler.
  3204.   window;
  3205.   ITHROWLIBRARYERROR( IC_MEMBER_ACCESS_ERROR,
  3206.                       IErrorInfo::invalidRequest,
  3207.                       IException::recoverable );
  3208.   return *this;
  3209. }
  3210.  
  3211.  
  3212. ΓòÉΓòÉΓòÉ 10.4.2. How Do I Center a Control on a Canvas? ΓòÉΓòÉΓòÉ
  3213.  
  3214. Question: 
  3215.  
  3216. I have a single push button on an ISetCanvas. I then put the ISetCanvas on an 
  3217. IMultiCellCanvas.  How do I center the button horizontally in the cell? 
  3218.  
  3219. Answer: 
  3220.  
  3221. You can use a multicell canvas to center a control. Add the control (for 
  3222. example, a set canvas or single pushbutton) to cell 2, 2. Then mark rows 1 and 
  3223. 3, and columns 1 and 3 as expandable. 
  3224.  
  3225. Because canvas objects can be nested, you can apply this technique to center a 
  3226. small control in a row containing another large control. 
  3227.  
  3228.  
  3229. ΓòÉΓòÉΓòÉ 10.4.3. How Do Tabbing and Cursor Movement Work? ΓòÉΓòÉΓòÉ
  3230.  
  3231. Question: 
  3232.  
  3233. Can the enableTabStop and enableGroup functions work on buttons or entry fields 
  3234. not owned by the same window? Do these functions effect how the tab key works 
  3235. in moving the cursor between entry fields? 
  3236.  
  3237. Answer: 
  3238.  
  3239. Tabbing and cursor-arrowing work as they do in PM. You can only tab to windows 
  3240. with the tabStop style.  You can only use arrow keys to move around in a group. 
  3241. A group is defined by giving the first window in the group the group style. 
  3242. The group ends when the next group is found. All windows in a group must also 
  3243. have the same parent window. 
  3244.  
  3245. Tabbing and arrowing are supported by frame windows and canvases. The control 
  3246. with the keyboard focus must be owned by a frame or canvas (so that frame or 
  3247. canvas can get the tab or arrow key not processed by the control). The control 
  3248. must also be a child window of the same frame or canvas (so the frame or canvas 
  3249. can enumerate child windows to find where to move the input focus to). You can 
  3250. also tab from a control in one canvas to a sibling window of the canvas or to a 
  3251. child control of a sibling canvas. 
  3252.  
  3253.  
  3254. ΓòÉΓòÉΓòÉ 10.4.4. Why Does My Canvas Work with new But Not with Solid Objects? ΓòÉΓòÉΓòÉ
  3255.  
  3256. Question: 
  3257.  
  3258. I can construct children of canvas classes using new, but when I try to 
  3259. construct them as solid objects as shown in the Open Class Library User's 
  3260. Guide, I get a SYS3170 or SYS3175 error message.  Why? 
  3261.  
  3262. Answer: 
  3263.  
  3264. A typical problem of using solid objects rather than pointers for data members 
  3265. (child windows) of a class is getting the wrong order of construction.  Parent 
  3266. and owner windows must be constructed before their child windows and windows 
  3267. they own. The order of their construction is dictated by their order in the 
  3268. class declaration (.hpp file), rather than how they appear in the constructor's 
  3269. initializer list (the .cpp file). 
  3270.  
  3271.  
  3272. ΓòÉΓòÉΓòÉ 10.4.5. How Do I Get a Fixed Column Size for an IMultiCellCanvas? ΓòÉΓòÉΓòÉ
  3273.  
  3274. Question: 
  3275.  
  3276. I have a 2-column IMultiCellCanvas that I dynamically build; the contents are 
  3277. also created dynamically.  The first column is an IStaticText with a style of 
  3278. default and workbreak. I want this text to split to multiple lines if it is 
  3279. longer than 20 characters. What should I do? 
  3280.  
  3281. Answer: 
  3282.  
  3283. IMultiCellCanvas uses the minimum size of the child window to determine the 
  3284. size that a column or row can be decreased to. Using setColumnWidth will not 
  3285. allow the column to be made smaller than that amount. 
  3286.  
  3287. If no minimum size value exists for a window, IMultiCellCanvas calls 
  3288. calcMinimumSize for that window to obtain the minimum size. For IStaticText, 
  3289. calcMinimumSize returns the larger of the text length in pixels or the text 
  3290. limit times the average character width. 
  3291.  
  3292. To do what you want, you need to set the minimum size of the IStaticText window 
  3293. yourself, before IMultiCellCanvas queries for the minimum size.  For an example 
  3294. that shows how to do this, click below: 
  3295.  
  3296. Example 
  3297.  
  3298. Debugging gridlines were also added to the example because they are useful for 
  3299. altering window sizes. 
  3300.  
  3301.  
  3302. ΓòÉΓòÉΓòÉ <hidden> Example of Fixed Column Size in IMultiCell Canvas ΓòÉΓòÉΓòÉ
  3303.  
  3304. /**********************************************************************/
  3305. /* Sample program                                                     */
  3306. /**********************************************************************/
  3307.                                    //Include IBM UI class headers:
  3308. #include <iapp.hpp>                  //IApplication Class
  3309. #include <iframe.hpp>                //Include IFrameWindow Class Header
  3310. #include <imcelcv.hpp>
  3311. #include <ientryfd.hpp>
  3312. #include <istattxt.hpp>
  3313.  
  3314. #define IDC_WINDOW    0x1000
  3315. #define IDC_TEST      0x1001
  3316. #define IDC_CONTROL1  0x1002
  3317. #define IDC_CONTROL2  0x1003
  3318.  
  3319. /**********************************************************************/
  3320. /* main  - Application entry point                                    */
  3321. /**********************************************************************/
  3322. void main()
  3323. {
  3324.   /********************************************************************/
  3325.   /* Create a main frame window on the desktop                        */
  3326.   /********************************************************************/
  3327.   IFrameWindow mainWindow( "Sample MCV", IDC_WINDOW );
  3328.  
  3329.   /********************************************************************/
  3330.   /* Create a multicell canvas with the frame as owner & parent       */
  3331.   /*                                                                  */
  3332.   /********************************************************************/
  3333.   IMultiCellCanvas testMCV( IDC_TEST, &mainWindow, &mainWindow,
  3334.                             IRectangle(), IMultiCellCanvas::gridLines |
  3335.                             IMultiCellCanvas::dragLines |
  3336.                             IWindow::visible );
  3337.  
  3338.   /********************************************************************/
  3339.   /* Create 2 controls for placing into the multicell                 */
  3340.   /********************************************************************/
  3341.   IStaticText *stControl1 = new IStaticText ( IDC_CONTROL1,
  3342.                                    &testMCV, &testMCV, IRectangle(),
  3343.                                    IStaticText::left |
  3344.                                    IStaticText::top |
  3345.                                    IStaticText::wordBreak |
  3346.                                    IStaticText::fillBackground |
  3347.                                    IWindow::visible);
  3348.   IEntryField *efControl2 = new IEntryField( IDC_CONTROL2,
  3349.                                    &testMCV, &testMCV, IRectangle(),
  3350.                                    IEntryField::defaultStyle() );
  3351.  
  3352.   /********************************************************************/
  3353.   /* Set the text of each of these controls after setting minimum     */
  3354.   /* size of the static text field                                    */
  3355.   /********************************************************************/
  3356.   stControl1->setMinimumSize( ISize( 70, 20 ));
  3357.   stControl1->setText("Control #1 test ... this one wraps");
  3358.   efControl2->setText("Control 2");
  3359.  
  3360.   /********************************************************************/
  3361.   /* Now place them into the multi-cell and adjust columns            */
  3362.   /********************************************************************/
  3363.   testMCV.addToCell( stControl1, 2,2, 1,1);
  3364.   testMCV.addToCell( efControl2, 4,2, 1,1);
  3365.   testMCV.setColumnWidth( 2, 20, false);
  3366.   testMCV.setColumnWidth( 4, 80, true);
  3367.   testMCV.setRowHeight( 2, 20, true);
  3368.  
  3369.   testMCV.refresh();
  3370.  
  3371.   /********************************************************************/
  3372.   /* Make the created text field the client of the frame window,      */
  3373.   /* change focus to the frame and show it.                           */
  3374.   /********************************************************************/
  3375.   mainWindow.setClient(&testMCV);
  3376.   mainWindow.setFocus();
  3377.   mainWindow.show();
  3378.  
  3379.   /********************************************************************/
  3380.   /* Run the application as built                                     */
  3381.   /********************************************************************/
  3382.   IApplication::current().run();
  3383.  
  3384.   return;
  3385. }
  3386.  
  3387.  
  3388. ΓòÉΓòÉΓòÉ 10.4.6. Does Changing the Minimum Size Affect Control Behavior? ΓòÉΓòÉΓòÉ
  3389.  
  3390. Question: 
  3391.  
  3392. If I use minimumSize to get the minimum size of a control, and then set the 
  3393. minimum size of this same control to that value, is the control's behavior 
  3394. affected? 
  3395.  
  3396. Answer: 
  3397.  
  3398. Yes.  Querying the minimumSize and then setting this value as the minimum size 
  3399. does change the behavior.  Once the minimumSize has been set, that value is 
  3400. always used; for example, if the font or text limit changes, the minimumSize 
  3401. does not change.  If the minimumSize is not set, changes to the control (such 
  3402. as font or text limit) may cause the control to have a different minimum size. 
  3403. You can call IWindow::resetMinimumSize to cause a window to discard the effects 
  3404. of any previous calls to IWindow::setMinimumSize. 
  3405.  
  3406.  
  3407. ΓòÉΓòÉΓòÉ 10.4.7. How Do I Draw Separator Lines in an IMultiCellCanvas? ΓòÉΓòÉΓòÉ
  3408.  
  3409. Question: 
  3410.  
  3411. How do I draw a horizontal separator line between cells of a multicell canvas? 
  3412. Is there a control that can be used across all the cells of the canvas? 
  3413.  
  3414. Answer: 
  3415.  
  3416. You could use an IStaticText and set it to the background color of the 
  3417. separator you want and a small minimum size.  The height of the minimum size 
  3418. would be used as the thickness of a horizontal line. The minimum width would 
  3419. not be important because the length of the line would be stretched by the 
  3420. columns it occupies.  This solution does require that you place IStaticText 
  3421. objects in each of the cells of the IMultiCellCanvas where you want separators 
  3422. to appear. 
  3423.  
  3424.  
  3425. ΓòÉΓòÉΓòÉ 10.4.8. Why Doesn't removeFromCell Remove the Window Text? ΓòÉΓòÉΓòÉ
  3426.  
  3427. Question: 
  3428.  
  3429. I am using IMultiCellCanvas::removeFromCell to remove windows from my multicell 
  3430. canvas that were added using IMultiCellCanvas::addToCell. However, the window 
  3431. text associated with the removed window remains visible in the multicell 
  3432. canvas, even after I call IWindow::refresh. Why? 
  3433.  
  3434. Answer: 
  3435.  
  3436. The library does not delete the child window after you call removeFromCell. As 
  3437. a result, the child window still exists, but is never resized or repositioned 
  3438. when the layout of the canvas changes. For this reason, if you are not adding 
  3439. the child window to a different cell, you should either delete it, hide it, or 
  3440. change its parent to the object window so it does not remain in the canvas. 
  3441. Note that keyboard navigation can also be affected by the child window. 
  3442.  
  3443.  
  3444. ΓòÉΓòÉΓòÉ 10.4.9. How Many Windows Does IViewPort Have? ΓòÉΓòÉΓòÉ
  3445.  
  3446. Question: 
  3447.  
  3448. Are there more windows to an IViewPort than just a canvas and some scroll bars? 
  3449.  
  3450. Answer: 
  3451.  
  3452. Yes.  A viewport has an additional window that is not obvious. Basically, it is 
  3453. an ICanvas that clips your view window so it does not overwrite the scrollbars. 
  3454. (The viewport makes the parent window of your view window the view rectangle.) 
  3455. The window IDs of these child windows are defined in <icconst.h>. 
  3456.  
  3457.  
  3458. ΓòÉΓòÉΓòÉ 10.4.10. How Do I Align an IComboBox in an IMultiCellCanvas? ΓòÉΓòÉΓòÉ
  3459.  
  3460. Question: 
  3461.  
  3462. I have a multicell canvas with a DropDownList combo box between two entry 
  3463. fields, but the combo box does not align correctly. I want the combo box to 
  3464. occupy a single line, and when I open it, to cover the second entry field. 
  3465. Instead, it takes extra lines. How can I get the box to take less space until 
  3466. it's opened? 
  3467.  
  3468. Answer: 
  3469.  
  3470. For a drop-down or read-only-drop-down combo box, you should have the combo box 
  3471. only occupy one row.  This is the row that its entry field and drop-down button 
  3472. will appear in.  The size of the drop-down list should be controlled with the 
  3473. IComboBox::setMinimumRows function.  The list box will appear over rows below 
  3474. the combo box, and could even stretch below the bottom of the multi-cell 
  3475. canvas. 
  3476.  
  3477.  
  3478. ΓòÉΓòÉΓòÉ 10.5. Container Control ΓòÉΓòÉΓòÉ
  3479.  
  3480. This section discusses the IContainerControl class and related classes. 
  3481.  
  3482.      Why Aren't Objects Sorted in Icon View? 
  3483.      How Do I Insert a Container Object as the First Object? 
  3484.      What Does extendedSelection Mean? 
  3485.      What Happens to Child Objects when an Object is Removed? 
  3486.      How Many Objects Can I Have in a Container? 
  3487.      Can I Use Small Icons in an IContainerControl? 
  3488.      Why Doesn't My Pop-Up Menu Work? 
  3489.      How Can I Wrap Text in Columns or Column Headings? 
  3490.      How Should I Handle Date and Time in a Container? 
  3491.      How Do I Access Members of a Derived IContainerObject? 
  3492.      Why Doesn't My Container Display? 
  3493.      Can I Display Items in Tree View on User Request? 
  3494.      Why Are All Container Objects Deleted from a Tree View? 
  3495.      Can I Have Two Instances of the Same Object in a Container? 
  3496.  
  3497.  
  3498. ΓòÉΓòÉΓòÉ 10.5.1. Why Aren't Objects Sorted in Icon View? ΓòÉΓòÉΓòÉ
  3499.  
  3500. Question: 
  3501.  
  3502. I have a sort function for a container that works correctly when the container 
  3503. is in tree or details view. However, when it is in icon view, the container is 
  3504. not refreshed until arrangeIconView is called or the view type is changed. Do I 
  3505. have to call arrangeIconView after sorting an icon view? If so, why? 
  3506.  
  3507. Answer: 
  3508.  
  3509. By default, the arrangement of the icon view is independent of the order of the 
  3510. objects in the container. This is to preserve any user arrangement of the 
  3511. objects through direct manipulation or any positioning that might have been 
  3512. done on insertion. If you always want the icon view to be sorted, you can 
  3513. either specify the IContainerControl::autoPosition style for the container or 
  3514. call arrangeIconView after the sort. 
  3515.  
  3516.  
  3517. ΓòÉΓòÉΓòÉ 10.5.2. How Do I Insert a Container Object as the First Object? ΓòÉΓòÉΓòÉ
  3518.  
  3519. Question: 
  3520.  
  3521. I want to be able to add IContainerObjects to my container. I know I can use 
  3522. addObject and addObjectAfter to add IContainerObjects to my container after a 
  3523. specified object. How do I add an object as the first object in the container? 
  3524.  
  3525. Answer: 
  3526.  
  3527. To add an object at the beginning of the container, specify 0 as the second 
  3528. argument to addObjectAfter or addObjectsAfter. For example: 
  3529.  
  3530.   addObjectAfter(newObject, 0);
  3531.  
  3532.  
  3533. ΓòÉΓòÉΓòÉ 10.5.3. What Does extendedSelection Mean? ΓòÉΓòÉΓòÉ
  3534.  
  3535. Question: 
  3536.  
  3537. What does the IContainerControl::Style extendedSelection mean? 
  3538.  
  3539. Answer: 
  3540.  
  3541. Extended selection is an enhanced form of single selection you can use to 
  3542. select discontinuous ranges of objects. For example, you use extended selection 
  3543. when you select objects in an OS/2 Workplace Shell folder. 
  3544.  
  3545. Extended selection works like single selection unless you use shift or control 
  3546. keys. The control key allows discontinuous selection like multiple selection. 
  3547. The shift key allows range selection as an editor would. 
  3548.  
  3549. If the user of your container should only be able to select one object, use 
  3550. single selection. If the user would typically select many objects, use multiple 
  3551. selection. If the user would typically select one object, but could optionally 
  3552. select more, use extended selection. 
  3553.  
  3554.  
  3555. ΓòÉΓòÉΓòÉ 10.5.4. What Happens to Child Objects when an Object is Removed? ΓòÉΓòÉΓòÉ
  3556.  
  3557. Question: 
  3558.  
  3559. In my tree view container, I have an object with two child objects. If I remove 
  3560. the object, the two child objects are also removed. If I delete the object, 
  3561. what happens to the child objects? 
  3562.  
  3563. Answer: 
  3564.  
  3565. When you remove or delete an object from a container in tree view, all of its 
  3566. child objects are also removed or deleted. 
  3567.  
  3568.  
  3569. ΓòÉΓòÉΓòÉ 10.5.5. How Many Objects Can I Have in a Container? ΓòÉΓòÉΓòÉ
  3570.  
  3571. Question: 
  3572.  
  3573. Is there a limit on the number of container objects I can add to a container? 
  3574.  
  3575. Answer: 
  3576.  
  3577. IContainerControl imposes no limit other than that set by the underlying 
  3578. container control. 
  3579.  
  3580. In the OS/2 implementation, the maximum number of records is limited by the 
  3581. amount of memory in the computer. The container control does not limit the 
  3582. number of records that a container can have. 
  3583.  
  3584. In the Motif implementation, there is a limit of approximately 1050 records 
  3585. that can be displayed in a one-dimensional view such as details or tree.  (The 
  3586. reason is that position values in the X Intrinsics use a signed 16-bit value.) 
  3587. To work around this limitation, limit the number of objects displayed at any 
  3588. one time. 
  3589.  
  3590.  
  3591. ΓòÉΓòÉΓòÉ 10.5.6. Can I Use Small Icons in an IContainerControl? ΓòÉΓòÉΓòÉ
  3592.  
  3593. Question: 
  3594.  
  3595. For my container's tree icon view, can I use small icons like the small size 
  3596. OS/2 desktop icons? 
  3597.  
  3598. Answer: 
  3599.  
  3600. Version 3.0 supports a new style, IContainerControl::miniIcons, that uses 
  3601. mini-icons.  These are similar to the Workplace Shell small icons. Also refer 
  3602. to the function IContainerControl::showMiniIcons. 
  3603.  
  3604.  
  3605. ΓòÉΓòÉΓòÉ 10.5.7. Why Doesn't My Pop-Up Menu Work? ΓòÉΓòÉΓòÉ
  3606.  
  3607. Question: 
  3608.  
  3609. Why doesn't the pop-up menu for my container work correctly? 
  3610.  
  3611. Answer: 
  3612.  
  3613. Here are some tips on pop-up menus: 
  3614.  
  3615.      When you create a menu handler class for a container, derive it from 
  3616.       ICnrMenuHandler instead of IMenuHandler. 
  3617.  
  3618.      Remember that an object is not selected by the manipulation mouse button 
  3619.       (right mouse-button click). What is shown visually is source emphasis. 
  3620.       You must keep track of the pop-up menu object yourself. Store the pointer 
  3621.       to the object returned by popupMenuObject, and use this pointer to 
  3622.       process a pop-up menu event for that object. 
  3623.  
  3624.      In your command handler, make sure you differentiate between commands 
  3625.       invoked from the pop-up menu and those invoked from the menu bar. A 
  3626.       pop-up menu should use the popupMenuObject; a menu-bar menu should use 
  3627.       selected objects.  You can use different command IDs for the pop-up and 
  3628.       menu bar. 
  3629.  
  3630.      You can also create a pop-up menu for the container itself if the pop-up 
  3631.       is requested when the pointer is not over an object.  In this case, 
  3632.       popupMenuObject returns 0. 
  3633.  
  3634.  
  3635. ΓòÉΓòÉΓòÉ 10.5.8. How Can I Wrap Text in Columns or Column Headings? ΓòÉΓòÉΓòÉ
  3636.  
  3637. Question: 
  3638.  
  3639. Can I make the text in my container columns wrap to the next line? Can I create 
  3640. container column headings that are more than one line? 
  3641.  
  3642. Answer: 
  3643.  
  3644. Yes to both questions. Insert new-line characters in the text where you want 
  3645. line breaks. 
  3646.  
  3647. For the column heading, you can use \x0a in a STRINGTABLE resource.  For 
  3648. example: 
  3649.  
  3650.      TXT_HEAD1     "Line1\x0aLine2"
  3651.  
  3652. Then when you build the container: 
  3653.  
  3654.      col->setHeadingText (TXT_HEAD1);
  3655.  
  3656. The following alternative also works: 
  3657.  
  3658.      col->setHeadingText ("Line1\nLine2");
  3659.  
  3660. To wrap the text in the column, put a new-line character (\n) in the string 
  3661. where you want it to wrap to the next line. For example: 
  3662.  
  3663. Column1 Column2 Column3 Textdata\n    something\n
  3664.                         for this\n    goes here\n
  3665.                         goes \n       for test
  3666.                         here
  3667.  
  3668. The text string for the fourth column would be: 
  3669.  
  3670.  "Textdata\nfor this\ngoes \nhere"
  3671.  
  3672.  
  3673. ΓòÉΓòÉΓòÉ 10.5.9. How Should I Handle Date and Time in a Container? ΓòÉΓòÉΓòÉ
  3674.  
  3675. Question: 
  3676.  
  3677. How should I use IDate and ITime to correctly handle date and time values in a 
  3678. container? 
  3679.  
  3680. Answer: 
  3681.  
  3682. The natural data type for a date in a container is a CDATE, defined in 
  3683. <pmstddlg.h>. Declare your date data member as a CDATE object. When you need to 
  3684. perform arithmetic operations on the value, construct an IDate object from the 
  3685. CDATE type. You can also convert from IDate to CDATE using the asCDATE 
  3686. function. 
  3687.  
  3688. For time, declare your member as a CTIME object, and construct an ITime object 
  3689. when you need to perform operations on the value. 
  3690.  
  3691. Alternatively, you can store the date and time information in the container as 
  3692. strings, and then convert the values using the asString functions of IDate and 
  3693. ITime. 
  3694.  
  3695.  
  3696. ΓòÉΓòÉΓòÉ 10.5.10. How Do I Access Members of a Derived IContainerObject? ΓòÉΓòÉΓòÉ
  3697.  
  3698. Question: 
  3699.  
  3700. The IContainerControl functions to access objects all return IContainerObject 
  3701. pointers.  How do I access functions defined in a class derived from 
  3702. IContainerObject? 
  3703.  
  3704. Answer: 
  3705.  
  3706. Cast the IContainerObject pointer to a pointer to your object. For example: 
  3707.  
  3708.   MyObject* object = (MyObject*)container.objectAt(1);
  3709.   object->myFunction();
  3710.  
  3711.  
  3712. ΓòÉΓòÉΓòÉ 10.5.11. Why Doesn't My Container Display? ΓòÉΓòÉΓòÉ
  3713.  
  3714. Question: 
  3715.  
  3716. I'm trying to use a group box to provide a border for a container, but the 
  3717. container is not being drawn.  Why? 
  3718.  
  3719. Answer: 
  3720.  
  3721. Containers will not paint over a sibling window that overlaps and lies on top 
  3722. of the container, even if the sibling window does not paint that portion of the 
  3723. screen (such as group boxes and outline boxes, which do not paint their 
  3724. interiors, and combination boxes, which do not paint where their drop-down list 
  3725. boxes will be displayed). 
  3726.  
  3727. Create the container first, and then the group box, so that the container lies 
  3728. on top of the group box. 
  3729.  
  3730.  
  3731. ΓòÉΓòÉΓòÉ 10.5.12. Can I Display Items in Tree View on User Request? ΓòÉΓòÉΓòÉ
  3732.  
  3733. Question: 
  3734.  
  3735. I want to partially fill my tree view container and indicate that more items 
  3736. exist, then display those items only when the user selects that branch of the 
  3737. tree. How can I do this? 
  3738.  
  3739. Answer: 
  3740.  
  3741. You can get a list of the top-level objects in the tree and insert each one 
  3742. into the container using 
  3743.  
  3744.   cnr->addObject(topLevelObject);
  3745.  
  3746. To provide a visual indication (such as a plus sign) that the tree can be 
  3747. expanded, add a dummy child object to each of the expandable top-level objects. 
  3748. For example: 
  3749.  
  3750.   cnr->addObject(dummy, topLevelObject);
  3751.  
  3752. To be able to expand the tree with real objects when the user selects it, add a 
  3753. container handler (ICnrHandler) to the container and override the 
  3754. IContainerObject::handleTreeExpanded member function in your container object 
  3755. class. This member function is called by the ICnrHandler whenever an object is 
  3756. expanded.  In this function, delete the dummy object and add the real objects. 
  3757. Once you have expanded the tree, set a flag so you don't expand it again. 
  3758. Return FALSE and let the default action occur if the level is already expanded. 
  3759.  
  3760. The object is really already expanded when handleTreeExpanded is called. 
  3761. However, the technique above works because the container is repainted when you 
  3762. add or remove objects. 
  3763.  
  3764.  
  3765. ΓòÉΓòÉΓòÉ 10.5.13. Why Are All Container Objects Deleted from a Tree View? ΓòÉΓòÉΓòÉ
  3766.  
  3767. Question: 
  3768.  
  3769. When I call deleteSelectedObjects for a tree view of a container, it deletes 
  3770. all objects, not just the selected one. I also noticed that the Select All and 
  3771. Deselect All menu choices for tree views are disabled.  Why? 
  3772.  
  3773. Answer: 
  3774.  
  3775. The behavior you are seeing is a restriction on the PM container control. In a 
  3776. tree view, only one object can be selected at any time and there must be one 
  3777. object selected. That is the reason you can't select or deselect all objects in 
  3778. a tree view. 
  3779.  
  3780. The deleteSelectedObjects function deletes the currently selected object. 
  3781. Because there must always be a selected object in a tree view, the next object 
  3782. in the tree view gets selected. The deleteSelectedObjects function then detects 
  3783. another selected object and deletes it, causing the next object to be selected. 
  3784. The cycle continues until all objects are deleted. 
  3785.  
  3786.  
  3787. ΓòÉΓòÉΓòÉ 10.5.14. Can I Have Two Instances of the Same Object in a Container? ΓòÉΓòÉΓòÉ
  3788.  
  3789. Question: 
  3790.  
  3791. Can I add the same IContainerObject to an IContainerControl twice? 
  3792.  
  3793. Answer: 
  3794.  
  3795. No, you cannot add the same container object twice. PM maintains pointers to 
  3796. place the record in the container relative to other records, and does not allow 
  3797. the same record to be added twice. 
  3798.  
  3799. Instead, use the IContainerObject copy constructor to create another instance 
  3800. of your container object, and add that to the container. 
  3801.  
  3802.  
  3803. ΓòÉΓòÉΓòÉ 10.6. Text and Button Controls ΓòÉΓòÉΓòÉ
  3804.  
  3805. This section discusses ITextControl and classes derived from it. 
  3806.  
  3807.      How Do I Limit the Character Type for an IEntryField? 
  3808.      How Do I Search for Text in an IMultiLineEdit Control? 
  3809.      Can I Append to a File using an IMultiLineEdit Control? 
  3810.      How Does IRadioButton::selectedIndex Work? 
  3811.      Why Can't I Disable Refreshing for an IMultiLineEdit Control? 
  3812.  
  3813.  
  3814. ΓòÉΓòÉΓòÉ 10.6.1. How Do I Limit the Character Type for an IEntryField? ΓòÉΓòÉΓòÉ
  3815.  
  3816. Question: 
  3817.  
  3818. I want to have a numeric-only entry field, a time-format entry field (hh:mm), 
  3819. and a date format entry field (mm/dd/yy). How can I do this? 
  3820.  
  3821. Answer: 
  3822.  
  3823. For a numeric-only entry field, create an IKeyboardHandler. In 
  3824. characterKeyPress, check for the characters 0 through 9. If the value is other 
  3825. than those characters, return TRUE and the non-numeric input will be ignored. 
  3826. Depending on how your user interface works, you may also want to override the 
  3827. entry field's paste and setText functions so they cannot be used to enter 
  3828. non-numeric text. 
  3829.  
  3830. To create a formatted field such as time, date, or currency,  you need an 
  3831. IEditHandler in addition to the IKeyboardHandler.  The IEditHandler is used to 
  3832. format the string correctly each time an acceptable character is received. 
  3833.  
  3834. An uppercase-only entry field is similar to the numeric entry field, except 
  3835. that you want to change the lowercase keyboard events to uppercase ones.  To do 
  3836. this, discard the lowercase keyboard event by calling setResult(true) for the 
  3837. event and returning TRUE from the characterKeyPress function. Then construct a 
  3838. new keyboard event with the appropriate uppercase value and send the new event 
  3839. to the entry field. Your keyboard handler will also be called for this new 
  3840. event, so ensure it ignores valid values; otherwise you may enter a loop. For 
  3841. example: 
  3842.  
  3843.    Boolean MyHandler :: characterKeyPress(IKeyboardEvent& keyEvt)
  3844.     {
  3845.     char cTest = keyEvt.character();
  3846.     if ( islower(cTest) )
  3847.         {
  3848.         cTest &= '\xDF';      //make upper case
  3849.         keyEvt.window()->postEvent(IWindow::character,
  3850.                                    keyEvt.parameter1(),
  3851.                                    cTest);
  3852.         return true;
  3853.         }
  3854.     return false;
  3855.     }
  3856.  
  3857.  
  3858. ΓòÉΓòÉΓòÉ 10.6.2. How Do I Search for Text in an IMultiLineEdit Control? ΓòÉΓòÉΓòÉ
  3859.  
  3860. Question: 
  3861.  
  3862. Is there a find or search function for locating text in an IMultiLineEdit 
  3863. control? 
  3864.  
  3865. Answer: 
  3866.  
  3867. For a forward text search, use the text function to copy the IMultiLineEdit 
  3868. content, beginning at the line where the cursor is, to an IString object.  Then 
  3869. search the resulting IString to find the index where the string is found. Use 
  3870. the index from the IString search to highlight the found string in the 
  3871. IMultiLineEdit control. 
  3872.  
  3873.  
  3874. ΓòÉΓòÉΓòÉ 10.6.3. Can I Append to a File using an IMultiLineEdit Control? ΓòÉΓòÉΓòÉ
  3875.  
  3876. Question: 
  3877.  
  3878. Is there a way to append to an existing file using the exportToFile function or 
  3879. some other function of the IMultiLineEdit control? 
  3880.  
  3881. Answer: 
  3882.  
  3883. The exportToFile function opens the file for writing and will overwrite your 
  3884. existing file. Instead, try the following: 
  3885.  
  3886.    IString  alltext = mle.selectRange().selectedText();
  3887.  
  3888. Then append alltext to the file yourself. 
  3889.  
  3890.  
  3891. ΓòÉΓòÉΓòÉ 10.6.4. How Does IRadioButton::selectedIndex Work? ΓòÉΓòÉΓòÉ
  3892.  
  3893. Question: 
  3894.  
  3895. The IRadioButton::selectedIndex function returns incorrect values when there 
  3896. are controls other than radio buttons in the window. Why? 
  3897.  
  3898. Answer: 
  3899.  
  3900. The index includes all windows that are of the group, not just radio buttons. 
  3901. The group should include only radio buttons to get the expected results. 
  3902.  
  3903.  
  3904. ΓòÉΓòÉΓòÉ 10.6.5. Why Can't I Disable Refreshing for an IMultiLineEdit Control? ΓòÉΓòÉΓòÉ
  3905.  
  3906. Question: 
  3907.  
  3908. I call disableRefresh to disable refreshing for my IMultiLineEdit control. 
  3909. Then when I add lines, the refresh still occurs.  Why? 
  3910.  
  3911. Answer: 
  3912.  
  3913. The User Interface classes use MLM_IMPORT to add text to the multiline edit 
  3914. field (MLE). MLM_IMPORT requires that a null character be the last character 
  3915. added, so the class library adds this extra character to the MLE along with 
  3916. your text. The library then calls MLM_DELETE to delete the extra null 
  3917. character, and MLM_DELETE sends an MLM_ENABLEREFRESH message to the MLE. As a 
  3918. result, refresh is always enabled when you add text. Even if a handler prevents 
  3919. MLM_ENABLEREFRSH from going to the MLE after a delete operation, the screen 
  3920. text is updated. 
  3921.  
  3922. To prevent the MLE from showing updates as they are made, call the IWindow 
  3923. virtual function enableUpdate with the appropriate Boolean value. For example: 
  3924.  
  3925.    mle.IWindow::enableUpdate(false);
  3926.    // add text to mle here
  3927.    mle.IWindow::enableUpdate(true);
  3928.  
  3929.  
  3930. ΓòÉΓòÉΓòÉ 10.7. Listbox and Combobox Controls ΓòÉΓòÉΓòÉ
  3931.  
  3932. This section discusses topics related to the list controls IListBox and 
  3933. IComboBox. 
  3934.  
  3935.      Why Don't I See Events from My IComboBox? 
  3936.      What Is the Limit on the Amount of Data in a Listbox? 
  3937.      Can I Determine the Height of a Listbox Item? 
  3938.  
  3939.  
  3940. ΓòÉΓòÉΓòÉ 10.7.1. Why Don't I See Events from My IComboBox? ΓòÉΓòÉΓòÉ
  3941.  
  3942. Question: 
  3943.  
  3944. I defined a class that inherits from IComboBox and IKeyboardHandler to 
  3945. intercept keystrokes within the entry field of the combo box. It seems the 
  3946. IKeyboardHandler is never invoked even though the constructor calls 
  3947. handleEventsFor(this). What is the problem? 
  3948.  
  3949. Answer: 
  3950.  
  3951. The combo box is causing you problems because it is a composite control, 
  3952. meaning that it is implemented with child controls: a child entry field and 
  3953. listbox.  The keystrokes you don't see are being processed by the child entry 
  3954. field. To process these keystrokes, you need to construct an IEntryField for 
  3955. this child entry field, and attach the keyboard handler to this window.  For 
  3956. example: 
  3957.  
  3958.   IComboBox comboBox( ... );
  3959.   IEntryField childEF( CBID_EDIT, &comboBox ); //CBID_EDIT is in pmwin.h
  3960.   MyKeyboardHandler keyhdr;
  3961.   keyhdr.handleEventsFor( &childEF );
  3962.  
  3963.  
  3964. ΓòÉΓòÉΓòÉ 10.7.2. What Is the Limit on the Amount of Data in a Listbox? ΓòÉΓòÉΓòÉ
  3965.  
  3966. Question: 
  3967.  
  3968. I have a listbox that could contain a large number of elements. Is there a 
  3969. limit to how many elements I can add? 
  3970.  
  3971. Answer: 
  3972.  
  3973. In OS/2 2.x, there is a limit of 64K of heap space per frame window for all 
  3974. controls. The list box data is allocated out of this space. The limitation is 
  3975. really on the amount of data, not the number of elements. 
  3976.  
  3977. In OS/2 Warp, the limit is 32K entries. 
  3978.  
  3979. One possible solution is to use a container in details view instead of the 
  3980. listbox. 
  3981.  
  3982.  
  3983. ΓòÉΓòÉΓòÉ 10.7.3. Can I Determine the Height of a Listbox Item? ΓòÉΓòÉΓòÉ
  3984.  
  3985. Question: 
  3986.  
  3987. Is there a way to determine the cell height or the number of displayable items 
  3988. for a given listbox? 
  3989.  
  3990. Answer: 
  3991.  
  3992. No. PM does not make available either the height of a row or the number that 
  3993. are currently visible in a listbox. 
  3994.  
  3995.  
  3996. ΓòÉΓòÉΓòÉ 10.8. Notebook Control ΓòÉΓòÉΓòÉ
  3997.  
  3998. This section discusses topics related to the INoteBook class. 
  3999.  
  4000.      How Do I Change the Appearance of INotebook Tabs? 
  4001.      Why Isn't My IPageHandler::drawTab Function Called? 
  4002.      How Can I Display Page Numbers in a Notebook? 
  4003.      How Can I Get the Correct Size for a Notebook? 
  4004.  
  4005.  
  4006. ΓòÉΓòÉΓòÉ 10.8.1. How Do I Change the Appearance of INotebook Tabs? ΓòÉΓòÉΓòÉ
  4007.  
  4008. Question: 
  4009.  
  4010. What can I do to change the appearance of INotebook tabs? 
  4011.  
  4012. Answer: 
  4013.  
  4014. To change the size of the notebook tabs, use INotebook::setMajorTabSize and 
  4015. INotebook::setMinorTabSize. Note, however, that all tabs in a notebook must be 
  4016. the same size. You can control the location of the tabs with the 
  4017. INotebook::setOrientation function and through INotebook styles. To change the 
  4018. color of all the tabs in a notebook, use INotebook::setColor. 
  4019.  
  4020. If you want to change the color of some but not all tabs (for example, as an 
  4021. indicator that a page has been changed), you must draw the tabs yourself using 
  4022. IPageHandler::drawTab. You also have to draw the tabs yourself if you want to 
  4023. have multiline tab text. 
  4024.  
  4025.  
  4026. ΓòÉΓòÉΓòÉ 10.8.2. Why Isn't My IPageHandler::drawTab Function Called? ΓòÉΓòÉΓòÉ
  4027.  
  4028. Question: 
  4029.  
  4030. The drawTab function for my IPageHandler is not called.  Why? 
  4031.  
  4032. Answer: 
  4033.  
  4034. If you call either setTabText or setTabBitmap for a page, the PM notebook 
  4035. control draws the tab and does not call your drawTab function. This behavior is 
  4036. determined by PM. 
  4037.  
  4038. To ensure your drawTab function is called, do not call either setTabText or 
  4039. setTabBitmap for the page. 
  4040.  
  4041.  
  4042. ΓòÉΓòÉΓòÉ 10.8.3. How Can I Display Page Numbers in a Notebook? ΓòÉΓòÉΓòÉ
  4043.  
  4044. Question: 
  4045.  
  4046. How can I display page numbers on my notebook pages, such as Page 1 of 3, Page 
  4047. 2 of 3, and so on? 
  4048.  
  4049. Answer: 
  4050.  
  4051. You can use INotebook::setStatusText to implement page numbers as status text 
  4052. on the notebook page.  If you want the page numbers aligned to one side, use 
  4053. INotebook::setStatusTextAlignment as well. 
  4054.  
  4055. You will need to specify the statusTextOn attribute when you construct the 
  4056. IPageSettings object that you use to insert pages. 
  4057.  
  4058.  
  4059. ΓòÉΓòÉΓòÉ 10.8.4. How Can I Get the Correct Size for a Notebook? ΓòÉΓòÉΓòÉ
  4060.  
  4061. Question: 
  4062.  
  4063. I have a notebook that contains a multicell canvas with an expandable margin. 
  4064. When I request the minimum notebook size after the pages are loaded, but before 
  4065. the canvas is filled, I get unusual values from INotebook::pageSize and 
  4066. INotebook::notebookSize.. A sizeTo of the frame window creates a 1x.75 inch 
  4067. window. What am I doing wrong? 
  4068.  
  4069. Answer: 
  4070.  
  4071. When you call INotebook::pageSize, the size of the notebook is still (0, 0), so 
  4072. the size needed by a page window to fit into a notebook would have to be even 
  4073. smaller. When you call INotebook::notebookSize, the page window is still sized 
  4074. to (0, 0), and that is the reason your notebook has such a small size. 
  4075.  
  4076. After adding page windows to your notebook, you can size the frame based on the 
  4077. size of the notebook client window: 
  4078.  
  4079.    frame.moveSizeToClient( IRectangle( IFrameWindow::nextShellRect()
  4080.                                                        .bottomLeft(),
  4081.                                        notebook.minimumSize() );
  4082.  
  4083.  
  4084. ΓòÉΓòÉΓòÉ 10.9. Other Controls ΓòÉΓòÉΓòÉ
  4085.  
  4086. This section discusses topics related to the IMessageBox, ISpinButton, and 
  4087. ISlider classes. 
  4088.  
  4089.      Why Don't I See Events from My ISpinButton? 
  4090.      Why Does My IProgressIndicator Not Display Correctly? 
  4091.      Can I Use IMessageBox without a Main Application Window? 
  4092.      What Is an IMessageBox Modal To? 
  4093.  
  4094.  
  4095. ΓòÉΓòÉΓòÉ 10.9.1. Why Don't I See Events from My ISpinButton? ΓòÉΓòÉΓòÉ
  4096.  
  4097. Question: 
  4098.  
  4099. I have a class that inherits from ISpinButton and IKeyboardHandler, and 
  4100. overrides the key function to intercept characters other than 0-9 and '.'. But 
  4101. when I enter a character, it appears in the entry field part of the control 
  4102. before the key function runs.  Also, the key event that I receive is not a 
  4103. character (isCharacter returns FALSE). Why does this happen? 
  4104.  
  4105. Answer: 
  4106.  
  4107. The spin button is a composite control with an entry-field child window. 
  4108.  
  4109. You need to attach the keyboard handler to the spin button's entry-field child 
  4110. window.  The spin button itself receives only the keystrokes that the entry 
  4111. field doesn't process (like noncharacter keys and key releases). 
  4112.  
  4113. To attach the keyboard handler to the entry field, you must first construct an 
  4114. IEntryField for the entry field. 
  4115.  
  4116. In OS/2 2.0 and above, you can take advantage of the fact that the spin button 
  4117. creates its child entry field with the same window ID that it uses, for 
  4118. example: 
  4119.  
  4120.   unsigned long ID = spinButton->id();
  4121.   IEntryField* spinEntry = new IEntryField( id, spinButton );
  4122.  
  4123.  
  4124. ΓòÉΓòÉΓòÉ 10.9.2. Why Does My IProgressIndicator Not Display Correctly? ΓòÉΓòÉΓòÉ
  4125.  
  4126. Question: 
  4127.  
  4128. When I add an IProgressIndicator to a multicell canvas and then size the window 
  4129. to its minimum size, the tick text associated with the progress indicator scale 
  4130. is clipped at both ends of the scale. Why? 
  4131.  
  4132. Answer: 
  4133.  
  4134. The calcMinimumSize for IProgressIndicator (and ISlider) returns (30,100) or 
  4135. (100,30), depending on the shaft orientation. Depending on your application and 
  4136. the styles you are using, you may need to call setMinimumSize to establish a 
  4137. different size for the control. 
  4138.  
  4139.  
  4140. ΓòÉΓòÉΓòÉ 10.9.3. Can I Use IMessageBox without a Main Application Window? ΓòÉΓòÉΓòÉ
  4141.  
  4142. Question: 
  4143.  
  4144. I need to display a message box for my application before my main window is 
  4145. created.  How can I do that? 
  4146.  
  4147. Answer: 
  4148.  
  4149. You can use IMessageBox and pass 0 for the window owner. Note, however, that 
  4150. without a window owner, you cannot provide help for the message box. 
  4151.  
  4152.  
  4153. ΓòÉΓòÉΓòÉ 10.9.4. What Is an IMessageBox Modal To? ΓòÉΓòÉΓòÉ
  4154.  
  4155. Question: 
  4156.  
  4157. I have an application with two frame windows. When I create an IMessageBox for 
  4158. frame window 1 with the applicationModal style, the message box is not modal 
  4159. with respect to frame window 2.  Why? 
  4160.  
  4161. Answer: 
  4162.  
  4163. A message box is only application-modal to its owner. In your example, the 
  4164. message box is modal relative to frame window 1, and your other frame windows 
  4165. can receive input focus. 
  4166.  
  4167.  
  4168. ΓòÉΓòÉΓòÉ 10.10. Menus ΓòÉΓòÉΓòÉ
  4169.  
  4170. This section discusses menus, including pop-up or context menus. 
  4171.  
  4172.      Why Don't the IMenuItem Functions Affect My Menu? 
  4173.      Where Should I Call setAutoDeleteObject for Pop-up Menus? 
  4174.      How Can I Change the Font of a Pop-up Menu? 
  4175.  
  4176.  
  4177. ΓòÉΓòÉΓòÉ 10.10.1. Why Don't the IMenuItem Functions Affect My Menu? ΓòÉΓòÉΓòÉ
  4178.  
  4179. Question: 
  4180.  
  4181. I can use IMenu::enableItem and IMenu::disableItem to enable and disable my 
  4182. menu items, but IMenuItem::setDisabled and IMenuItem::setSelectable do not 
  4183. work. Why? 
  4184.  
  4185. Answer: 
  4186.  
  4187. The key point to remember about the IMenuItem functions is that they do not 
  4188. affect the menu unless the IMenu add or set functions are called with the 
  4189. instance of the menu item. 
  4190.  
  4191. To set the styles or attributes of an existing menu item, you must use the 
  4192. IMenu functions such as enableItem and checkItem. 
  4193.  
  4194. You can also manipulate an IMenuItem object that represents a menu item within 
  4195. the existing menu, and then call IMenu::setItem to replace the styles or 
  4196. attributes of that item with those you specify for the IMenuItem object. 
  4197.  
  4198.  
  4199. ΓòÉΓòÉΓòÉ 10.10.2. Where Should I Call setAutoDeleteObject for Pop-up Menus? ΓòÉΓòÉΓòÉ
  4200.  
  4201. Question: 
  4202.  
  4203. I create a pop-up menu with makePopUpMenu. To delete it correctly, can I call 
  4204. setAutoDeleteObject from makePopUpMenu, or do I have to override menuEnded and 
  4205. call setAutoDeleteObject from there? 
  4206.  
  4207. Answer: 
  4208.  
  4209. If you want the library to delete your pop-up menu, call setAutoDeleteObject in 
  4210. makePopUpMenu. Note that to do this, you must have created the pop-up menu with 
  4211. operator new. 
  4212.  
  4213.  
  4214. ΓòÉΓòÉΓòÉ 10.10.3. How Can I Change the Font of a Pop-up Menu? ΓòÉΓòÉΓòÉ
  4215.  
  4216. Question: 
  4217.  
  4218. When I change the font in a container, the pop-up menus for objects in the 
  4219. container inherit the font change. How can I change the fonts of the pop-up 
  4220. menus? 
  4221.  
  4222. Answer: 
  4223.  
  4224. Fonts are inherited from the owner chain. If you don't want the pop-up menu to 
  4225. inherit from the container, change the owner of the pop-up menu from the 
  4226. container to the frame window. 
  4227.  
  4228.  
  4229. ΓòÉΓòÉΓòÉ 10.11. Creating Help with IHelpWindow ΓòÉΓòÉΓòÉ
  4230.  
  4231. This section discusses providing application help using IHelpWindow and other 
  4232. classes. 
  4233.  
  4234.      How Do I Create Help for Child or Secondary Windows? 
  4235.      How Does IMessageBox Help Work? 
  4236.      How Do I Customize Help for IFileDialog? 
  4237.  
  4238.  
  4239. ΓòÉΓòÉΓòÉ 10.11.1. How Do I Create Help for Child or Secondary Windows? ΓòÉΓòÉΓòÉ
  4240.  
  4241. Question: 
  4242.  
  4243. I have two help subtables, one for my main window and one for a dialog. An 
  4244. IHelpWindow is associated with the main window and an IHelpHandler is attached 
  4245. to the main window. The help works for the main window, but not for the dialog. 
  4246. How do I fix this? 
  4247.  
  4248. Answer: 
  4249.  
  4250. If your dialog is a secondary window (its parent window is the desktop), then 
  4251. Help Manager should be able to locate the correct help subtable for its 
  4252. contextual and/or general help. However, you should use 
  4253. IHelpWindow::associateWindow to associate the IHelpWindow used by the main 
  4254. window with your secondary dialog. Then when you dismiss the help window, focus 
  4255. returns to the dialog instead of the primary window, and when you dismiss the 
  4256. dialog, the help window is automatically dismissed. Once you add the 
  4257. associateWindow, you will also need to add the same help handler to the dialog 
  4258. because all help notification messages will be sent to the associated window. 
  4259.  
  4260. If your dialog is a child window, use the IHelpWindow::setActiveWindow function 
  4261. to identify the child frame window as the active help window. Without this 
  4262. call, Help Manager will use the wrong frame window when searching the help 
  4263. tables. 
  4264.  
  4265.  
  4266. ΓòÉΓòÉΓòÉ 10.11.2. How Does IMessageBox Help Work? ΓòÉΓòÉΓòÉ
  4267.  
  4268. Question: 
  4269.  
  4270. I am trying to display a message box with a help button on it. The IMessageBox 
  4271. documentation says, if you have helpID, the help button will display, but it 
  4272. does not say anything about the help file to load the help from.  What does 
  4273. IMessageBox do? 
  4274.  
  4275. Answer: 
  4276.  
  4277. IMessageBox uses the same IHelpWindow that its owner window uses and 
  4278. consequently the same help library file. 
  4279.  
  4280.  
  4281. ΓòÉΓòÉΓòÉ 10.12. Application and Resources ΓòÉΓòÉΓòÉ
  4282.  
  4283. This section discusses general application topics and how to use resources and 
  4284. and resource libraries. 
  4285.  
  4286.      How Should I Use IResourceLock and ISemaphoreHandle? 
  4287.      What Does IDynamicLinkLibrary Do If the DLL Is Not Found? 
  4288.      How Do I Get the Anchor Block (HAB) of a Thread? 
  4289.      Which Classes Can I Use in a Non-GUI Application? 
  4290.      Can I Dynamically Load Resources from a DLL? 
  4291.      How Can I Specify a New-Line Character in a Resource File? 
  4292.      How Does the Library Choose between Multiple Icons? 
  4293.      Can I Dynamically Load Bitmaps and Icons That Aren't Resources? 
  4294.      How Do I Load a String Resource into an IString? 
  4295.  
  4296.  
  4297. ΓòÉΓòÉΓòÉ 10.12.1. How Should I Use IResourceLock and ISemaphoreHandle? ΓòÉΓòÉΓòÉ
  4298.  
  4299. Question: 
  4300.  
  4301. How should I use ISemaphoreHandle and IResourceLock? 
  4302.  
  4303. Answer: 
  4304.  
  4305. The easiest way to lock resources is to use the IResourceLock class. Create a 
  4306. static instance of IPrivateResource or ISharedResource. When you need to lock 
  4307. the resource, create a local instance of IResourceLock that exists during the 
  4308. time you need the resource to be locked.  For example: 
  4309.  
  4310.    static IPrivateResource collectionResource;
  4311.    // ...
  4312.  
  4313.    {
  4314.       // set lock
  4315.       IResourceLock reslock(collectionResource);
  4316.  
  4317.       // ... do serialized tasks here
  4318.  
  4319.    }  // lock freed on scope exit and destruction of reslock object
  4320.  
  4321. In OS/2, IResourceLock uses mutex semaphores to implement the locking. 
  4322.  
  4323. The User Interface class library does not support direct user of OS/2 event 
  4324. semaphores, but you can use ISemaphoreHandle as an alias for the PM HEV and 
  4325. HMTX types on the OS/2 API calls. 
  4326.  
  4327.  
  4328. ΓòÉΓòÉΓòÉ 10.12.2. What Does IDynamicLinkLibrary Do If the DLL Is Not Found? ΓòÉΓòÉΓòÉ
  4329.  
  4330. Question: 
  4331.  
  4332. What does the IDynamicLinkLibrary constructor do if the DLL specified in the 
  4333. input character string cannot be found? 
  4334.  
  4335. Answer: 
  4336.  
  4337. The IDynamicLinkLibrary class will throw an IAccessError exception if it cannot 
  4338. find and load the DLL specified. 
  4339.  
  4340.  
  4341. ΓòÉΓòÉΓòÉ 10.12.3. How Do I Get the Anchor Block (HAB) of a Thread? ΓòÉΓòÉΓòÉ
  4342.  
  4343. Question: 
  4344.  
  4345. How can I determine the anchor block handle (HAB) of the current thread? 
  4346.  
  4347. Answer: 
  4348.  
  4349. You can determine the anchor block handle with the following function call: 
  4350.  
  4351.   IAnchorBlockHandle hab = IThread::current().anchorBlock();
  4352.  
  4353.  
  4354. ΓòÉΓòÉΓòÉ 10.12.4. Which Classes Can I Use in a Non-GUI Application? ΓòÉΓòÉΓòÉ
  4355.  
  4356. Question: 
  4357.  
  4358. Are there any User Interface classes that I can use in a non-GUI application? 
  4359.  
  4360. Answer: 
  4361.  
  4362. For applications that do not have a graphical interface, you can use the 
  4363. following classes from the User Interface class library: 
  4364.  
  4365.      IBase 
  4366.      IVBase 
  4367.      ITrace 
  4368.      IErrorInfo and derived classes (except IGUIErrorInfo and IXLibErrorInfo) 
  4369.      IString, I0String and related classes 
  4370.      IDate 
  4371.      ITime 
  4372.      IBitFlag 
  4373.      IPoint and derived classes 
  4374.      IRectangle 
  4375.      IResource and IResourceLock 
  4376.      IProcedureAddress 
  4377.      IDynamicLinkLibrary 
  4378.      IApplication and ICurrentApplication (non-GUI functions only) 
  4379.      IThread and ICurrentThread (non-GUI functions only) 
  4380.  
  4381.  The other libraries in IBM Open Class (I/O Stream, Complex, Collection, 
  4382.  Database Access, and Data Type and Exception) are also available to all C++ 
  4383.  applications. 
  4384.  
  4385.  
  4386. ΓòÉΓòÉΓòÉ 10.12.5. Can I Dynamically Load Resources from a DLL? ΓòÉΓòÉΓòÉ
  4387.  
  4388. Question: 
  4389.  
  4390. Is there a way I can load resources (like icons) and dialogs dynamically from a 
  4391. DLL without having to use setUserResourceLibrary and setResourceLibary? 
  4392.  
  4393. Answer: 
  4394.  
  4395. Most of the functions in the library that use resource IDs accept them in the 
  4396. form of an IResourceId.  If you provide an unsigned long value for this 
  4397. argument, the resource is loaded from the default resource library set by 
  4398. ICurrentApplication::setUserResourceLibrary. However, you can explicitly create 
  4399. the IResourceId to refer to a specific resource library.  For example, 
  4400.  
  4401.    textctl.setText( IResourceId( 1000, IDynamicLinkLibrary("mydll") ) );
  4402.  
  4403. would set the text to the value of resource ID 1000 from mydll.dll. 
  4404.  
  4405.  
  4406. ΓòÉΓòÉΓòÉ 10.12.6. How Can I Specify a New-Line Character in a Resource File? ΓòÉΓòÉΓòÉ
  4407.  
  4408. Question: 
  4409.  
  4410. When I call myResLib.loadString for my message, it doesn't remove the new-line 
  4411. (\n) characters from the message string in my string table. Should I specify 
  4412. new-line characters a different way? 
  4413.  
  4414. Answer: 
  4415.  
  4416. This is the usual behavior of the PM WinLoadString function, which is used to 
  4417. load the string. To get around it, use \x0d instead of \n in the string in the 
  4418. resource file. 
  4419.  
  4420.  
  4421. ΓòÉΓòÉΓòÉ 10.12.7. How Does the Library Choose between Multiple Icons? ΓòÉΓòÉΓòÉ
  4422.  
  4423. Question: 
  4424.  
  4425. When there is more than one version or size of a bitmap or icon, what rules are 
  4426. used to choose which one is displayed? 
  4427.  
  4428. Answer: 
  4429.  
  4430. PM chooses the icon or bitmap whose format most closely matches the target 
  4431. display device. When you design your icons and bitmaps, you should provide and 
  4432. test formats for each anticipated target display device. 
  4433.  
  4434.  
  4435. ΓòÉΓòÉΓòÉ 10.12.8. Can I Dynamically Load Bitmaps and Icons That Aren't Resources? ΓòÉΓòÉΓòÉ
  4436.  
  4437. Question: 
  4438.  
  4439. Can I dynamically load and display a bitmap or icon file dynamically without 
  4440. binding it as a resource? 
  4441.  
  4442. Answer: 
  4443.  
  4444. You can use the PM function WinLoadFileIcon to load icons. In Version 3.0 of 
  4445. the class library, you can also use the IGBitmap class to dynamically load 
  4446. bitmaps and icons, as well as other image file types such as .GIF. 
  4447.  
  4448. The DMSAMP.CPP file in the DRAG2 sample (shipped with VisualAge C++) contains 
  4449. code that loads a bitmap from an icon. 
  4450.  
  4451.  
  4452. ΓòÉΓòÉΓòÉ 10.12.9. How Do I Load a String Resource into an IString? ΓòÉΓòÉΓòÉ
  4453.  
  4454. Question: 
  4455.  
  4456. How do I load a string resource into an IString object? 
  4457.  
  4458. Answer: 
  4459.  
  4460. Use the IApplication::current().userResourceLibrary().loadString function and 
  4461. pass it the ID of the string resource. For example: 
  4462.  
  4463.    IString string;
  4464.    string = IApplication::current().userResourceLibrary().loadString(id);
  4465.  
  4466.  
  4467. ΓòÉΓòÉΓòÉ 10.13. Threads ΓòÉΓòÉΓòÉ
  4468.  
  4469. This section discusses how to use the IThread class and related topics. 
  4470.  
  4471.      Is There an Example of Using IThread and IThreadFn? 
  4472.      How Do I Start A Thread? 
  4473.      When Is a PM Message Queue Allocated for a Thread? 
  4474.      How Do I Open a Window on a Secondary Thread? 
  4475.      Can I Create Child Windows in Another Thread? 
  4476.  
  4477.  
  4478. ΓòÉΓòÉΓòÉ 10.13.1. Is There an Example of Using IThread and IThreadFn? ΓòÉΓòÉΓòÉ
  4479.  
  4480. Question: 
  4481.  
  4482. Is there an example that shows how to use IThread and IThreadFn? 
  4483.  
  4484. Answer: 
  4485.  
  4486. The MLE sample program shipped with VisualAge C++ shows a simple example using 
  4487. of IThread and IThreadFn. In addition, OS/2 C++ Class Library: Power GUI 
  4488. Programming with C Set ++ contains extensive discussion and examples for 
  4489. IThread and related functions. For more information about this book, see What 
  4490. Documentation Exists for the User Interface Classes?. 
  4491.  
  4492.  
  4493. ΓòÉΓòÉΓòÉ 10.13.2. How Do I Start A Thread? ΓòÉΓòÉΓòÉ
  4494.  
  4495. Question: 
  4496.  
  4497. I want to start an asynchronous thread using a function and an unsigned long 
  4498. argument.  How do I start it? 
  4499.  
  4500. Answer: 
  4501.  
  4502. There are several ways to start a thread, depending on what you want to use it 
  4503. for.  First decide what code you want to run in the separate thread. 
  4504.  
  4505.    1. If the code matches any of the following, you can use the IThread::start 
  4506.       function directly: 
  4507.  
  4508.         a. A given member function of a given object (with return type void and 
  4509.            no arguments): 
  4510.  
  4511.                          // MyClass has member function void foo()
  4512.                          IThread thread;
  4513.                          thread.start( new IThreadMemberFn< MyClass >( *this, foo ) )
  4514.  
  4515.         b. A _System function accepting an unsigned long argument (that you 
  4516.            would start with DosCreateThread in C): 
  4517.  
  4518.                          // non-member function declared as
  4519.                          void _System foo( unsigned long arg);
  4520.                          IThread thread;
  4521.                          thread.start( foo );
  4522.  
  4523.         c. An _Optlink function accepting a void* argument (that you would 
  4524.            start with _beginthread in C): 
  4525.  
  4526.                          // non-member function declared as
  4527.                          void _Optlink foo( void* arg);
  4528.                          IThread thread;
  4529.                          thread.start( foo );
  4530.  
  4531.    2. If the code you want to run does not match the above descriptions, you 
  4532.       must write a "wrapper" using one of the following two techniques: 
  4533.  
  4534.         a. Derive from IThreadFn and implement run to call the desired member 
  4535.            function of your object. This may be difficult because you typically 
  4536.            need to know what additional arguments to pass, and this technique 
  4537.            provides no way to address that requirement. However, it can be more 
  4538.            syntactically elegant: aThread.start(this) instead of aThread.start( 
  4539.            new IThreadMemberFn<T>(*this, T::foobar) ). Also, the lifetime of 
  4540.            this must transcend the lifetime of the thread. 
  4541.         b. Derive a new class from IThreadFn.  Add data members for arguments 
  4542.            to the function you want to run, including the object that a member 
  4543.            function might be invoked on.  Add a constructor that accepts 
  4544.            references to the arguments as its arguments.  Finally, implement 
  4545.            run to dispatch the function you want with the provided arguments. 
  4546.            The MLE sample program shipped with VisualAge C++ provides an 
  4547.            example of this technique. You could alternatively implement the 
  4548.            function you want to run within MyThreadFn::run. 
  4549.  
  4550.       The IThreadFn object is reference-counted so that it can be automatically 
  4551.       deleted when the thread terminates. As a result, if you use IThreadFn or 
  4552.       a derived class, you must allocate the IThreadFn using the new operator 
  4553.       and you must not delete it. 
  4554.  
  4555.  
  4556. ΓòÉΓòÉΓòÉ 10.13.3. When Is a PM Message Queue Allocated for a Thread? ΓòÉΓòÉΓòÉ
  4557.  
  4558. Question: 
  4559.  
  4560. When I create a thread with IThread, does PM automatically allocate a message 
  4561. queue for it?  If not, when and how does a message queue get allocated? 
  4562.  
  4563. Answer: 
  4564.  
  4565. When you start your thread, if you set the second argument (autoInitPM) to 
  4566. TRUE, it automatically calls initializePM, which in turn calls WinInitialize 
  4567. and WinCreateMsgQueue to create a message queue. 
  4568.  
  4569. If you set autoInitPM to FALSE, the thread initializes PM when it first creates 
  4570. a frame window (or certain other types of window such as IFileDialog).  It does 
  4571. not create a message queue. 
  4572.  
  4573. If your thread will be sending PM messages, it requires a message queue. 
  4574. Because many User Interface class library functions interact with controls by 
  4575. sending messages, it is recommended you create a message queue for your thread 
  4576. if it deals with any IWindow objects. 
  4577.  
  4578.  
  4579. ΓòÉΓòÉΓòÉ 10.13.4. How Do I Open a Window on a Secondary Thread? ΓòÉΓòÉΓòÉ
  4580.  
  4581. Question: 
  4582.  
  4583. My application starts a secondary thread that instantiates a window (inherited 
  4584. from IFrameWindow) to run in that thread. However, after the window is 
  4585. constructed, the function in the second thread ends and therefore ends the 
  4586. thread.  The window only appears momentarily.  How can I prevent the thread 
  4587. from ending before the user closes the window for that thread? 
  4588.  
  4589. Answer: 
  4590.  
  4591. If you open a window on a thread, you must process the PM window messages for 
  4592. that thread's message queue.  The message processing loop keeps your thread 
  4593. running while simultaneously handling the messages sent to your window. 
  4594.  
  4595. You can call IThread::current().processMsgs to enter an event loop for the 
  4596. thread.  This is the same as calling IApplication::current().run in your main 
  4597. thread. The event loop will normally be terminated when the last primary window 
  4598. on the thread is closed. 
  4599.  
  4600. Another alternative is to show the frame window modally by using showModally 
  4601. instead of show. For a frame without an owner, showModally is equivalent to 
  4602. showing the frame using show followed by the message processing loop. 
  4603.  
  4604.  
  4605. ΓòÉΓòÉΓòÉ 10.13.5. Can I Create Child Windows in Another Thread? ΓòÉΓòÉΓòÉ
  4606.  
  4607. Question: 
  4608.  
  4609. Can I create the child windows of the frame window in another thread? 
  4610.  
  4611. Answer: 
  4612.  
  4613. No. PM window parentage and ownership cannot cross thread boundaries. 
  4614.  
  4615.  
  4616. ΓòÉΓòÉΓòÉ 10.14. Fonts and Colors ΓòÉΓòÉΓòÉ
  4617.  
  4618. This section discusses the usage of the IFont and IColor classes. 
  4619.  
  4620.      How Can I Detect Font or Color Changes in a Window? 
  4621.      How Can I Save Font Information? 
  4622.      Why Do I Get an Incorrect Font? 
  4623.  
  4624.  
  4625. ΓòÉΓòÉΓòÉ 10.14.1. How Can I Detect Font or Color Changes in a Window? ΓòÉΓòÉΓòÉ
  4626.  
  4627. Question: 
  4628.  
  4629. Is there a way to determine when the font or color of a window has changed as 
  4630. the result of a drag/drop operation? 
  4631.  
  4632. Answer: 
  4633.  
  4634. When the font or color changes, the IWindow dispatcher calls the virtual 
  4635. function IWindow::setLayoutDistorted. The first argument to this function is 
  4636. the set of flags that are being turned on (values defined in the 
  4637. IWindow::Layout enumeration). The second argument is the set of flags being 
  4638. turned off. This function is the basic notification vehicle for telling a 
  4639. canvas that the look of one of its child windows has changed. 
  4640.  
  4641. To detect font changes, you can provide your own implementation of 
  4642. setLayoutDistorted in a derived class.  Check the first argument, which is 
  4643. IWindow::fontChanged for a font change and IWindow::colorChanged for a color 
  4644. change, and then call the base class version of setLayoutDistorted, passing the 
  4645. original arguments. 
  4646.  
  4647.  
  4648. ΓòÉΓòÉΓòÉ 10.14.2. How Can I Save Font Information? ΓòÉΓòÉΓòÉ
  4649.  
  4650. Question: 
  4651.  
  4652. Is there a way to save the current font and font attributes from an IFont 
  4653. object into a .INI file, so that it can be recalled the next time the program 
  4654. is started? 
  4655.  
  4656. Answer: 
  4657.  
  4658. The font face name and size should uniquely identify the font you are using. 
  4659. You may also want to save the emphasis information so that the font will look 
  4660. identical in the future. The HELLO6 sample program shipped with VisualAge C++ 
  4661. gives an example of how to save and restore the font facename and size to a 
  4662. profile. Look at the readProfile and updateProfile member functions in that 
  4663. sample. 
  4664.  
  4665.  
  4666. ΓòÉΓòÉΓòÉ 10.14.3. Why Do I Get an Incorrect Font? ΓòÉΓòÉΓòÉ
  4667.  
  4668. Question: 
  4669.  
  4670. I want to use Helvetica bold font with point size 8. However, I always get the 
  4671. Courier font instead.  Why? 
  4672.  
  4673. Answer: 
  4674.  
  4675. Make sure you specify the font name as the first parameter of the IFont 
  4676. constructor, and that it is in the correct case. Because font names in OS/2 are 
  4677. case-sensitive, "Helvetica" uses the correct Helvetica font, but "helvetica" 
  4678. does not. If the font cannot be found, the class library defaults to Courier. 
  4679.  
  4680.  
  4681. ΓòÉΓòÉΓòÉ 10.15. Font and File Dialogs ΓòÉΓòÉΓòÉ
  4682.  
  4683. This section discusses the classes IFontDialog and IFileDialog as well as the 
  4684. related classes. 
  4685.  
  4686.      How Do I Customize Help for IFileDialog? 
  4687.      Why Doesn't IFileDialog Find the Files? 
  4688.      Can I Customize the File and Font Dialogs? 
  4689.  
  4690.  
  4691. ΓòÉΓòÉΓòÉ 10.15.1. How Do I Customize Help for IFileDialog? ΓòÉΓòÉΓòÉ
  4692.  
  4693. Question: 
  4694.  
  4695. I have set the helpButton style on a IFileDialog. How do I show my help for the 
  4696. button?  Do I have to trap the WM_HELP message?  What is the ID of the Help 
  4697. button? 
  4698.  
  4699. Answer: 
  4700.  
  4701. The simplest approach for contextual help support in the file dialog is to 
  4702. create a HELPTABLE and HELPSUBTABLE in a resource file.  Use the IDs that are 
  4703. defined by PM for the various fields in the subtable to identify the contextual 
  4704. help panels. 
  4705.  
  4706. The control IDs for the file dialog are in <pmstddlg.h> after the following: 
  4707.  
  4708.     /*-----------------------------------------
  4709.     /* File Dialog - dialog and control IDs
  4710.     /*-----------------------------------------
  4711.     #define   DID_FILE_DIALOG             256
  4712.  
  4713. You can use a similar approach for IFontDialog help. The font dialog control 
  4714. IDs are also in <pmstddlg.h> after the following: 
  4715.  
  4716.    /**********************************************************************/
  4717.    /* font dialog and control id's                                       */
  4718.    /**********************************************************************/
  4719.    #define DID_FONT_DIALOG          300
  4720.  
  4721. You can also read about the IDs in the Presentation Manager Guide and 
  4722. Reference. 
  4723.  
  4724.  
  4725. ΓòÉΓòÉΓòÉ 10.15.2. Why Doesn't IFileDialog Find the Files? ΓòÉΓòÉΓòÉ
  4726.  
  4727. Question: 
  4728.  
  4729. I created an instance of IFileDialog and used setInitialFileType to set the 
  4730. type to "*.CPP".  There are files with that extension in the directory, but the 
  4731. Files list box never contains any files.  Why? 
  4732.  
  4733. Answer: 
  4734.  
  4735. The setInitialFileType specifies an extended attribute type, not the file 
  4736. extension.  Allow the EA type to default to all file types, and use 
  4737. setFileName("*.CPP") instead of setInitialFileType. 
  4738.  
  4739.  
  4740. ΓòÉΓòÉΓòÉ 10.15.3. Can I Customize the File and Font Dialogs? ΓòÉΓòÉΓòÉ
  4741.  
  4742. Question: 
  4743.  
  4744. I want to alter the field prompts on the file dialog, but IFileDialog only 
  4745. supports changes to the title.  Can I change the prompts? 
  4746.  
  4747. Answer: 
  4748.  
  4749. You can specify your own dialog template using 
  4750. IFileDialog::Settings::setDialogTemplate or 
  4751. IFontDialog::Settings::setDialogTemplate. The &pmref. describes how to define 
  4752. this dialog template. You do have to use specific constants for control IDs 
  4753. when defining your dialog template.  These are also described in the &pmref.. 
  4754.  
  4755.  
  4756. ΓòÉΓòÉΓòÉ 10.16. Direct Manipulation (Drag and Drop) ΓòÉΓòÉΓòÉ
  4757.  
  4758. This section discusses the IDM classes and related problems with drag and drop 
  4759. operations. 
  4760.  
  4761.      How Do I Control Drag and Drop between Containers? 
  4762.      Can I Add Drag and Drop Support to an IComboBox? 
  4763.  
  4764.  
  4765. ΓòÉΓòÉΓòÉ 10.16.1. How Do I Control Drag and Drop between Containers? ΓòÉΓòÉΓòÉ
  4766.  
  4767. Question: 
  4768.  
  4769. I have two containers with different objects. How can I control what objects 
  4770. can be dragged from one container to the other, or from one object to another? 
  4771. What classes or functions should I use? 
  4772.  
  4773. Answer: 
  4774.  
  4775. By default, you can move any container object to any container window in your 
  4776. application. 
  4777.  
  4778. To restrict or enhance this level of function, you need to write your own 
  4779. IDMCnrItem-derived class.  In your constructors, set the attributes of your 
  4780. derived item class (type, operations, and rendering mechanisms and formats). 
  4781. You must also create a corresponding IDMItemProvider that works with your item 
  4782. class.  In most cases, you can use the IDMItemProviderFor class template to 
  4783. generate that class. 
  4784.  
  4785. The basic framework moves the container objects to the container controls for 
  4786. you. If the action of dragging and/or dropping requires some 
  4787. application-specific action to take place, you must also override the 
  4788. targetDrop function. 
  4789.  
  4790. You may find the Drag and Drop samples (DRAG1 through DRAG4) useful in 
  4791. demonstrating how to enable this support. 
  4792.  
  4793.  
  4794. ΓòÉΓòÉΓòÉ 10.16.2. Can I Add Drag and Drop Support to an IComboBox? ΓòÉΓòÉΓòÉ
  4795.  
  4796. Question: 
  4797.  
  4798. I tried to add drag and drop support for an IComboBox control, but it didn't 
  4799. work.  Are there restrictions on direct manipulation of combo boxes? 
  4800.  
  4801. Answer: 
  4802.  
  4803. IComboBox is a composite control. You have to use PM to enumerate the children 
  4804. of the combo box for its contained list box and entry field, depending on the 
  4805. support you require.  Use the obtained PM window handles to create an IListbox 
  4806. and IEntryfield. Then you can add drag and drop support to the new class 
  4807. objects. 
  4808.  
  4809. ISpinButton requires similar support; you must add drag support to the entry 
  4810. field contained in the spin button. 
  4811.  
  4812.  
  4813. ΓòÉΓòÉΓòÉ 10.17. Dynamic Data Exchange (DDE) ΓòÉΓòÉΓòÉ
  4814.  
  4815. This section discusses the Dynamic Data Exchange (DDE) classes. 
  4816.  
  4817.      What DDE Formats Are Supported? 
  4818.  
  4819.  
  4820. ΓòÉΓòÉΓòÉ 10.17.1. What DDE Formats Are Supported? ΓòÉΓòÉΓòÉ
  4821.  
  4822. Question: 
  4823.  
  4824. Is there a list of valid DDE data formats and what they represent? 
  4825.  
  4826. Answer: 
  4827.  
  4828. The information on the IDDE class in the Open Class Library Reference defines a 
  4829. number of IDDE:Format values. These values represent the predefined DDE formats 
  4830. defined in the header file <pmwin.h>.  (The formats in the header file all 
  4831. begin with SZFMT_). 
  4832.  
  4833. Applications can also define their own DDE formats.  If you want to use a 
  4834. format specific to a particular application, check the documentation for the 
  4835. application you want to communicate with for a description of the format. 
  4836.  
  4837.  
  4838. ΓòÉΓòÉΓòÉ 10.18. Exceptions ΓòÉΓòÉΓòÉ
  4839.  
  4840. This section discusses exceptions and exception handling. 
  4841.  
  4842.      What Happens to Exceptions on Secondary Threads? 
  4843.      Why Does My Program Just Exit? 
  4844.  
  4845.  
  4846. ΓòÉΓòÉΓòÉ 10.18.1. What Happens to Exceptions on Secondary Threads? ΓòÉΓòÉΓòÉ
  4847.  
  4848. Question: 
  4849.  
  4850. I throw an exception in a secondary thread that I started. What happens if I do 
  4851. not catch that exception in the function I started on that thread? 
  4852.  
  4853. Answer: 
  4854.  
  4855. If you started the thread with either _beginthread or the IThread class, the 
  4856. exception is handled as though it were the main thread: an uncaught exception 
  4857. on a thread calls terminate, which then calls abort. To avoid termination, put 
  4858. a try/catch block around the code in the secondary thread. 
  4859.  
  4860. If you started the thread with DosCreateThread and did not register the C++ 
  4861. OS/2 exception handler, the C++ exception is treated as though it never 
  4862. occurred. 
  4863.  
  4864.  
  4865. ΓòÉΓòÉΓòÉ 10.18.2. Why Does My Program Just Exit? ΓòÉΓòÉΓòÉ
  4866.  
  4867. Question: 
  4868.  
  4869. When I run the program I wrote with the User Interface classes, it simply ends. 
  4870. Why? 
  4871.  
  4872. Answer: 
  4873.  
  4874. What is probably happening is that an exception is being thrown and not being 
  4875. caught, causing the program to terminate. To learn more about the exception, 
  4876. use the User Interface library trace facility. Before running your program, 
  4877. enter: 
  4878.  
  4879.   SET ICLUI TRACE=ON
  4880.   SET ICLUI TRACETO=STDERR
  4881. (You could also set this in your CONFIG.SYS file.) 
  4882.  
  4883. When you run your program, redirect stderr to a file, for example: 
  4884.  
  4885.   myprog 2> myprog.out
  4886. After the program ends, look at myprog.out to see if exceptions were logged. 
  4887.  
  4888. For more information about the ITrace class, see the Open Class Library 
  4889. Reference. 
  4890.  
  4891.  
  4892. ΓòÉΓòÉΓòÉ 10.19. Internationalization ΓòÉΓòÉΓòÉ
  4893.  
  4894. This section discusses internationalization and national language support 
  4895. topics. 
  4896.  
  4897.      Are There Restrictions on National Language Support? 
  4898.      Can I Change Text on Message Box Buttons? 
  4899.  
  4900.  
  4901. ΓòÉΓòÉΓòÉ 10.19.1. Are There Restrictions on National Language Support? ΓòÉΓòÉΓòÉ
  4902.  
  4903. Question: 
  4904.  
  4905. Are there limitations of the national language support provided in the User 
  4906. Interface class library? If so, what are they? 
  4907.  
  4908. Answer: 
  4909.  
  4910. The known limitations of the class library support for national language 
  4911. enablement are: 
  4912.  
  4913.      There is no multiple code page support for IFont. 
  4914.  
  4915.      The following functions do not account for double-byte characters (DBCS): 
  4916.  
  4917.         -  IString::isLike 
  4918.         -  IFont::textWidth 
  4919.         -  IFont::charWidth 
  4920.         -  IFont::textLines 
  4921.  
  4922.      All messages retrieved from the message file are in English. (In the 
  4923.       Japanese version of VisualAge C++, they are in Japanese.) These messages 
  4924.       are used primarily for exception text for library-specific errors; the 
  4925.       class library retrieves other error messages from OS/2 and PM. If you 
  4926.       want to translate the message file into another language, the source is 
  4927.       available in the Class Library Source Code product. However, the end user 
  4928.       would not see this text unless you display exception text in message 
  4929.       boxes, or do something similar. 
  4930.  
  4931.  
  4932. ΓòÉΓòÉΓòÉ 10.19.2. Can I Change Text on Message Box Buttons? ΓòÉΓòÉΓòÉ
  4933.  
  4934. Question: 
  4935.  
  4936. I'm developing a bilingual application. I need the buttons to say OUI/NON 
  4937. instead of YES/NO. Is there a way to change the text on IMessageBox buttons? 
  4938.  
  4939. Answer: 
  4940.  
  4941. The PM message box does not support this, and displays the buttons using the 
  4942. language that was specified during system setup. However, you could replace the 
  4943. message box with a modal IFrameWindow with an ISetCanvas containing the buttons 
  4944. as a frame extension.  Then you could easily change the text. 
  4945.  
  4946.  
  4947. ΓòÉΓòÉΓòÉ 10.20. Extending the User Interface Class Library ΓòÉΓòÉΓòÉ
  4948.  
  4949. This section discusses how you can extend the User Interface class library. 
  4950.  
  4951.      How Can I Create a New IWindow Class? 
  4952.      Can I Use PM Window Words in My Application? 
  4953.  
  4954.  
  4955. ΓòÉΓòÉΓòÉ 10.20.1. How Can I Create a New IWindow Class? ΓòÉΓòÉΓòÉ
  4956.  
  4957. Question: 
  4958.  
  4959. I want to create a new IWindow class that is not based on one of the existing 
  4960. IWindow or derived classes.  The new class must work with a new handler class 
  4961. that processes new message types. What should I do? 
  4962.  
  4963. Answer: 
  4964.  
  4965. Assuming you have a unique PM window class, you need to create the windows and 
  4966. interact with them using C++: 
  4967.  
  4968.    1. Derive from IWindow. 
  4969.  
  4970.    2. Add constructors for your window class.  The constructor arguments should 
  4971.       correspond roughly to the values your PM window class takes for its style 
  4972.       and ctldata parameters to WinCreateWindow or WM_CREATE. 
  4973.  
  4974.    3. In your constructor, or in a common intialization function called from 
  4975.       each of your constructors, construct the appropriate arguments and call 
  4976.       WinCreateWindow or IWindow::create. Your constructors should use the 
  4977.       default constructor to construct the IWindow base class. 
  4978.  
  4979.    4. After you have the hwnd value returned by WinCreateWindow or 
  4980.       IWindow::create, call IWindow::startHandlingEventsFor. 
  4981.  
  4982.    5. At this point, you can add handlers to your window.  If you choose to 
  4983.       implement your window procedure as an IHandler, add the handler here. 
  4984.       You can have a separate handler for each window, or one that works for 
  4985.       all windows.  If you choose the latter, use a static member of your 
  4986.       IWindow-derived class to point to the shared handler (refer to 
  4987.       IFrameWindow for an example). Note that, if your PM window class includes 
  4988.       handler functions in its window procedure, you don't need a handler. 
  4989.  
  4990.    6. Add member functions to your derived IWindow class that correspond to the 
  4991.       window messages your PM window responds to.  If your window class is a 
  4992.       conventional PM class, you can implement those functions by sending the 
  4993.       appropriate PM message (IEvent). 
  4994.  
  4995.    7. If your window class is tailorable, meaning it sends notifications or 
  4996.       allows users to override the message handling, declare an 
  4997.       IHandler-derived class with an appropriate implementation of 
  4998.       dispatchHandlerEvent.  Typically, you would add virtual functions for the 
  4999.       notifications and events that can be handled. 
  5000.  
  5001.       You can also choose to derive specialized IEvent classes specific to the 
  5002.       events required. 
  5003.  
  5004.    8. If you are implementing the base window behavior as a handler (as 
  5005.       mentioned in step 5) rather than a PM window procedure, separate that 
  5006.       handler from the one described at step 7.  The latter should ideally have 
  5007.       empty implementations of all virtual functions. Users inherit the 
  5008.       built-in behavior of your primary handler in the base window by the 
  5009.       chaining done by the IWindow dispatching, not through C++ inheritance. 
  5010.       The inheritance diagram would look like: 
  5011.  
  5012.       This method is recommended because you are adding your handler 
  5013.       automatically at construction; if a user derives from the class without 
  5014.       knowing this, he or she could invoke your handler's code a second time by 
  5015.       calling Inherited::virtFunc. 
  5016.  
  5017.    9. Override inherited IWindow functions as required for your window. Often 
  5018.       you do not need to override any functions. 
  5019.  
  5020.  If you are interested in additional information, the September/October 1994 
  5021.  issue of OS/2 Developer magazine also has several articles relating to this 
  5022.  topic. 
  5023.  
  5024.  
  5025. ΓòÉΓòÉΓòÉ 10.20.2. Can I Use PM Window Words in My Application? ΓòÉΓòÉΓòÉ
  5026.  
  5027. Question: 
  5028.  
  5029. Does the User Interface class library use the window words provided in PM 
  5030. controls?  Can I use the user words in my application, or will that cause a 
  5031. conflict? 
  5032.  
  5033. Answer: 
  5034.  
  5035. The User Interface class library does not use the QWL_USER value.  Currently, 
  5036. it does not register any new window classes either. You can use the window 
  5037. words as described in the Presentation Manager Guide and Reference. 
  5038.  
  5039.  
  5040. ΓòÉΓòÉΓòÉ 10.21. Graphics and Drawing ΓòÉΓòÉΓòÉ
  5041.  
  5042. This section discusses using graphics and customized drawing with the User 
  5043. Interface classes. 
  5044.  
  5045.      Are There Graphics Classes? 
  5046.      How Can I Implement Customized Graphics? 
  5047.  
  5048.  
  5049. ΓòÉΓòÉΓòÉ 10.21.1. Are There Graphics Classes? ΓòÉΓòÉΓòÉ
  5050.  
  5051. Question: 
  5052.  
  5053. Which class implements the Gpi functions such as GpiLine, GpiPolyline, and 
  5054. GpiBox? 
  5055.  
  5056. Answer: 
  5057.  
  5058. The latest version of the User Interface class library now includes a set of 
  5059. 2-D graphics classes. See the Open Class Library User's Guide and Open Class 
  5060. Library Reference for more details on these classes and how to use them. 
  5061.  
  5062.  
  5063. ΓòÉΓòÉΓòÉ 10.21.2. How Can I Implement Customized Graphics? ΓòÉΓòÉΓòÉ
  5064.  
  5065. Question: 
  5066.  
  5067. Can I put graphics in the client area of a window?  How? 
  5068.  
  5069. Answer: 
  5070.  
  5071. Yes, you can. Use the samples 2D-BMAP, 2D-DRAW, and BIGCPP as a starting point. 
  5072. The HELLO6 sample also provides some example code that may be helpful. (All of 
  5073. these samples are included with VisualAge C++.) 
  5074.  
  5075.  
  5076. ΓòÉΓòÉΓòÉ 11. Creating Portable Applications ΓòÉΓòÉΓòÉ
  5077.  
  5078. This section discusses questions you might have about the portability of the 
  5079. applications you create with VisualAge C++. 
  5080.  
  5081.      What Operating Systems Does It Support? 
  5082.      What Are General Guidelines for Creating Portable Applications? 
  5083.      Are There Guidelines for Portable User Interface Applications? 
  5084.  
  5085.  
  5086. ΓòÉΓòÉΓòÉ 11.1. What Are General Guidelines for Creating Portable Applications? ΓòÉΓòÉΓòÉ
  5087.  
  5088. Question: 
  5089.  
  5090. I am writing an application that I want to be able to compile and run on other 
  5091. platforms. Are there any guidelines I should follow? 
  5092.  
  5093. Answer: 
  5094.  
  5095. To ensure the greatest degree of portability between operating system 
  5096. platforms, use only language and library extensions that are defined in current 
  5097. language standards such as ANSI/ISO and POSIX. 
  5098.  
  5099. If you are using VisualAge C++ on the other platforms, there may be extensions 
  5100. that are common.  Refer to the language and library references. 
  5101.  
  5102. If you use language elements that are implementation-defined (as described in 
  5103. the appendix about implementation-defined values in the Language Reference), 
  5104. try to code them in a way that will require less effort to port to platforms 
  5105. with different implementations. 
  5106.  
  5107. For example, in you require a variable to be exactly 32 bits in length, don't 
  5108. use unsigned int or unsigned long.  A better solution is to use a typedef to 
  5109. create a new type synonym, and then use that new type name instead. Then when 
  5110. you port to a different platform, you only have to modify the typedef. 
  5111.  
  5112. If you are creating a C++ program, another way to increase portability is to 
  5113. use the class libraries. Because they provide a layer of abstraction above the 
  5114. operating system, the code you write can be less system-specific. The 
  5115. VisualAge C++ class libraries are currently available on the OS/2, AIX, and 
  5116. Solaris operating systems. 
  5117.  
  5118. Note:  Some classes in the class libraries differ slightly from platform to 
  5119. platform, particularly the User Interface classes which must encapsulate very 
  5120. different system interfaces. The Open Class Library Reference includes 
  5121. portability information on each function, and platform-specific notes where 
  5122. applicable. For tips on creating portable applications with the User Interface 
  5123. class library, see Are There Guidelines for Portable User Interface 
  5124. Applications?. 
  5125.  
  5126.  
  5127. ΓòÉΓòÉΓòÉ 11.2. Are There Guidelines for Portable User Interface Applications? ΓòÉΓòÉΓòÉ
  5128.  
  5129. Question: 
  5130.  
  5131. I am writing an application that uses the User Interface classes, and I want to 
  5132. port it to other platforms. Are there any guidelines I should follow? 
  5133.  
  5134. Answer: 
  5135.  
  5136. The User Interface class library was designed to be as portable as possible to 
  5137. all supported environments, which currently include OS/2 (PM), AIX (Motif), and 
  5138. Solaris (Motif). Most of the classes are supported in all of the environments, 
  5139. but there are some unavoidable system differences. 
  5140.  
  5141. When you design your application for portability, you should consider the 
  5142. following differences that exist between the PM and Motif versions of the 
  5143. library: 
  5144.  
  5145.      Motif does not support DLGTEMPLATE resources or the ability to construct 
  5146.       an IFrameWindow from a DLGTEMPLATE resource. Use the ICanvas classes to 
  5147.       create portable dialogs. 
  5148.  
  5149.      Motif does not support Dynamic Data Exchange (the IDDE* classes). 
  5150.  
  5151.      The current Motif version does not support direct manipulation (IDM* 
  5152.       classes). 
  5153.  
  5154.      Motif does not support the owner-draw classes (IDrawItemEvent and derived 
  5155.       classes) or the handlers that process owner-draw events. To do customized 
  5156.       drawing in Motif, write a handler class to capture the appropriate X 
  5157.       events and use the X functions to do the drawing. 
  5158.  
  5159.      Motif does not support the IDynamicLinkLibrary class. To change the 
  5160.       resource library being used, you must change the locale (the LANG 
  5161.       environment variable and related settings) in the calling environment. 
  5162.  
  5163.      Motif does not support ISystemBitmapHandle or ISystemPointerHandle, or 
  5164.       the IBitmapControl and IIconControl constructors that use 
  5165.       ISystemBitmapHandle::Identifier and ISystemPointerHandle::Identifier as 
  5166.       parameters. 
  5167.  
  5168.      Because Motif does not provide a scheme palette, the IGUIColor class 
  5169.       returns hard-coded color values.  It is probably best to avoid color 
  5170.       manipulation where possible and use the default values provided by the 
  5171.       user in the OS/2 scheme palette or X resource database. 
  5172.  
  5173.      Under Motif, IThread does not support the creation or starting of new 
  5174.       threads. 
  5175.  
  5176.      Use ISetCanvas to create group boxes instead of the IGroupBox class for 
  5177.       better portability. 
  5178.  
  5179.  There are other classes and functions that are not provided in all 
  5180.  environments or have no effect in some environments. Refer to the Open Class 
  5181.  Library Reference for details on the support for each class and function. 
  5182.  
  5183.  VisualAge C++ also provides macros you can use to conditionally include 
  5184.  platform-dependent code. In the PM environment (VisualAge C++ for OS/2), the 
  5185.  IC_PM macro is defined. In the Motif environment (C Set ++ for AIX and 
  5186.  Solaris), the IC_MOTIF macro is defined. 
  5187.  
  5188.  
  5189. ΓòÉΓòÉΓòÉ 12. Compiling and Compiler Errors ΓòÉΓòÉΓòÉ
  5190.  
  5191. This section includes questions about using the compiler, as well as questions 
  5192. about compiler errors and why they occur. 
  5193.  
  5194.      Can I Use an Object File in Both an EXE and a DLL? 
  5195.      How Can I Improve Compiler Performance? 
  5196.      Can the Compiler Generate Assembler Listings? 
  5197.      Can I Compile C Files as C++ Files? 
  5198.      Why Doesn't My _beginthread Function Have _Optlink Linkage by Default? 
  5199.      Why Can't I Increment a Cast Value? 
  5200.      Why Are My Structures Incomplete or Mismatched? 
  5201.      How Should I Compile DB2 Applications? 
  5202.      Can I Inherit Static Data Members? 
  5203.      How Does the /Sn Option Enable DBCS Support? 
  5204.      Why Does My Part Get Compiler Errors? 
  5205.  
  5206.  
  5207. ΓòÉΓòÉΓòÉ 12.1. Can I Use an Object File in Both an EXE and a DLL? ΓòÉΓòÉΓòÉ
  5208.  
  5209. Question: 
  5210.  
  5211. How do I use VisualAge C++ to compile a library .OBJ file that can be linked 
  5212. into either an .EXE or a .DLL file? 
  5213.  
  5214. Answer: 
  5215.  
  5216. To compile objects that can be linked into an .EXE or DLL file, use the /Ge+ 
  5217. option. These objects must not contain a main function. 
  5218.  
  5219. To link in the correct startup code for a .EXE, compile the source file that 
  5220. contains the main function using the /Ge+ option. 
  5221.  
  5222. To link in the correct startup code for a .DLL, compile one of the source 
  5223. files, preferably the one that contains your _DLL_InitTerm function, with the 
  5224. /Ge- option. 
  5225.  
  5226. /Ge+generates a reference to _exeentry only if a main function is seen. 
  5227.  
  5228. /Ge- always generates a reference to _dllentry. 
  5229.  
  5230.  
  5231. ΓòÉΓòÉΓòÉ 12.2. How Can I Improve Compiler Performance? ΓòÉΓòÉΓòÉ
  5232.  
  5233. Question: What can I do to get faster compile times? 
  5234.  
  5235. Answer: 
  5236.  
  5237. You can speed up some compilations by doing one or all of the following: 
  5238.  
  5239.      Check the settings of your environment variables (LIBPATH, PATH, INCLUDE, 
  5240.       and so on). If the VisualAge C++ directories are at the end of the paths, 
  5241.       the compiler or linker must search through all of the other directories 
  5242.       before it finds the required DLLs, header files, and so on. 
  5243.  
  5244.      Ensure you preload the compiler with the /Tl option (it is preloaded by 
  5245.       default).  This option keeps the compiler components loaded in memory. 
  5246.  
  5247.      If you are statically linking to the VisualAge C++ libraries, try dynamic 
  5248.       linking. 
  5249.  
  5250.      Use precompiled header files.  See the User's Guide for details on how to 
  5251.       structure your files so the compiler can take full advantage of the 
  5252.       precompiled headers. 
  5253.  
  5254.      Turn off all optimizations. 
  5255.  
  5256.      If you are using the HPFS file system, set the IFS statement in your 
  5257.       CONFIG.SYS file to: 
  5258.  
  5259.               IFS=c:\os2\hpfs.ifs /cache:2048 /crecl:64
  5260.  
  5261.       This allows OS/2 to keep frequently-used files in memory between 
  5262.       compilations, which can greatly reduce the amount of time it requires the 
  5263.       compiler to process them. 
  5264.  
  5265.       Note:  If you experience performance problems and have LAN Requester 4.0 
  5266.       installed, doublecheck this statement in your CONFIG.SYS. Some users have 
  5267.       reported that LAN Requester 4.0 changes these settings and severely 
  5268.       degrades performance. 
  5269.  
  5270.      Add more RAM to your system.  In a memory-constrained environment, OS/2 
  5271.       spends more time swapping data to disk, which increases compilation times 
  5272.       tremendously. Additional RAM allows the compiler and its data to remain 
  5273.       in memory, which can make your builds run more quickly. 
  5274.  
  5275.      Define a virtual disk (VDISK or RAM disk) with the OS/2 VDISK device 
  5276.       driver.  It creates a disk from your system's RAM. For example, placing 
  5277.       this statement in your CONFIG.SYS file: 
  5278.  
  5279.                DEVICE=C:\OS2\VDISK.SYS 2048,,256
  5280.  
  5281.       allocates a virtual disk of 2M with 256 directory entries. You can then 
  5282.       copy all the library and header files you need for compiling and linking 
  5283.       to this disk and set your LIB and INCLUDE variables to point to it before 
  5284.       any other directory. Because these files are already in memory, your 
  5285.       compile and link times will improve. (Do not put the compiler executable 
  5286.       files there; the compiler preloads them into memory by default, so you 
  5287.       would then have two copies in memory.) 
  5288.  
  5289.       However, there are drawbacks to using a VDISK. The data on it is lost 
  5290.       when you reboot. Also, memory allocated for a VDISK is unswappable memory 
  5291.       space, meaning it cannot be used as normal memory space by applications. 
  5292.       Because C++ compilations can require a lot of memory, putting memory into 
  5293.       a VDISK could cause excessive memory paging and slow down your 
  5294.       compilation. If you have a large VDISK, it may be to your advantage to 
  5295.       eliminate it or make it smaller to provide more available memory to the 
  5296.       compiler 
  5297.  
  5298.      Minimize dependencies between source files so that changes made to one 
  5299.       file don't require you to recompile all your files. 
  5300.  
  5301.      For C++ programs specifically: 
  5302.  
  5303.         -  Create abstract objects that contain only public methods and make 
  5304.            your real objects descendents of those objects.  This approach 
  5305.            reduces the amount of total source code in compiles that do not need 
  5306.            to refer to the real objects. 
  5307.         -  In .HPP files, only include those files you need. 
  5308.  
  5309.            For example, if all that the .HPP file for class b needs to know 
  5310.            about class a is that class b contains a pointer to a class a-type 
  5311.            object, put class a;, (rather than #include "a.hpp") in B.HPP. 
  5312.  
  5313.            Note:  This approach would still allow you to put #include "a.hpp" 
  5314.            in B.CPP. 
  5315.  
  5316.  
  5317. ΓòÉΓòÉΓòÉ 12.3. Can the Compiler Generate Assembler Listings? ΓòÉΓòÉΓòÉ
  5318.  
  5319. Question: 
  5320.  
  5321. Is there a compiler option that provides instruction offsets in conjunction 
  5322. with the assembler code? 
  5323.  
  5324. Answer: 
  5325.  
  5326. There is no compiler option that provides instruction offsets with assembler 
  5327. code.  You can usually process the output of the /Fa+ option with a 32-bit 
  5328. assembler. 
  5329.  
  5330. However, because of the nature of some assemblers, output of /Fa+ that is 
  5331. processed with an assembler may not be identical to the compiler output.  Also, 
  5332. certain problems, such as variables that have the same name as assembler 
  5333. statements, may prevent the code from assembling. 
  5334.  
  5335. You can also link with the /L option to get line offsets. refdi=xlat. 
  5336.  
  5337. Use the VisualAge C++ Debugger to look at the actual object code. 
  5338.  
  5339.  
  5340. ΓòÉΓòÉΓòÉ 12.4. Can I Compile C Files as C++ Files? ΓòÉΓòÉΓòÉ
  5341.  
  5342. Question: 
  5343.  
  5344. How do I compile an application written in C as if it were C++ on the 
  5345. VisualAge C++ compiler?  I have tried to do this, but I get syntax errors in 
  5346. some header files. 
  5347.  
  5348. Answer: 
  5349.  
  5350. VisualAge C++ allows you to mix your C- and C++-compiled modules freely as long 
  5351. as you use extern "C" { ... }  with any prototypes of functions that are called 
  5352. by C code or are compiled as C code. 
  5353.  
  5354. Note that there are some language elements, such as #pragma linkage directives, 
  5355. that are valid in C but not in C++.  If your C source files contain these 
  5356. language elements, you cannot compile them as C++.  For complete information on 
  5357. C and C++ compatibility, see the Language Reference. 
  5358.  
  5359.  
  5360. ΓòÉΓòÉΓòÉ 12.5. Why Doesn't My _beginthread Function Have _Optlink Linkage by Default? ΓòÉΓòÉΓòÉ
  5361.  
  5362. Question: 
  5363.  
  5364. I am using _beginthread to start a thread, and passing func as the function to 
  5365. run in that thread. I declared func as static void func(void). The compiler 
  5366. says that it cannot convert func to _Optlink. I thought that _Optlink was the 
  5367. default calling convention.  Why am I getting this error? 
  5368.  
  5369. Answer: 
  5370.  
  5371. If you are compiling a C program, _Optlink is the default calling convention. 
  5372. Make sure you did not change the default with one of the /M compiler options. 
  5373.  
  5374. If you are compiling a C++ program, the default calling convention is a bit 
  5375. different.  C++ functions have C++ linkage.  They use the _Optlink model of 
  5376. parameter passing, but they also have mangled names and can be overloaded. You 
  5377. need to tell the compiler that func is a C function by declaring it as extern 
  5378. "C", extern "OPTLINK", or _Optlink. For example, instead of declaring your C++ 
  5379. function as: 
  5380.  
  5381.    void cpp_func(void *);
  5382.  
  5383. use one of the following declarations: 
  5384.  
  5385.    extern "OPTLINK" void cpp_func(void *);
  5386.    void _Optlink cpp_func(void *);
  5387.    extern "C" void cpp_func(void *); // if _Optlink is the default
  5388.                                      // calling convention (/Mp option)
  5389.  
  5390. You cannot specify a member function for _beginthread. 
  5391.  
  5392.  
  5393. ΓòÉΓòÉΓòÉ 12.6. Why Can't I Increment a Cast Value? ΓòÉΓòÉΓòÉ
  5394.  
  5395. Question: 
  5396.  
  5397. Why does the compiler generate an error message for the statement 
  5398. ((long *)fred)++ ? 
  5399.  
  5400. Answer: 
  5401.  
  5402. There are two problems with this expression.  First, the operand of the 
  5403. increment operator (++) must be an lvalue.  Because a cast does not produce an 
  5404. lvalue, the statement above is not valid and the compiler generates an error 
  5405. for it. 
  5406.  
  5407. Operators that must have lvalue operands include the increment and decrement 
  5408. operators ++ and --, as well as the simple and compound assignment operators. 
  5409.  
  5410. The following statement yields and increments an lvalue: 
  5411.  
  5412.    (*(long **)&fred)++
  5413.  
  5414. For more information on casting and lvalues, see the Language Reference. 
  5415.  
  5416. The other and more important problem is that you are trying to reference a 
  5417. value using a type other than the one it was defined with.  According to the 
  5418. ANSI/ISO standard, you can only reference an object using its declared type 
  5419. (with some minor changes such as qualifiers) or a char *. The example statement 
  5420. may or may not work, but is not guaranteed to work. 
  5421.  
  5422. Change your code to reference the value either using its declared type or a 
  5423. char *. 
  5424.  
  5425.  
  5426. ΓòÉΓòÉΓòÉ 12.7. Why Are My Structures Incomplete or Mismatched? ΓòÉΓòÉΓòÉ
  5427.  
  5428. Question: 
  5429.  
  5430. The compiler says that the argument I am passing to a function doesn't match 
  5431. its prototype, but both have the same structure type: 
  5432.  
  5433.    int func(struct st *);
  5434.    struct st {int s1;} ss;
  5435.  
  5436.    func(&ss);
  5437.  
  5438. Why? 
  5439.  
  5440. Answer: 
  5441.  
  5442. A structure declaration must appear before any function prototype statements 
  5443. that use that structure type. GIven the above declaration for func: 
  5444.  
  5445.    int func(struct st *);
  5446.            a           b
  5447.  
  5448. At point (a), a new scope is opened for the identifiers that are introduced in 
  5449. the parameter list.  At point (b), this scope is closed.  Every identifier that 
  5450. appears betweeen (a) and (b) is local to that scope, and nothing outside is 
  5451. allowed to look inside. 
  5452.  
  5453. The declaration of struct st occurs outside the scope of the function 
  5454. declaration for func. Therefore, this struct st is different from the struct st 
  5455. is the function prototype. 
  5456.  
  5457. As a result, struct st is incomplete when it is introduced in the parameter 
  5458. list of func, and can never be completed because its scope is closed to 
  5459. everything outside.  Only a void pointer could be passed to func. 
  5460.  
  5461. To solve this problem, declare the structure before you use it in the the 
  5462. function prototype.  For example: 
  5463.  
  5464.    struct st;
  5465.    int f(struct st *);
  5466.    struct st {int s1;} ss;
  5467.  
  5468.    f(&ss);
  5469.  
  5470. Declaring the tag at file scope causes all subsequent occurrences of struct st 
  5471. to resolve to the same file scope identifier, and everything works correctly. 
  5472.  
  5473.  
  5474. ΓòÉΓòÉΓòÉ 12.8. How Should I Compile DB2 Applications? ΓòÉΓòÉΓòÉ
  5475.  
  5476. Question: 
  5477.  
  5478. What compiler options do I need to set to create a DB2 application using 
  5479. VisualAge C++? 
  5480.  
  5481. Answer: 
  5482.  
  5483. The easiest way to build DB2 applications is to use Data Access Builder to 
  5484. create classes to access the DB2/2 database, and code your program in C++. 
  5485. Using these classes may eliminate the need to call DB2/2 APIs directly. You can 
  5486. then use whatever compiler options are appropriate. 
  5487.  
  5488. If you are calling DB2/2 APIs directly, compile with the /DES32TO16 option 
  5489. (defines ES32TO16) and link with the SQL_DYN.LIB library. 
  5490.  
  5491. You also need to add the SQLLIB directory to the INCLUDE and LIB paths in your 
  5492. CONFIG.SYS file. 
  5493.  
  5494.  
  5495. ΓòÉΓòÉΓòÉ 12.9. Can I Inherit Static Data Members? ΓòÉΓòÉΓòÉ
  5496.  
  5497. Question: 
  5498.  
  5499. The following code gives very different warnings and errors when compiled with 
  5500. different compilers: 
  5501.  
  5502.    class a {
  5503.    public:
  5504.    static int sm;
  5505.    };
  5506.  
  5507.    int a::sm = 1;
  5508.  
  5509.    class b: public a {
  5510.    };
  5511.  
  5512.    int b::sm = 2;
  5513.  
  5514. I want all classes that inherit from a to have a member sm that has a unique 
  5515. value for the class.  However, VisualAge C++ generates the following error 
  5516. message: 
  5517.  
  5518.    13       |int b::sm = 2;
  5519.    test.cpp(13:1) : error EDC3079: "sm" is not a member of "b".
  5520. Does this mean that static members are not inherited in C++? 
  5521.  
  5522. Answer: 
  5523.  
  5524. There is only one instance of a static member called sm in your program, and it 
  5525. belongs to class a.  Class b does not contain a separate copy of sm, it 
  5526. inherits a::sm. 
  5527.  
  5528. Because class b does not contain its own copy of sm, it does not allow: 
  5529.  
  5530.    int b::sm = 2;
  5531. However, used in an expression, a::sm and b::sm refer to the same piece of 
  5532. storage. 
  5533.  
  5534. If you want class b to have its own copy of sm, declare it as a static member, 
  5535. which then hides a::sm. 
  5536.  
  5537.  
  5538. ΓòÉΓòÉΓòÉ 12.10. How Does the /Sn Option Enable DBCS Support? ΓòÉΓòÉΓòÉ
  5539.  
  5540. Question: 
  5541.  
  5542. According to the compiler documentation, the /Sn compiler option allows you to 
  5543. use the double-byte character set (DBCS). What does that mean? 
  5544.  
  5545. Answer: 
  5546.  
  5547. Use /Sn to tell the compiler whether you use double-byte characters in your 
  5548. source code. It specifies whether characters in the DBCS first-byte range 
  5549. should be interpreted as single-byte characters (/Sn-) or as the first half of 
  5550. a double-byte character (/Sn+). DBCS support is always included in the runtime 
  5551. library and VisualAge C++-generated code, regardless of compiler options. 
  5552.  
  5553. If you are interested in DBCS support because you want to translate or tailor 
  5554. your applications for other countries or languages, see the information on 
  5555. locales and internationalization, beginning with "Introduction to Locale" in 
  5556. the Programming Guide. 
  5557.  
  5558.  
  5559. ΓòÉΓòÉΓòÉ 13. Linking and Linker Errors ΓòÉΓòÉΓòÉ
  5560.  
  5561. The questions in this section deal with how to link your program and with 
  5562. errors that occur at link time. 
  5563.  
  5564.      Which Libraries Should I Link To? 
  5565.      How Can I Improve Linker Performance? 
  5566.      Why Are My Symbols Defined More than Once? 
  5567.      When Should I Use the /NOD Option? 
  5568.      Why Do I Get Unresolved External Errors? 
  5569.      Why Does errno Cause an Undefined External Error? 
  5570.      Why Does Inlining Cause Unresolved External Errors? 
  5571.      Why Does My Part Get Unresolved External Link Errors? 
  5572.      Why Is My virtual-fcn-table-ptr Unresolved? 
  5573.      Why Does /Ti Cause Unresolved External References? 
  5574.  
  5575.  
  5576. ΓòÉΓòÉΓòÉ 13.1. Which Libraries Should I Link To? ΓòÉΓòÉΓòÉ
  5577.  
  5578. Question: 
  5579.  
  5580. What libraries should I use to link? 
  5581.  
  5582. Answer: 
  5583.  
  5584. You do not have to specify any libraries for the link step. Information about 
  5585. the required libraries, including the IBM Open Class library files, is imbedded 
  5586. in your .OBJ files by the compiler according to the compiler options you use 
  5587. and the #pragma library statements in the header files you include. 
  5588.  
  5589. If you mix objects compiled with different runtime options (for example, one 
  5590. multithread and the other single-thread), the linker generates duplicate 
  5591. definition errors, as described in Why Are My Symbols Defined More than Once?. 
  5592.  
  5593. There are compiler and linker options to exclude or ignore the information 
  5594. about the default libraries (/Gn and /NOD), but we do not recommend you use 
  5595. them. If you specify these options, you must then explicitly specify the names 
  5596. of all required libraries to the linker. If the libraries specified are 
  5597. incorrect, your program may not link or run correctly. 
  5598.  
  5599. For details on the names of the library files, see What Are the Library Naming 
  5600. Conventions?. 
  5601.  
  5602.  
  5603. ΓòÉΓòÉΓòÉ 13.2. How Can I Improve Linker Performance? ΓòÉΓòÉΓòÉ
  5604.  
  5605. Question: 
  5606.  
  5607. What can I do to get faster link times? 
  5608.  
  5609. Answer: 
  5610.  
  5611. To improve linker performance: 
  5612.  
  5613.      Invoke the linker using icc to preload it in memory. 
  5614.  
  5615.      Use the /NOEXEPACK option. 
  5616.  
  5617.      Use the /NODEBUG option if you don't need debug information.  If you do 
  5618.       need debug information, use /DBGPACK. 
  5619.  
  5620.      Do not use the /NOE or /SEG options unless a linker error message tells 
  5621.       you to. 
  5622.  
  5623.      Convert old .LIB files to the new format: 
  5624.  
  5625.                 ILIB /CONV /NOBR xxx.LIB;
  5626.  
  5627.       or for import libraries: 
  5628.  
  5629.                ILIB /CONV /NOBR /NOE xxx.LIB;
  5630.  
  5631.      Do not use the /OPTFUNC option. 
  5632.  
  5633.  To improve your application load time: 
  5634.  
  5635.      Use the /EXEPACK option, or /EXEPACK if you are targetting only OS/2 Warp 
  5636.       systems. 
  5637.  
  5638.      Use the /OPTFUNC option. 
  5639.  
  5640.  
  5641. ΓòÉΓòÉΓòÉ 13.3. Why Are My Symbols Defined More than Once? ΓòÉΓòÉΓòÉ
  5642.  
  5643. Question: 
  5644.  
  5645. When I link my object modules, the linker says that some symbols are defined 
  5646. more than once.  The symbols are not in my source code, so I think they're in 
  5647. the runtime library. Why do I get this error? 
  5648.  
  5649. Answer: 
  5650.  
  5651. You are probably linking objects that were compiled with incompatible compiler 
  5652. options.  For example, if you compile one module as a multithread program 
  5653. (/Gm+) and another as single-thread (/Gm-), each will include a reference to a 
  5654. different runtime library. At link time, both libraries are linked in, 
  5655. resulting in symbols being defined more than once. 
  5656.  
  5657. Recompile your objects using the same compiler options. 
  5658.  
  5659.  
  5660. ΓòÉΓòÉΓòÉ 13.4. When Should I Use the /NOD Option? ΓòÉΓòÉΓòÉ
  5661.  
  5662. Question: 
  5663.  
  5664. When should I use the /NOD linker option? 
  5665.  
  5666. Answer: 
  5667.  
  5668. We do not recommend the /NOD option for general use.  It tells the linker to 
  5669. ignore the library information included in the object modules being linked and 
  5670. to link in only the libraries you explicitly specify in the linker command. You 
  5671. must then make sure that the libraries you link in match the libraries that the 
  5672. object modules were compiled for. For example, if the objects were compiled as 
  5673. multithread objects (/Gm+ compiler option) and you use /NOD to override the 
  5674. specified library and link them with the single-thread library, the linker will 
  5675. have unresolved references. 
  5676.  
  5677. However, if you have created your own runtime libraries, you need to use /NOD 
  5678. and specify the names of your libraries and OS2386.LIB. You can use /NOD in 
  5679. other situations, but be careful that you specify the correct libraries. 
  5680.  
  5681. Note also that using the /Gn+ compiler option suppresses the default library 
  5682. information in the object module itself.  Using this compiler option has the 
  5683. same effect as using the /NOD linker option; you must then explicitly specify 
  5684. the correct libraries in the linker command. 
  5685.  
  5686.  
  5687. ΓòÉΓòÉΓòÉ 13.5. Why Do I Get Unresolved External Errors? ΓòÉΓòÉΓòÉ
  5688.  
  5689. Question: 
  5690.  
  5691. Why is the linker generating unresolved external errors? 
  5692.  
  5693.  Answer: 
  5694.  
  5695. The linker probably cannot find the libraries it needs to construct the 
  5696. executable module. 
  5697.  
  5698. Make sure that you specify all necessary libraries when you invoke the linker. 
  5699. The correct VisualAge C++ libraries are linked in by default, unless you use 
  5700. the /Gn compiler option or the /NOD linker option. 
  5701.  
  5702. Avoid using the /Gn compiler option and /NOD linker option. The /Gn option 
  5703. suppresses information about the default libraries from the linker; the /NOD 
  5704. option causes the linker to ignore the default libraries.  When you use these 
  5705. options, you must specify on the command line all libraries you use, both 
  5706. directly and indirectly. 
  5707.  
  5708. For details about what libraries you need to include, see Which Libraries 
  5709. Should I Link To?. 
  5710.  
  5711. This error can also occur if you do not specify your functions and variables 
  5712. using consistent case. For example, if you define a function as UPPERCASE, but 
  5713. then call it as uppercase. Because the C language is case sensitive, the linker 
  5714. is also case sensitive by default. 
  5715.  
  5716. You can specify the /IGNORECASE linker option to make it case insensitive, but 
  5717. because the VisualAge C++ libraries and most other C code are case sensitive, 
  5718. you may encounter more problems at a later time.  Change your code so that the 
  5719. case of the function name is the same in the definition and in the call. 
  5720.  
  5721. Another possibility is that you are compiling code with templates using the 
  5722. /Ft+ option.  When you use this method of handling templates, additional source 
  5723. files are created in your TEMPINC directory.  Before you link, you must compile 
  5724. these files as well, and any additional files that are created when you compile 
  5725. the TEMPINC files.  For this reason, use icc to invoke the linker for you to 
  5726. ensure that all TEMPINC files are compiled before the link step. 
  5727.  
  5728. For more details on templates and how to use them, see the sections on 
  5729. templates in the Language Reference and the Programming Guide. 
  5730.  
  5731.  
  5732. ΓòÉΓòÉΓòÉ 13.6. Why Does errno Cause an Undefined External Error? ΓòÉΓòÉΓòÉ
  5733.  
  5734. Question: 
  5735.  
  5736. Why do I get an undefined external error for errno? 
  5737.  
  5738. Answer: 
  5739.  
  5740. When you use the single-thread library, there is only one instance of errno, 
  5741. and it is defined as an extern int. However, when you use the multithread 
  5742. library, there is a separate instance of errno for each thread, so it is 
  5743. defined differently than it is in the single-thread library. 
  5744.  
  5745. Ensure you: 
  5746.  
  5747.      Always include <errno.h>. It defines errno appropriately for either the 
  5748.       single-thread or multithread library (depending on the compiler option 
  5749.       you specify). 
  5750.  
  5751.      Compile and link all modules with the same library. If you compile module 
  5752.       A with the single-thread library and module B with the multithread 
  5753.       library, linking both together with either library generates an 
  5754.       unresolved external error. 
  5755.  
  5756.  
  5757. ΓòÉΓòÉΓòÉ 13.7. Why Does Inlining Cause Unresolved External Errors? ΓòÉΓòÉΓòÉ
  5758.  
  5759. Question: 
  5760.  
  5761. I am trying to inline one of my functions, but I keep getting an "external not 
  5762. found" error in another module. Why? 
  5763.  
  5764. Answer: 
  5765.  
  5766. Inline functions are only available in the source file in which they are 
  5767. defined. (They are conceptually similar to static functions with regard to 
  5768. scoping.) If you have defined the inline function in one module, it is not 
  5769. available to your other modules, the reason you are getting the "unresolved 
  5770. external". 
  5771.  
  5772. Inlining means you want the compiler to inline the code if possible rather than 
  5773. linking the functions together. The compiler can't inline code that is not 
  5774. available until your modules are linked together. 
  5775.  
  5776. You may want to put your inline function in a .H file and include the .H file 
  5777. in both source files that need the function. Alternatively, you could use the 
  5778. intermediate code linker to link the intermediate files together. 
  5779.  
  5780.  
  5781. ΓòÉΓòÉΓòÉ 13.8. Why Is My virtual-fcn-table-ptr Unresolved? ΓòÉΓòÉΓòÉ
  5782.  
  5783. Question: 
  5784.  
  5785. When I link C++ code, I get the following linker error: 
  5786.  
  5787.    X::virtual-fcn-table-ptr: undefined symbol
  5788. What am I doing wrong? 
  5789.  
  5790. Answer: 
  5791.  
  5792. The missing virtual-fcn-table for a class is a compiler-generated data 
  5793. structure that is used to implement virtual function calls for that class.  The 
  5794. compiler has to determine which compilation unit it should generate each table 
  5795. in.  Often, the compiler generates the table in the compilation that contains 
  5796. your definition of a selected virtual function.  If you never define that 
  5797. function, the table is never generated, and this linker error results. 
  5798.  
  5799. If you recompile your code with the /Wvft+ option, the compiler will produce a 
  5800. message similar to: 
  5801.  
  5802.   EDC3281: informational The virtual function table for X will be
  5803.   defined where X::foo() is defined.
  5804. You will find that the function X::foo() has not been defined anywhere. 
  5805.  
  5806.  
  5807. ΓòÉΓòÉΓòÉ 13.9. Why Does /Ti Cause Unresolved External References? ΓòÉΓòÉΓòÉ
  5808.  
  5809. Question: 
  5810.  
  5811. When I compile the following program with debug information on: 
  5812.  
  5813. class X
  5814. {
  5815. protected:
  5816. int getI() {return i;}
  5817. static int i;
  5818. };
  5819.  
  5820. main(int argc, char *argv[])
  5821. {
  5822. X x;
  5823. return 0;
  5824. }
  5825. why does it generate the following linker error? 
  5826.  
  5827.    filename.obj(filename.CPP) : error L2029: 'X::i' : unresolved
  5828.    external
  5829.  
  5830. Answer: 
  5831.  
  5832. When you compile with debug information on, the compiler generates an external 
  5833. reference to X::i so that you can see the value of X::i from any other 
  5834. compilation units that make up your application.  If the compiler didn't do 
  5835. this, you would only be able to view the contents of X::i while you are in the 
  5836. source view for the compilation unit in which X::i was defined (where the 
  5837. storage was allocated). 
  5838.  
  5839. The unresolved reference is a result of no storage being allocated for the 
  5840. static data member; it was declared but it was not defined. The compiler does 
  5841. not know if the storage has been allocated in another compilation unit so it 
  5842. can't check if it should put out the reference or not.  Therefore, it always 
  5843. puts out references to static data members.  Add the following statement, which 
  5844. allocates storage for the data member: 
  5845.  
  5846.    int X::i = <some value>;
  5847.  
  5848. If you never reference the static class variable, the amount of storage 
  5849. available for it is irrelevant.  Your program generates the same results 
  5850. whether or not it exists.  The same is true for unreferenced class methods. 
  5851.  
  5852. One of the reasons that external references are not included when they are not 
  5853. required is that unreferenced data items may consume page space or address 
  5854. space, but they do not increase the size of the working set, except for a 
  5855. slight effect they may have on page tables. 
  5856.  
  5857.  
  5858. ΓòÉΓòÉΓòÉ 14. Runtime Errors ΓòÉΓòÉΓòÉ
  5859.  
  5860. This section contains possible answers to questions that you might have when 
  5861. you run a program.  Refer to this section if your program ends abnormally or 
  5862. behaves unexpectedly. 
  5863.  
  5864.      Why Does My DLL Work Incorrectly? 
  5865.      Why Does Adding Entry Points Change Existing Ones? 
  5866.      Why Does My DLL End Abnormally When I Call It? 
  5867.      Can I Allocate and Free Memory across Modules? 
  5868.      Should I Link My DLL to the VisualAge C++ Runtime Library? 
  5869.      Why Don't My String and Memory Functions Work in DLLs? 
  5870.      Why Are My Classes Initialized Multiple Times? 
  5871.      Why Is _DLL_InitTerm Causing Errors? 
  5872.      Why Does a Destructor Exception End My Program? 
  5873.      Why Does a Destructor Corrupt the Object? 
  5874.      Why Does Calling a Destructor Explicitly Cause Errors? 
  5875.      Why Do I Get an Access Violation from the Runtime DLL? 
  5876.      Why Can't I Open a File? 
  5877.      Why Does Optimization Cause My Program to Fail? 
  5878.      Why Doesn't My Old C Code Work? 
  5879.      Why Does One Function Alter Information from Another? 
  5880.      Why Do My Window Procedures End Abnormally? 
  5881.      Why Does Printing a _Seg16 Pointer Trap? 
  5882.      What Is __EDCThunkProlog and Why Does It Trap? 
  5883.      Why Does printf Work Incorrectly? 
  5884.      Why Doesn't printf Output Display? 
  5885.      Why Does scanf Behave Unexpectedly? 
  5886.      Why Do Library Functions and APIs Not Work? 
  5887.      Why Do Macros with Increment Operators Work Incorrectly? 
  5888.      Why Doesn't My Macro Resolve Correctly? 
  5889.      Why Don't My Threads Work Correctly? 
  5890.      Why Do My Statements Have No Effect? 
  5891.      Why Do Increment Operators Produce Unexpected Results? 
  5892.      Why Do I Get a SYS2070 Error? 
  5893.      Why Does My PM Application Disappear? 
  5894.      Why Does My Program Work Incorrectly and Inconsistently? 
  5895.      Where Is the Message File? 
  5896.      Why Doesn't My Application End when the Frame is Closed? 
  5897.      Why Does My Program Just Exit? 
  5898.  
  5899.  
  5900. ΓòÉΓòÉΓòÉ 14.1. Why Does My DLL Work Incorrectly? ΓòÉΓòÉΓòÉ
  5901.  
  5902. Question: 
  5903.  
  5904. Why doesn't my DLL work correctly? 
  5905.  
  5906. Answer: 
  5907.  
  5908. You may be mixing objects compiled with the /Ge+ and /Ge- compiler options in 
  5909. the same DLL. 
  5910.  
  5911. The VisualAge C++ libraries provide different initialization routines for 
  5912. executable modules and DLLs.  To ensure that the correct initialization routine 
  5913. is run, use the /Ge+ option when you create an executable module and the /Ge- 
  5914. option when you create a DLL. 
  5915.  
  5916. When you link your files, you can override the /Ge option you specified at 
  5917. compile time.  See the User's Guide for more information on how to do this. See 
  5918. the Programming Guide for more information on DLLs in general. 
  5919.  
  5920.  
  5921. ΓòÉΓòÉΓòÉ 14.2. Why Does Adding Entry Points Change Existing Ones? ΓòÉΓòÉΓòÉ
  5922.  
  5923. Question: 
  5924.  
  5925. I have an existing DLL that exports a number of functions and works correctly. 
  5926. However, when I add more entry points (export additional functions), the DLL no 
  5927. longer works as it did. How can I add entry points without affecting existing 
  5928. ones? 
  5929.  
  5930. Answer: 
  5931.  
  5932. When you add to your DLL, you are probably changing the ordinal numbers 
  5933. associated with your existing entry points. 
  5934.  
  5935. A DLL contains a table that maps names to entry points. An ordinal is an index 
  5936. into this table. The OS/2 loader can resolve entry points by either name or 
  5937. ordinal, depending on what is available.  Resolving by ordinal is faster. 
  5938.  
  5939. If you build an import library (.LIB) with ILIB using a .DEF file that does not 
  5940. contain ordinals, the library only provides the loader with names for the entry 
  5941. points. If you create the library from the DLL, both names and ordinals are 
  5942. included, and calls to the DLL are resolved by ordinal.  If you do not 
  5943. explicitly associate an ordinal with an entry point, the ordinal could change 
  5944. when you rebuild the DLL.  You then need to rebuild all executables and DLLs 
  5945. that reference that DLL or library. 
  5946.  
  5947. To avoid any confusion, you should define both a name and an ordinal for each 
  5948. entry point in one of the following ways: 
  5949.  
  5950.    1. Use #pragma export to specify the name and ordinal for each export.  If 
  5951.       you do not change the #pragma directives when you rebuild your DLL, the 
  5952.       files currently using that DLL do not require rebuilding. 
  5953.  
  5954.    2. List the exports in the .DEF file by name and ordinal. Again, if you do 
  5955.       not change the names or ordinals of existing entry points when you 
  5956.       rebuild the DLL, the files currently using that DLL do not require 
  5957.       relinking. The advantage of using a .DEF file instead of #pragma export 
  5958.       is that your exports are defined in one place. 
  5959.  
  5960.  Alternatively, include the statement OLD in your .DEF file.  This statement 
  5961.  tells the linker to maintain the ordinal assignments as used in a previous 
  5962.  version of the DLL.  If you are making only a few changes to a DLL that is 
  5963.  mostly complete, this method is quicker than defining ordinals for all entry 
  5964.  points. See the section on Linking in the User's Guide for more information on 
  5965.  the OLD statement. 
  5966.  
  5967.  
  5968. ΓòÉΓòÉΓòÉ 14.3. Why Does My DLL End Abnormally When I Call It? ΓòÉΓòÉΓòÉ
  5969.  
  5970. Question: 
  5971.  
  5972. My DLL ends abnormally when a second process tries to call it.  Why? 
  5973.  
  5974. Answer: 
  5975.  
  5976. It could be that both processes are trying to use the same memory for library 
  5977. data, but only one of them has access. Make sure that you include the following 
  5978. statements in your module definition (.DEF) file: 
  5979.  
  5980.      LIBRARY INITINSTANCE TERMINSTANCE 
  5981.  
  5982.       This statement identifies the executable file as a DLL. INITINSTANCE 
  5983.       specifies that the _DLL_InitTerm function is called the first time the 
  5984.       DLL is loaded for each process that accesses the DLL. TERMINSTANCE 
  5985.       specifies that _DLL_InitTerm is called the last time the DLL is loaded 
  5986.       for each process that accesses the DLL. 
  5987.  
  5988.      DATA MULTIPLE NONSHARED 
  5989.  
  5990.       This statement defines the default attributes for data segments within 
  5991.       the DLL. MULTIPLE specifies that there is a separate copy of the data 
  5992.       segment for each process that accesses the DLL. NONSHARED specifies that 
  5993.       the data segment is not shared by other processes. 
  5994.  
  5995.  If you need to share memory between two instances of your DLL, use #pragma 
  5996.  data_seg to put the data to be shared in a named data segment.  Then put a 
  5997.  SEGMENTS statement in the .DEF file for your DLL and specify that segment 
  5998.  after it. 
  5999.  
  6000.  For more information on DLLs, see Building Dynamic Link Libraries in the 
  6001.  Programming Guide. 
  6002.  
  6003.  
  6004. ΓòÉΓòÉΓòÉ 14.4. Can I Allocate and Free Memory across Modules? ΓòÉΓòÉΓòÉ
  6005.  
  6006. Question: 
  6007.  
  6008. I allocate memory in one DLL, using new or malloc, and then free it in another 
  6009. DLL. Sometimes this works, but other times it causes my application to trap. 
  6010. Why? 
  6011.  
  6012. Answer: 
  6013.  
  6014. In most cases, you can allocate memory in one module (executable or DLL) and 
  6015. free it in another. (Note that this has changed from the previous release of 
  6016. C Set ++.) 
  6017.  
  6018. However, both modules must be linked to the same copy of the library code. 
  6019.  
  6020.  
  6021. ΓòÉΓòÉΓòÉ 14.5. Should I Link My DLL to the VisualAge C++ Runtime Library? ΓòÉΓòÉΓòÉ
  6022.  
  6023. Question: 
  6024.  
  6025. I'm creating a DLL.  Do I need to link it to the VisualAge C++ runtime library? 
  6026.  
  6027. Answer: 
  6028.  
  6029. If you are not making any runtime calls out of your DLL, you don't have to do 
  6030. anything else and don't have to link to the runtime library. 
  6031.  
  6032. If you do use the runtime, you have to specify the /Gd+ option when you 
  6033. compile.  Otherwise, the VisualAge C++ runtime environment may not be 
  6034. initialized correctly. 
  6035.  
  6036. You will probably need some kind of runtime support because you probably have a 
  6037. static constructor and/or destructor in your DLL.  Make sure that you call the 
  6038. __ctordtorInit and __ctordtorTerm routines as described in the Programming 
  6039. Guide. 
  6040.  
  6041.  
  6042. ΓòÉΓòÉΓòÉ 14.6. Why Don't My String and Memory Functions Work in DLLs? ΓòÉΓòÉΓòÉ
  6043.  
  6044. Question: 
  6045.  
  6046. I have a problem with the strupr, stricmp, and memicmp library functions when 
  6047. they are used in a DLL.  They work if only a single copy of the DLL is loaded, 
  6048. but they return incorrect values when they are used by any additional processes 
  6049. that load another copy of the DLL.  The strupr function always returns a 
  6050. zero-length string, and stricmp and memicmp always return equal values for the 
  6051. two strings or blocks of memory. 
  6052.  
  6053. These functions do not exhibit this behavior when they are used in an .EXE 
  6054. file, and multiple copies of the .EXE are running.  What is wrong? 
  6055.  
  6056. Answer: 
  6057.  
  6058. Make sure you include 
  6059.  
  6060.   LIBRARY libname INITINSTANCE TERMINSTANCE
  6061. (where libname is the name of your library) in your .DEF file when you create 
  6062. the DLL, 
  6063.  
  6064.  
  6065. ΓòÉΓòÉΓòÉ 14.7. Why Are My Classes Initialized Multiple Times? ΓòÉΓòÉΓòÉ
  6066.  
  6067. Question: 
  6068.  
  6069. In my program, my class constructor is called each time my DLL is loaded 
  6070. (called by an executable file), but built-in types are initialized only once. 
  6071. For example: 
  6072.  
  6073.    class MYCL ....
  6074.  
  6075.    // global
  6076.    int  i1=4711;  // only on 1st loading
  6077.    MYCL i2(4711); // each time
  6078.  
  6079. I specified INITINSTANCE for the DLL.  Why does this happen? 
  6080.  
  6081. Answer: 
  6082.  
  6083. Because you are building a shared DLL, you should use INITGLOBAL, not 
  6084. INITINSTANCE.  When you specify INITINSTANCE, the library initialization 
  6085. routine is called for each process that uses the DLL.  When you use INITGLOBAL, 
  6086. the routine is only called once, when the DLL is loaded. The initialization is 
  6087. calling __ctordtorInit each time, and that is what is initializing your 
  6088. variable each time. 
  6089.  
  6090. Important  When you use INITGLOBAL, you must ensure that your DLL does not 
  6091. statically link to the VisualAge C++ runtime library. The VisualAge C++ runtime 
  6092. library must use INITINSTANCE to correctly initialize the runtime environment. 
  6093. Making the runtime library INITGLOBAL could lead to problems as described in 
  6094. Why Does My DLL End Abnormally When I Call It?. 
  6095.  
  6096.  
  6097. ΓòÉΓòÉΓòÉ 14.8. Why Is _DLL_InitTerm Causing Errors? ΓòÉΓòÉΓòÉ
  6098.  
  6099. Question: 
  6100.  
  6101. I have some questions about _DLL_InitTerm: 
  6102.  
  6103.    1. Why does my program trap when my _DLL_InitTerm calls printf? 
  6104.  
  6105.    2. The Programming Guide says to register a clean-up routine with 
  6106.       DosExitList if I require runtime calls and the runtime library is 
  6107.       dynamically linked. I'm using /Gd+ to dynamically link to the runtime, 
  6108.       but _DLL_InitTerm is called with ulFlag!=0.  Why? 
  6109.  
  6110.    3. The Programming Guide says that I need to call _CRT_Term only if the 
  6111.       runtime is statically linked. Does this also apply to __ctordtorTerm? 
  6112.  
  6113.  Answer: 
  6114.  
  6115.    1. Your program traps because _DLL_InitTerm has already terminated the 
  6116.       runtime environment, so you cannot call any runtime functions (like 
  6117.       printf). 
  6118.  
  6119.    2. Specifying TERMINSTANCE in your .DEF file tells OS/2 to call your code 
  6120.       when the DLL is terminated or unloaded. 
  6121.  
  6122.    3. You must always call __ctordtorTerm. 
  6123.  
  6124.  
  6125. ΓòÉΓòÉΓòÉ 14.9. Why Does a Destructor Exception End My Program? ΓòÉΓòÉΓòÉ
  6126.  
  6127. Question: 
  6128.  
  6129. If an exception is thrown in a constructor of a derived class, and the 
  6130. destructor of the base class also throws an exception, the program terminates 
  6131. immediately.  It is not even possible to do an output redirection in this case. 
  6132. Why? 
  6133.  
  6134. Answer: 
  6135.  
  6136. If a destructor that is called during exception handling itself throws an 
  6137. exception, the terminate function is called.  This is the way C++ handles 
  6138. double exceptions.  If you have not registered your own terminate routine (by 
  6139. using set_terminate), the program is aborted by default. 
  6140.  
  6141.  
  6142. ΓòÉΓòÉΓòÉ 14.10. Why Does a Destructor Corrupt the Object? ΓòÉΓòÉΓòÉ
  6143.  
  6144. Question: 
  6145.  
  6146. Why does a destructor corrupt the address of an object in the following 
  6147. example? 
  6148.  
  6149.    main(int argc, char *argv[])
  6150.    {
  6151.    SharedEventSemaphore *phev = new SharedEventSemaphore;
  6152.    phev->~SharedEventSemaphore();
  6153.    delete phev;
  6154.    return(0);
  6155.    }
  6156.  
  6157. Answer: 
  6158.  
  6159. According to ANSI, if you call a destructor twice for the same object, the 
  6160. behavior is undefined. 
  6161.  
  6162. In the example, you call the destructor once explicitly, and again as part of 
  6163. the delete processing.  Rewrite your program so that the destructor is called 
  6164. only once. 
  6165.  
  6166.  
  6167. ΓòÉΓòÉΓòÉ 14.11. Why Does Calling a Destructor Explicitly Cause Errors? ΓòÉΓòÉΓòÉ
  6168.  
  6169. Question: 
  6170.  
  6171. It appears that an explicit call to a destructor sometimes generates an error, 
  6172. and sometimes creates and destroys an object in one step. It never simply calls 
  6173. the destructor. When the destructor is called with a this-> statement, it works 
  6174. properly.  Why? 
  6175.  
  6176. Answer: 
  6177.  
  6178. You should not explicitly call destructors on objects. 
  6179.  
  6180. You can use a delete this; statement that calls the destructor, and then free 
  6181. the memory used by the object. 
  6182.  
  6183. Note:  This should only be done on dynamically allocated objects, and not in 
  6184. the destructor itself. 
  6185.  
  6186.  
  6187. ΓòÉΓòÉΓòÉ 14.12. Why Do I Get an Access Violation from the Runtime DLL? ΓòÉΓòÉΓòÉ
  6188.  
  6189. Question: 
  6190.  
  6191. My program runs fine until the very end of main, and then I get an access 
  6192. violation from the runtime library (DDE4MBS.DLL) after termination.  What 
  6193. causes this and how can I fix it? 
  6194.  
  6195. Answer: 
  6196.  
  6197. This behavior is typically caused by problems in the heap, such as writing to 
  6198. unallocated or freed memory. To find the problem: 
  6199.  
  6200.    1. Compile your program with the /Tm option to enable the debug versions of 
  6201.       the memory management functions. 
  6202.  
  6203.    2. Call _heapmin immediately before the end of main (or before the function 
  6204.       call that ends the program). If your problems are in a DLL, call _heapmin 
  6205.       in your _DLL_InitTerm function. 
  6206.  
  6207.  For more information about debugging your heap problems, see "Debugging Your 
  6208.  Heaps" in the Programming Guide. 
  6209.  
  6210.  
  6211. ΓòÉΓòÉΓòÉ 14.13. Why Can't I Open a File? ΓòÉΓòÉΓòÉ
  6212.  
  6213. Question: 
  6214.  
  6215. I can edit a file, but I cannot open it.  Why? 
  6216.  
  6217. Answer: 
  6218.  
  6219. Make sure that, if you store the file name in a constant string, you use a 
  6220. double backslash (\\) to represent a backslash (\). 
  6221.  
  6222. In C, a backslash is an escape character for inserting a character that you 
  6223. normally cannot type.  For example, because \t is the tab character, the 
  6224. following string: 
  6225.  
  6226.    char filename[] = "c:\directory\test.c"
  6227. has an actual value of 
  6228.  
  6229.    "c:directory     est.c"
  6230. To enter the file name correctly, convert the string to the following: 
  6231.  
  6232.    char filename[] = "c:\\directory\\test.c"
  6233.  
  6234.  
  6235. ΓòÉΓòÉΓòÉ 14.14. Why Does Optimization Cause My Program to Fail? ΓòÉΓòÉΓòÉ
  6236.  
  6237. Question: 
  6238.  
  6239. My program runs correctly when I create it with no optimization (/O-), but when 
  6240. I add optimization, it fails or traps.  Why? 
  6241.  
  6242. Answer: 
  6243.  
  6244. There could be a problem with the optimizer, but often, optimization reveals an 
  6245. underlying problem in your source code. 
  6246.  
  6247. For example, given the following code: 
  6248.  
  6249.    int bruce()
  6250.    {
  6251.       int dave[8];
  6252.       char stephan;
  6253.       int vij[6];
  6254. .
  6255. .
  6256. .
  6257.       vij[6] = 0;  // writes past end of array
  6258. .
  6259. .
  6260. .
  6261.       return dave[0];
  6262.    }
  6263.  
  6264. With no optimization (/O-), the statement vij[6] = 0; causes stephan to be 
  6265. overwritten.  This may or may not cause a runtime error, depending on how 
  6266. stephan is used after this statement. 
  6267.  
  6268. With optimization (/O+), the order of local variables on the stack changes, and 
  6269. the same statement causes dave[0] to be overwritten.  Because bruce actually 
  6270. returns this value, the problem is more likely to appear. 
  6271.  
  6272. Using the optimizer is a good way to further test your source code. 
  6273.  
  6274.  
  6275. ΓòÉΓòÉΓòÉ 14.15. Why Doesn't My Old C Code Work? ΓòÉΓòÉΓòÉ
  6276.  
  6277. Question: 
  6278.  
  6279. Some of the old C code that I have recently started to use does not seem to 
  6280. work correctly.  It seems that the parameters to a function are not being 
  6281. received correctly.  What is happening? 
  6282.  
  6283. Answer: 
  6284.  
  6285. Make sure that you do not mix functions defined under the old C standard (KRx) 
  6286. with functions defined under the ANSI standard. You can still define functions 
  6287. according to the KRx standard, but you cannot mix prototyped and unprototyped 
  6288. function definitions because of the difference in conversions. 
  6289.  
  6290. Note:  The C++ language requires that all functions have ANSI-style prototypes. 
  6291.  
  6292. There are important differences between the standards in the way that functions 
  6293. are defined and processed by the compiler.  Under the old standard, you define 
  6294. a function as follows: 
  6295.  
  6296.    int my_function( variable1, variable2, variable3 )
  6297.       int   variable1;
  6298.       float variable2;
  6299.       short variable3;
  6300.    {
  6301.        .
  6302.        :
  6303.    }
  6304.  
  6305. To make passing of parameters easier, variables of type char or short are 
  6306. converted to type int, and variables of type float are converted to double. 
  6307.  
  6308. The ANSI standard formally defines the function using a function prototype. 
  6309. With the prototype definition, you explicitly state the number and types of 
  6310. parameters each function receives.  The corresponding ANSI definition of the 
  6311. function above is: 
  6312.  
  6313.    /* function prototype */
  6314.    int my_function( int variable1, float variable2, short variable3 );
  6315.  
  6316.    /* function declaration */
  6317.    int my_function( int variable1, float variable2, short variable3 )
  6318.    {
  6319.       .
  6320.       :
  6321.    }
  6322.  
  6323. The ANSI standard also allows functions with a variable number of parameters, 
  6324. specified by following the fixed parameter list with an ellipsis (...).  Under 
  6325. this standard, fixed parameters of type char are converted to int, optional 
  6326. parameters of type char and short are converted to int, and optional parameters 
  6327. of type float are converted to double. 
  6328.  
  6329. It is best to convert the function definitions to the ANSI standard. 
  6330. Prototyping your functions as described in the ANSI standard makes your code 
  6331. more portable. Defining a full prototype also gives the compiler and optimizer 
  6332. complete information about the types and sizes of the parameters. As a result, 
  6333. the compiler does not have to perform conversions to widened types or generate 
  6334. eyecatcher instructions for the function. 
  6335.  
  6336.  
  6337. ΓòÉΓòÉΓòÉ 14.16. Why Does One Function Alter Information from Another? ΓòÉΓòÉΓòÉ
  6338.  
  6339. Question: 
  6340.  
  6341. Why is information that I generate by calling one function being altered after 
  6342. I call a second function? 
  6343.  
  6344. Answer: 
  6345.  
  6346. You may be returning the address of a local variable.  If you call a function 
  6347. from within your program, do not rely on any of its local data after it 
  6348. returns.  For example, given the following function: 
  6349.  
  6350.    void a( void )
  6351.    {
  6352.       int *x;
  6353.       x = b();            /* x points to a variable local to b() */
  6354.        .
  6355.        :
  6356.       c();
  6357.        .
  6358.        :
  6359.       printf( "%p", &x ); /* try to access x after c() has been called */
  6360.    }
  6361. The int variable that x points to may not exist after function c is called, 
  6362. causing an error on the printf statement. 
  6363.  
  6364. Local data is stored temporarily on the stack, which may be used by the 
  6365. operating system.  If the operating system or another function needs some of 
  6366. the stack space, it is likely that the original data will be overwritten.  The 
  6367. cause of this problem can be difficult to isolate, because the demand for stack 
  6368. space is random and unpredictable. 
  6369.  
  6370. To avoid this problem, declare the variables in the calling function or as 
  6371. global variables. 
  6372.  
  6373.  
  6374. ΓòÉΓòÉΓòÉ 14.17. Why Do My Window Procedures End Abnormally? ΓòÉΓòÉΓòÉ
  6375.  
  6376. Question: 
  6377.  
  6378. Why do my window procedures end abnormally? 
  6379.  
  6380. Answer: 
  6381.  
  6382. Make sure that you prototype your window procedures to use the _System calling 
  6383. convention.  You can do this by including the appropriate system header file 
  6384. from the Toolkit.  You should also ensure your window procedures include the 
  6385. EXPENTRY keyword, as described in the Toolkit documentation. 
  6386.  
  6387. The VisualAge C++ compiler uses the _Optlink calling convention by default, 
  6388. which is not compatible with the _System calling convention used by the OS/2 
  6389. system to call window procedures.  OS/2 APIs use _System linkage; _Optlink is 
  6390. used for VisualAge C++ library functions. 
  6391.  
  6392. It is easiest to use the _System keyword to give individual functions _System 
  6393. linkage. 
  6394.  
  6395. For more information on the calling conventions, see the Programming Guide. 
  6396.  
  6397.  
  6398. ΓòÉΓòÉΓòÉ 14.18. Why Does Printing a _Seg16 Pointer Trap? ΓòÉΓòÉΓòÉ
  6399.  
  6400. Question: 
  6401.  
  6402. I have a char * _Seg16 variable in my application.  When I use it with string 
  6403. functions like strupr, it works fine.  However, when I try to print it with 
  6404. printf, my program traps. Why? 
  6405.  
  6406. Answer: 
  6407.  
  6408. VisualAge C++ converts _Seg16 pointers to flat pointers depending on the 
  6409. function prototype. The string functions always take char * variables, so the 
  6410. conversion is done for you. However, because printf has a variable argument 
  6411. list and can take any type, there is no prototype to convert the pointer. 
  6412.  
  6413. To force the conversion, explicitly cast the _Seg16 pointer to the type you 
  6414. want to print.  For example, to print char * _Seg16 myptr as a string, code: 
  6415.  
  6416.    printf("%s\n", (char *)myptr);
  6417.  
  6418.  
  6419. ΓòÉΓòÉΓòÉ 14.19. What Is __EDCThunkProlog and Why Does It Trap? ΓòÉΓòÉΓòÉ
  6420.  
  6421. Question: 
  6422.  
  6423. I have an application that uses both 16-bit and 32-bit modules. When I run it, 
  6424. it traps in __EDCThunkProlog. What is this function, and why does it cause the 
  6425. trap? 
  6426.  
  6427. Answer: 
  6428.  
  6429. __EDCThunkProlog is part of the VisualAge C++ runtime and is called in the 
  6430. prolog of any 32-bit function that calls a 16-bit function. It ensures that the 
  6431. 32-bit function's parameters and local variables, as well as the 16-bit 
  6432. function's parameters and the 16-bit stack, do not cross a 64K boundary on the 
  6433. stack. If it traps, it usually indicates that you have insufficient stack to 
  6434. run the 16-bit function correctly. 
  6435.  
  6436. Check the value specified in your #pragma stack16 statement (the default value 
  6437. is 4K). This value specifies how much stack __EDCThunkProlog reserves from your 
  6438. program's stack for your 16-bit functions. If you set this value too low, your 
  6439. 16-bit functions may not have enough stack to run correctly. 
  6440.  
  6441. Because the 16-bit stack is allocated from your program's stack, you may also 
  6442. need to increase your program's stack size. 
  6443.  
  6444.  
  6445. ΓòÉΓòÉΓòÉ 14.20. Why Does printf Work Incorrectly? ΓòÉΓòÉΓòÉ
  6446.  
  6447. Question: 
  6448.  
  6449. When I call printf, why does it print the wrong thing or cause my program to 
  6450. end abnormally? 
  6451.  
  6452. Answer: 
  6453.  
  6454. Make sure that the parameters you list in your format string match the 
  6455. parameters you are actually passing to the function. 
  6456.  
  6457. Possible problems include: 
  6458.  
  6459.      Passing a parameter of a different type than you have declared. 
  6460.  
  6461.       For example, the printf function in the following code fragment expects a 
  6462.       string variable, but is passed a variable of type int: 
  6463.  
  6464.                int a;
  6465.                printf( "%s", a );
  6466.       The correct printf call should read: 
  6467.  
  6468.                printf( "%d", a );
  6469.  
  6470.      Passing a parameter of a different size than you have declared. 
  6471.  
  6472.       For example, the format string in the following code fragment indicates 
  6473.       that three variables of type int are expected, but the variables passed 
  6474.       are of type long, int, and short: 
  6475.  
  6476.                long  l;
  6477.                int   i;
  6478.                short s;
  6479.                printf( "%d %d %d", l, i, s );
  6480.       Because it reads in the bytes from storage, this call could have 
  6481.       unexpected results.  The correct printf call should read: 
  6482.  
  6483.                printf( "%ld %d %hd", l, i, s );
  6484.  
  6485.      Passing a parameter by reference instead of by value. 
  6486.  
  6487.       For example, in the following code fragment, the printf function expects 
  6488.       a variable of type int, but is passed the address of an int variable: 
  6489.  
  6490.                int a;
  6491.                printf( "%d", &a );
  6492.       The correct printf call should read: 
  6493.  
  6494.                printf( "%d", a );
  6495.  
  6496.  
  6497. ΓòÉΓòÉΓòÉ 14.21. Why Doesn't printf Output Display? ΓòÉΓòÉΓòÉ
  6498.  
  6499. Question: 
  6500.  
  6501. How do I display a printf prompt on the screen before the program waits for an 
  6502. answer from scanf? 
  6503.  
  6504. Answer: 
  6505.  
  6506. Because printf is line-buffered, its output appears only after a new-line 
  6507. character or when the buffer is flushed. You can do one of three things: 
  6508.  
  6509.    1. Include a new-line character at the end of every printf statement (for 
  6510.       example, 
  6511.  
  6512.                printf("This will display immediately.\n");
  6513.  
  6514.    2. Put a fflush(stdout); statement after any output to stdout that precedes 
  6515.       input from stdin.  It is usually a good idea to fflush at every point 
  6516.       where you switch between stdout and stdin. 
  6517.  
  6518.    3. Change the buffering mode to unbuffered by calling setbuf or setvbuf at 
  6519.       the beginning of your program  after any fopen or freopen statements, but 
  6520.       before any output to stdout: 
  6521.  
  6522.                setbuf(stdout, NULL);
  6523.                setvbuf(stdout, NULL, _IONBF, 0);
  6524.  
  6525.       Note that this last solution can make your program run more slowly. 
  6526.  
  6527.  In C++ programs, output from cout and cin is automatically displayed. 
  6528.  
  6529.  
  6530. ΓòÉΓòÉΓòÉ 14.22. Why Does scanf Behave Unexpectedly? ΓòÉΓòÉΓòÉ
  6531.  
  6532. Question: 
  6533.  
  6534. Why doesn't scanf behave as I expect it to? Sometimes it does not wait for 
  6535. input, does not convert all input, or goes into an infinite loop. 
  6536.  
  6537. Answer: 
  6538.  
  6539. scanf works on streams of characters, not lines of input.  It reads the 
  6540. characters from the specified input stream and formats them according to the 
  6541. conversion rules that you specify. 
  6542.  
  6543. Here are some guidelines to follow when reading character input: 
  6544.  
  6545.      Use scanf for machine-generated input only. 
  6546.  
  6547.      Use a combination of the fgets and sscanf functions for user input. 
  6548.  
  6549.       Note:  Do not substitute the gets function for fgets.  If you use gets, 
  6550.       it is possible to overwrite the character array used to store the input, 
  6551.       and cause memory problems.  With fgets, you control the number of 
  6552.       characters that the user can input. 
  6553.  
  6554.      Check the return count from the scanf functions to see how many fields 
  6555.       were processed. 
  6556.  
  6557.      Read the descriptions of the various formats carefully.  Some formats 
  6558.       skip leading white space (for example, %d and %f) and others do not (for 
  6559.       example, %c). Remember to include the new-line character. 
  6560.  
  6561.      Remember that the scanf conversion characters are different from the 
  6562.       printf conversion characters. 
  6563.  
  6564.  The following examples show how scanf works and illustrate some possible 
  6565.  problems.  All of the examples assume that the input is coming from the user. 
  6566.  
  6567.      The following statement reads an integer from the user: 
  6568.  
  6569.                scanf( "%d", &myint )
  6570.       The program waits for you to enter a string of characters.  If you enter: 
  6571.  
  6572.                25\n
  6573.       the function reads the digits 2 and 5 and stops when it reads the first 
  6574.       non-decimal digit, the new-line character (\n). 
  6575.  
  6576.      If you instead enter: 
  6577.  
  6578.                13 74\n
  6579.       the function reads the digits 1 and 3 and stops when it reads the blank, 
  6580.       which is the first non-decimal digit.  The %d conversion skips any 
  6581.       leading whitespace characters such as a blank, the tab character (\t), 
  6582.       and the new-line character. 
  6583.  
  6584.       The 74\n remains in the input stream.  Because the input stream is not 
  6585.       empty, the next call to scanf will read directly from the stream and will 
  6586.       not wait for user input. 
  6587.  
  6588.      It is possible to enter an infinite loop with a combination of scanf and 
  6589.       unexpected user input.  Here is an example: 
  6590.  
  6591.       The following code fragment reads a set of numbers until a negative 
  6592.       number is entered. 
  6593.  
  6594.                answer = 0;
  6595.                i = 0;
  6596.                while (answer >= 0) {
  6597.                   scanf( "%d" , &answer );
  6598.                   myarray[i] = answer;
  6599.                   i++;
  6600.                }
  6601.       If you enter: 
  6602.  
  6603.                123XYZ\n
  6604.       the first call to scanf reads 123 as a valid integer and stops at the X, 
  6605.       leaving XYZ\n in the input stream.  Because the input stream is not 
  6606.       empty, the next call to scanf tries to read an integer from the stream. 
  6607.       Because X is not an integer, scanf never progresses through the input 
  6608.       stream, and you do not have the opportunity to enter new data.  The 
  6609.       result is an infinite loop. 
  6610.  
  6611.  For more information on scanf, see the C Library Reference 
  6612.  
  6613.  
  6614. ΓòÉΓòÉΓòÉ 14.23. Why Do Library Functions and APIs Not Work? ΓòÉΓòÉΓòÉ
  6615.  
  6616. Question: 
  6617.  
  6618. When I call a library function or OS/2 API, it does not work or it causes my 
  6619. program to end abnormally.  Why? 
  6620.  
  6621. Answer: 
  6622.  
  6623. Make sure that you use the #include preprocessor directive to include the 
  6624. header file that contains the prototype statement for the library function or 
  6625. API. 
  6626.  
  6627. Also make sure that you are using the correct calling convention.  Use _Optlink 
  6628. to call library functions.  Use _System to call OS/2 APIs.  Include the 
  6629. appropriate header files to ensure that the functions and APIs you use are 
  6630. prototyped correctly. If you change the default calling convention to _System 
  6631. (with the /Ms compiler option), you must include header files for all library 
  6632. functions you use. 
  6633.  
  6634. Note:  Use the /Wpro compiler option to warn about unprototyped functions. This 
  6635. option is set by default. 
  6636.  
  6637.  
  6638. ΓòÉΓòÉΓòÉ 14.24. Why Do Macros with Increment Operators Work Incorrectly? ΓòÉΓòÉΓòÉ
  6639.  
  6640. Question: 
  6641.  
  6642. A statement in my C program behaves strangely.  It deals with a combination of 
  6643. a macro and increment operators.  What is the problem? 
  6644.  
  6645. Answer: 
  6646.  
  6647. When you use a macro, make sure that you know how it will be expanded.  If you 
  6648. define a macro that repeats the input argument, problems might occur in 
  6649. combination with increment (++) and decrement (--) operators. 
  6650.  
  6651. As an example, given the following macro toupp: 
  6652.  
  6653. #define toupp(c) islower(c) ? _toupper(c) : (c)
  6654. The following statement is intended to copy every character of source into 
  6655. dest: 
  6656.  
  6657. while (*dest++ = toupp(*source++));
  6658.  
  6659. After the toupp macro is expanded, the actual statement that is executed is: 
  6660.  
  6661. while (*dest++ = islower(*source++) ? _toupper(*source++) : (*source++));
  6662. This increments source twice each time the loop is done, an unintended result. 
  6663.  
  6664.  
  6665. ΓòÉΓòÉΓòÉ 14.25. Why Doesn't My Macro Resolve Correctly? ΓòÉΓòÉΓòÉ
  6666.  
  6667. I have defined a macro, but it does not always produce the correct answer. 
  6668. Why? 
  6669.  
  6670. Answer: 
  6671.  
  6672. If your macro expands to an expression, make sure that you use parentheses when 
  6673. you define the macro.  You may get unexpected results if you use the macro in 
  6674. the same statement as other operators.  The precedence rules of the other 
  6675. operators may interfere with the macro definition. 
  6676.  
  6677. For example, given the following code: 
  6678.  
  6679.    #define DOUBLE(x) x+x
  6680.  
  6681.    y = DOUBLE(2)+1;      /* assigns 5 to y */
  6682.    z = DOUBLE(2)*3;      /* assigns 8 to z */
  6683. The last statement evaluates to 8 rather than to 12 because it expands to 
  6684. z = 2 + 2 * 3.  To prevent this problem, use parentheses when you define a 
  6685. macro.  For example, the above macro would give the expected results if it were 
  6686. defined as: 
  6687.  
  6688.    #define DOUBLE(x) ((x) + (x))
  6689.  
  6690.  
  6691. ΓòÉΓòÉΓòÉ 14.26. Why Don't My Threads Work Correctly? ΓòÉΓòÉΓòÉ
  6692.  
  6693. Question: 
  6694.  
  6695. In my program, why do threads other than thread one not work correctly? 
  6696.  
  6697. Answer: 
  6698.  
  6699. Ensure that: 
  6700.  
  6701.      You use the /Gs- compiler option to generate stack probes (which is the 
  6702.       default). 
  6703.  
  6704.      You use the /Gm compiler option to link with the multithread libraries. 
  6705.  
  6706.      If you started a thread with the DosCreateThread API, you call _endthread 
  6707.       to end the thread and perform the necessary termination actions.  If you 
  6708.       used _beginthread to start the thread, _endthread is called implicitly 
  6709.       when the thread ends. 
  6710.  
  6711.  
  6712. ΓòÉΓòÉΓòÉ 14.27. Why Do My Statements Have No Effect? ΓòÉΓòÉΓòÉ
  6713.  
  6714. Question: 
  6715.  
  6716. I have a statement or a group of statements that does not seem to do anything. 
  6717.  
  6718. Answer: 
  6719.  
  6720. Make sure that you are not missing an end to a comment (*/).  In the following 
  6721. example, an ending comment is omitted, causing a statement to be skipped during 
  6722. the compilation: 
  6723.  
  6724.    /* This comment has an incorrect terminator *\
  6725.    ...
  6726.    here = (is > some) ? important : code;
  6727.    ...
  6728.    /* This comment "accidentally" terminates the previous comment */
  6729.    code = begins + working / fine->again;
  6730.  
  6731. A similar problem can occur with macro definitions. For example: 
  6732.  
  6733.    #define something(important)   // An important macro  \
  6734.        this->gets(ignored)                               \
  6735.        this->does(too)
  6736.  
  6737. Because of the line continuation character (\), the lines are spliced together 
  6738. before the comment is processed. As a result, the second and third lines of the 
  6739. macro become part of the comment. For this reason, avoid using // comments in 
  6740. multi-line macro definitions. 
  6741.  
  6742. The syntax highlighting in the VisualAge Editor can help you find this type of 
  6743. problem. 
  6744.  
  6745.  
  6746. ΓòÉΓòÉΓòÉ 14.28. Why Do Increment Operators Produce Unexpected Results? ΓòÉΓòÉΓòÉ
  6747.  
  6748. Question: 
  6749.  
  6750. A section of my code is not producing the expected results.  The statements use 
  6751. the ++ and -- operators. 
  6752.  
  6753. Answer: 
  6754.  
  6755. Make sure that your statements do not depend on side effects of the ++ and -- 
  6756. operators. For example, because the result of the following statement depends 
  6757. on when the ++ operator is evaluated and when the assignment is done, it may 
  6758. produce inconsistent results: 
  6759.  
  6760.      s[i++] = t[i];
  6761.  
  6762. The order of these operations depends on the compiler being used and possibly 
  6763. on the optimization requirements.  One compiler may compute the source address 
  6764. first (the right-hand side of the statement), while another may compute the 
  6765. target address first (the left-hand side). 
  6766.  
  6767. The same problem often occurs with function parameters. For example, given : 
  6768.  
  6769.    printf("%d %d %d\n", i++, i++, i++);
  6770.  
  6771. The parameters can be evaluated and passed in any order, so any code that 
  6772. depends on a particular order of evaluation will most likely fail. 
  6773.  
  6774. To produce consistent results, if you use the ++ or -- operators on a variable 
  6775. within an expression, make sure that the variable appears only once within the 
  6776. expression. 
  6777.  
  6778.  
  6779. ΓòÉΓòÉΓòÉ 14.29. Why Do I Get a SYS2070 Error? ΓòÉΓòÉΓòÉ
  6780.  
  6781. Questions: 
  6782.  
  6783. When I try to run my program, it does not run and the operating system 
  6784. generates a SYS2070 error.  Why? 
  6785.  
  6786. Answer: 
  6787.  
  6788. The program could not access an external reference.  The linker may not have 
  6789. been able to resolve all of the external references in your program. 
  6790.  
  6791. Make sure you use the /NOI linker option to preserve the case of external names 
  6792. when you link your program. This is the default. Do not use the /IGNORECASE 
  6793. linker option. 
  6794.  
  6795. See Why Do I Get Unresolved External Errors? for different causes of unresolved 
  6796. external references. 
  6797.  
  6798.  
  6799. ΓòÉΓòÉΓòÉ 14.30. Why Does My PM Application Disappear? ΓòÉΓòÉΓòÉ
  6800.  
  6801. Question: 
  6802.  
  6803. Why does my PM application disappear without generating any messages? 
  6804.  
  6805. Answer: 
  6806.  
  6807. An exception has been generated and handled by an exception handler that has 
  6808. terminated the program.  A machine-state dump is sent to stderr, but because 
  6809. the PM interface directs the stderr stream to a null output device, you do not 
  6810. see the error messages. 
  6811.  
  6812. Use the _set_crt_msg_handle function to redirect stderr to a file.  You will 
  6813. then be able to see the runtime messages, including exception messages and 
  6814. machine-state information.  Alternatively, you can write your own exception 
  6815. handler to intercept the exception and handle it however you want. 
  6816.  
  6817.  
  6818. ΓòÉΓòÉΓòÉ 14.31. Why Does My Program Work Incorrectly and Inconsistently? ΓòÉΓòÉΓòÉ
  6819.  
  6820. Question: 
  6821.  
  6822. My program does not work properly.  Sometimes adding or removing statements 
  6823. changes how the program terminates or may even solve the problem temporarily. 
  6824. Using a debugger changes the symptoms. What is the problem? 
  6825.  
  6826. Answer: 
  6827.  
  6828. There are several possible solutions to your problem: 
  6829.  
  6830.      Make sure that you are calling functions correctly. 
  6831.  
  6832.       If a parameter is missing, the program may replace the parameter with 
  6833.       arbitrary data to complete the function call.  The VisualAge C++ compiler 
  6834.       checks for missing parameters if you define your functions using function 
  6835.       prototypes. 
  6836.  
  6837.       Note:  Use the /Wpro compiler option to warn about missing prototypes. 
  6838.       This option is set by default. 
  6839.  
  6840.       If the incorrect type of parameter is used, the function misreads the 
  6841.       parameter list. 
  6842.  
  6843.      Make sure that there is not a semicolon at the end of a for, do, or while 
  6844.       statement. 
  6845.  
  6846.       When there is only one statement in the body of a loop, it is common to 
  6847.       code the loop in the following style: 
  6848.  
  6849.                for (... ; ... ; ...)
  6850.                   statement;
  6851.  
  6852.       It is also a common error to accidentally add a semicolon to the end of 
  6853.       the first line.  For example: 
  6854.  
  6855.                for (i = 0; i < SOMENUMBER; i++);
  6856.                   d[i] = 0;
  6857.  
  6858.       The semicolon at the end of the for statement ends the body of the loop. 
  6859.       The second line, which is the intended body of the loop, is executed only 
  6860.       once. 
  6861.  
  6862.       To catch problems like this, use the /Weff compiler diagnostic option to 
  6863.       locate code that has no effect. 
  6864.  
  6865.       It is also a good idea to enclose the loop statements in braces ({ }). 
  6866.  
  6867.      Ensure that strings are terminated by a null byte. 
  6868.  
  6869.       When you initialize a string, you must include space for the null byte. 
  6870.       For example, 
  6871.  
  6872.                char str1[3] = "ab"   /* allocates 'a', 'b', '\0' */
  6873.                char str2[3] = "abc"  /* allocates 'a', 'b', 'c'; no '\0' */
  6874.       When you use a string, do not overwrite the null byte. 
  6875.  
  6876.       Because the null byte is used to indicate where the string terminates, a 
  6877.       string without the null byte can cause memory problems. If you use a 
  6878.       function such as strcpy on a string without the terminating character, 
  6879.       portions of the memory following the string may be overwritten, causing 
  6880.       problems with the current program or programs that are using that memory 
  6881.       space.  Problems could appear immediately or only after the program is 
  6882.       run several times. 
  6883.  
  6884.       Note:  Use debug memory management (/Tm option) to help find memory 
  6885.       corruption problems. 
  6886.  
  6887.      Check your function return types. 
  6888.  
  6889.       The compiler assumes that a function declared without a return type 
  6890.       returns an int.  This could cause problems if your program is expecting a 
  6891.       different return type.  Prototype your functions to avoid this problem. 
  6892.  
  6893.      If you declare an array in one file and reference it in another file 
  6894.       using extern, make sure that the extern statement has the same form as 
  6895.       the declaration statement. 
  6896.  
  6897.       For example, the following declarations are not equivalent: 
  6898.  
  6899.                 /* File 1: Global Data definitions */
  6900.                 char x[100];
  6901.  
  6902.                 /* File 2: Using the global data */
  6903.                 extern char *x;
  6904.  
  6905.       In the second file, the compiler generates code that assumes that the 
  6906.       address at x contains the address of the actual array. The correct 
  6907.       definition in File 2 is: 
  6908.  
  6909.                 /* File 2: Using the global data */
  6910.                 extern char x[];
  6911.  
  6912.      Ensure that you are not referencing beyond the last element of an array. 
  6913.  
  6914.       The first entry of an array is found at index 0 (for example, array[0]). 
  6915.       If you declare an array of size n, the array starts at element 0 and ends 
  6916.       at element n-1. 
  6917.  
  6918.       The following code fragment references beyond the last array element: 
  6919.  
  6920.                char stuff[10];
  6921.                int  i;
  6922.                .
  6923.                .
  6924.                .
  6925.                for (i = 0; i <= 10; i++) {    /* test should have been i < 10 */
  6926.                   stuff[i] = ' ';
  6927.                }
  6928.  
  6929.       Referencing beyond the last element in the array may overwrite memory 
  6930.       locations and cause problems with variable data, functions, or the entire 
  6931.       program. 
  6932.  
  6933.      Ensure you use the malloc and free library functions correctly. 
  6934.  
  6935.       The malloc function returns a pointer to an area of memory that is at 
  6936.       least as large as you request.  The free function releases memory 
  6937.       previously allocated by malloc. 
  6938.  
  6939.       Make sure that only pointers returned by the malloc function are passed 
  6940.       to the free function.  To keep track of what memory is available, malloc 
  6941.       stores information in a section of memory adjacent to the pointer that it 
  6942.       returns.  The free function uses this information to return the allocated 
  6943.       space to the list of available memory. 
  6944.  
  6945.       The free function does not check the pointer that it receives.  If free 
  6946.       receives a pointer that was not set by malloc, memory problems can occur. 
  6947.       For example, other programs may get unauthorized access to your data 
  6948.       areas, program code, or parts of the operating system. 
  6949.  
  6950.       Also make sure that you do not use memory outside of the memory allocated 
  6951.       by malloc. 
  6952.  
  6953.       To help you find possible problems with these functions, use the debug 
  6954.       memory management functions. Memory management is described in the 
  6955.       Programming Guide; for descriptions of individual functions, see the C 
  6956.       Library Reference 
  6957.  
  6958.  
  6959. ΓòÉΓòÉΓòÉ 14.32. Where Is the Message File? ΓòÉΓòÉΓòÉ
  6960.  
  6961. Question: 
  6962.  
  6963. When I run my application on another machine, I get the message "Message file 
  6964. not found".  Why? 
  6965.  
  6966. Answer: 
  6967.  
  6968. The VisualAge C++ runtime cannot find the message file that contains the 
  6969. runtime messages it needs. 
  6970.  
  6971. To solve this problem, do one of the following: 
  6972.  
  6973.      Copy the runtime message files you need to a directory in the DPATH of 
  6974.       the machine running the program.  The runtime message files are: 
  6975.  
  6976.       DDE4.MSG             C runtime library and I/O Stream and Complex class 
  6977.                            libraries. 
  6978.       IBMCRERR.MSG         Regular expressions. 
  6979.       DDE4C01E.MSG         Collection class libraries. 
  6980.       CPPOOC3U.MSG         User Interface class libraries. 
  6981.       DAXCLS.MSG           Database Access class libraries. 
  6982.  
  6983.      Use MSGBIND to bind the messages to your application's own runtime.  (You 
  6984.       must do this if you will be shipping your application to other people.) 
  6985.  
  6986.  For more information about how to use MSGBIND and what messages you need, see 
  6987.  the section on MSGBIND in the User's Guide. 
  6988.  
  6989.  
  6990. ΓòÉΓòÉΓòÉ 15. Debugging with the Debugger ΓòÉΓòÉΓòÉ
  6991.  
  6992. This section answers questions you may have while debugging your program with 
  6993. the debugger. 
  6994.  
  6995.      When Should I Use Synchronous and Asynchronous Debugging Modes? 
  6996.      Can I Debug 16-Bit Code? 
  6997.      Can I Debug Optimized Code? 
  6998.      Why Do I Get A DosStartSession Error? 
  6999.      How Does the Debugger Locate Source Files? 
  7000.      Why Can't the Debugger Find the Source File? 
  7001.      How Do I Debug A DLL Called by A REXX Program? 
  7002.      How Do I Debug a WorkPlace Shell DLL? 
  7003.      Why Can't I Typecast in the Monitor Expression Dialog? 
  7004.      How Do I Debug SQC Files? 
  7005.      Can I Run Performance Analyzer and the Debugger at the Same Time? 
  7006.  
  7007.  
  7008. ΓòÉΓòÉΓòÉ 15.1. When Should I Use Synchronous and Asynchronous Debugging Modes? ΓòÉΓòÉΓòÉ
  7009.  
  7010. Question: 
  7011.  
  7012. When should I run the debugger in synchronous mode, and when should I run it in 
  7013. asynchronous mode?  What is the difference? 
  7014.  
  7015. Answer: 
  7016.  
  7017. The difference between the two modes appears when the program you are debugging 
  7018. is stopped, such as at a breakpoint. In asynchronous mode, you can interact 
  7019. with non-debugger applications, such as an editor.  This is the usual mode for 
  7020. running the debugger. 
  7021.  
  7022. However, the debugger then interferes with the normal flow of messages to the 
  7023. program you are debugging.  The debugger responds to the PM messages of your 
  7024. program in a default manner, so that it does not lock the PM input queue. 
  7025.  
  7026. If you need to handle your program's messages in a specific way (other than the 
  7027. default), or if the order of input messages is important, run in synchronous 
  7028. mode. For example, if your application uses dynamic data exchange (DDE), you 
  7029. should run in synchronous mode. You will not be able to use other applications 
  7030. while the debugger is running, but you will capture all the messages to and 
  7031. from your application. 
  7032.  
  7033.  
  7034. ΓòÉΓòÉΓòÉ 15.2. Can I Debug 16-Bit Code? ΓòÉΓòÉΓòÉ
  7035.  
  7036. Question: 
  7037.  
  7038. Can I use the VisualAge C++ debugger to debug my 16-bit code? 
  7039.  
  7040. Answer: 
  7041.  
  7042. The VisualAge C++ debugger recognizes both IBM and Codeview debugger data, so 
  7043. you can use it to debug both the 32-bit and 16-bit parts of your application. 
  7044.  
  7045.  
  7046. ΓòÉΓòÉΓòÉ 15.3. Can I Debug Optimized Code? ΓòÉΓòÉΓòÉ
  7047.  
  7048. Question: 
  7049.  
  7050. Can I debug code that has been optimized? 
  7051.  
  7052. Answer: 
  7053.  
  7054. Yes, but you will not be able to use all debugger features. Because some 
  7055. variables are placed in registers, you cannot monitor variables accurately. The 
  7056. register and storage windows are both accurate. 
  7057.  
  7058. To debug optimized code most efficiently, turn off the instruction scheduling 
  7059. optimization (/Os-) when you compile, and use a mixed source and assembly view 
  7060. to navigate through your code while using the register and storage windows. 
  7061.  
  7062.  
  7063. ΓòÉΓòÉΓòÉ 15.4. Why Do I Get A DosStartSession Error? ΓòÉΓòÉΓòÉ
  7064.  
  7065. Question: 
  7066.  
  7067. Why do I get a DosStartSession error when I start the debugger? 
  7068.  
  7069. Answer: 
  7070.  
  7071. The debugger starts your program using DosStartSession in trace mode. 
  7072. DosStartSession does much more checking when trace mode is on, causing some 
  7073. programs that seem to run correctly outside the debugger to fail under the 
  7074. debugger. The most common errors and causes are: 
  7075.  
  7076.  Return Code Cause 
  7077.  
  7078.   2        A DLL referenced by the application could not be found. 
  7079.  
  7080.   127      A function in a DLL could not be found (usually because of a missing 
  7081.            EXPORTS line in a .DEF file). 
  7082.  
  7083.   182      An ordinal is invalid (usually caused by picking up a different 
  7084.            level of the DLL than was used to create the import library you 
  7085.            linked to). 
  7086.  
  7087.  
  7088. ΓòÉΓòÉΓòÉ 15.5. How Does the Debugger Locate Source Files? ΓòÉΓòÉΓòÉ
  7089.  
  7090. Question: 
  7091.  
  7092. How does the debugger locate the source files? 
  7093.  
  7094. Answer: 
  7095.  
  7096. The debugger looks in the following places in the following order: 
  7097.  
  7098.    1. The name stored in the .EXE file (from the icc command line) 
  7099.    2. The directory containing the .EXE file 
  7100.    3. The PMDPATH environment variable 
  7101.    4. The current directory 
  7102.  
  7103.  
  7104. ΓòÉΓòÉΓòÉ 15.6. Why Can't the Debugger Find the Source File? ΓòÉΓòÉΓòÉ
  7105.  
  7106. Question: 
  7107.  
  7108. Why is the debugger unable to find a source file unless the path and file name 
  7109. are given in the Source Filename Incorrect dialog box? 
  7110.  
  7111. Answer: 
  7112.  
  7113. If you recompiled any of the code since the last time you used the debugger, it 
  7114. may be unable to locate the source file. 
  7115.  
  7116. If you compile in one directory and run in another, you should either use the 
  7117. PMDPATH environment variable or put a qualified path on the ICC compile line, 
  7118. For example, specify: 
  7119.  
  7120.    icc ./test.c
  7121. rather than: 
  7122.  
  7123.    ICC test.c
  7124.  
  7125. If your ICC command lines are created by the WorkFrame MAKEMAKE utility, check 
  7126. the make file to see if it is using .\source or source.c on the command line. 
  7127.  
  7128.  
  7129. ΓòÉΓòÉΓòÉ 15.7. How Do I Debug A DLL Called by A REXX Program? ΓòÉΓòÉΓòÉ
  7130.  
  7131. Question: 
  7132.  
  7133. How do I debug a DLL called by a REXX program? 
  7134.  
  7135. Answer: 
  7136.  
  7137.    1. Start the debugger with the command: 
  7138.  
  7139.                IPMD CMD.EXE /C your Rexx.cmd
  7140.  
  7141.    2. When the debugger displays the code for CMD.EXE, set a load-type 
  7142.       breakpoint to stop at the DLL. 
  7143.  
  7144.    3. Select Run from the menu. 
  7145.  
  7146.    4. At the pop-up indicating your DLL has loaded, open the desired parts and 
  7147.       set breakpoints. Use deferred breakpoints to have them set in your next 
  7148.       debugger session. 
  7149.  
  7150.    5. Select Run again. 
  7151.  
  7152.  
  7153. ΓòÉΓòÉΓòÉ 15.8. How Do I Debug a WorkPlace Shell DLL? ΓòÉΓòÉΓòÉ
  7154.  
  7155. Question: 
  7156.  
  7157. How do I debug a WorkPlace Shell DLL? 
  7158.  
  7159. Answer: 
  7160.  
  7161.    1. In your CONFIG.SYS file, add the following line: 
  7162.  
  7163.               SET RUNWORKPLACE=C:\OS2\CMD.EXE
  7164.  
  7165.    2. Reboot your machine. 
  7166.  
  7167.    3. In the initial OS/2 window, enter IPMD C:\os2\pmshell 
  7168.  
  7169.    4. Set a Load-type breakpoint for the DLL containing the WPS program. 
  7170.  
  7171.  
  7172. ΓòÉΓòÉΓòÉ 15.9. Why Can't I Typecast in the Monitor Expression Dialog? ΓòÉΓòÉΓòÉ
  7173.  
  7174. Question: 
  7175.  
  7176. Why doesn't my typecasting work in the Monitor Expression Dialog? 
  7177.  
  7178. Answer: 
  7179.  
  7180. Complex user typecasting is only supported if you build your application with 
  7181. the C++ runtime library. If you are compiling a C program, use the /Tdp 
  7182. compiler option to compile it as a C++ program and include the C++ runtime 
  7183. support. 
  7184.  
  7185.  
  7186. ΓòÉΓòÉΓòÉ 15.10. How Do I Debug SQC Files? ΓòÉΓòÉΓòÉ
  7187.  
  7188. Question: 
  7189.  
  7190. I am trying to debug some SQC files, but the debugger seems to get lost in 
  7191. them.  Is there a special option that I need to use? 
  7192.  
  7193. Answer: 
  7194.  
  7195. The problem originates in the SQL precompiler. To assist with error messages 
  7196. when you're compiling your .SQC file, the precompiler brackets all the code it 
  7197. adds to the .C with #line macros.  Unfortunately, the #line macros can cause 
  7198. debuggers to get confused. 
  7199.  
  7200. To avoid this problem, tell the precompiler not to create the #line macros. You 
  7201. can do this by modifying the option in your project's SQLPREP action, or by 
  7202. setting the /# option in your SQLPREP statement. (If you're using SDK/2, add 
  7203. NOLINEMACRO to your DB2 PREP statement instead.) 
  7204.  
  7205.  
  7206. ΓòÉΓòÉΓòÉ 16. Tracing with Performance Analyzer ΓòÉΓòÉΓòÉ
  7207.  
  7208. This section answers questions you may have about using the Performance 
  7209. Analyzer. 
  7210.  
  7211. Note:  In previous versions of C Set ++, the Performance Analyzer was called 
  7212. EXTRA. 
  7213.  
  7214.      Why Can't Performance Analyzer Show My Executable or Object Files? 
  7215.      Why Can't Performance Analyzer Trace OS/2 API Calls? 
  7216.      Why Are There No Events in My Trace File? 
  7217.      Can Performance Analyzer Analyze Child Processes? 
  7218.      Why Can't I Open My Trace File? 
  7219.      Why Can't I View Execution Density or Time Line? 
  7220.      Why Doesn't the Trace File Show All Functions? 
  7221.      How Can I Make My Trace File Smaller? 
  7222.      Why Is My Trace File Incomplete? 
  7223.      Why Do I Get Dashes in the Statistical Summary? 
  7224.      Why Are Many Events Displayed as the Same String? 
  7225.      Why Is the User Event Information Unreadable? 
  7226.      Why Is the Annotate Choice Disabled? 
  7227.      Why Is the Pattern Recognition Choice Disabled? 
  7228.      Why Is the Include Functions Choice Unavailable? 
  7229.      Why Aren't All Events Displayed? 
  7230.      Why Doesn't the Dynamic Call Graph Display? 
  7231.      Why Can't Performance Analyzer Trace My DLL? 
  7232.      Why Can't I Manipulate the Focus in the Overview Window? 
  7233.      Why Can't I See the Function Names? 
  7234.      Why Can't I See My Annotations? 
  7235.      Can I Run Performance Analyzer and the Debugger at the Same Time? 
  7236.  
  7237.  
  7238. ΓòÉΓòÉΓòÉ 16.1. Why Can't Performance Analyzer Show My Executable or Object Files? ΓòÉΓòÉΓòÉ
  7239.  
  7240. Question: 
  7241.  
  7242. Sometimes my executable files don't appear in the trace generation window. 
  7243. Other times, my executable file is shown in black, but Performance Analyzer 
  7244. cannot show the object files. Why? 
  7245.  
  7246. Answer: 
  7247.  
  7248. You must compile and link your application with the correct options before you 
  7249. can use Performance Analyzer. 
  7250.  
  7251. To compile your application, use the following options: 
  7252.  
  7253.  /Gh  Includes the profile hooks that allow Performance Analyzer to monitor 
  7254.       your executable. 
  7255.  
  7256.  /Ti  Includes the debugging information in the compiled object (.OBJ) file. 
  7257.  
  7258.  To link your application, use the /DE option to include the debugging 
  7259.  information in the final executable (EXE or DLL file).  You must also link 
  7260.  CPPOPA3.OBJ into your executable file. 
  7261.  
  7262.  
  7263. ΓòÉΓòÉΓòÉ 16.2. Why Can't Performance Analyzer Trace OS/2 API Calls? ΓòÉΓòÉΓòÉ
  7264.  
  7265. Question: 
  7266.  
  7267. Why can't Performance Analyzer trace my calls to the OS/2 APIs? 
  7268.  
  7269. Answer: 
  7270.  
  7271. To trace calls to the OS/2 APIs, specify the Performance Analyzer library for 
  7272. the APIs immediately before the OS/2 libraries in your link statement: 
  7273.  
  7274.      For Dos APIs, use  _DOSCALL.LIB. 
  7275.      For Win APIs, use _PMWIN.LIB. 
  7276.      For Gpi APIs, use _PMGPI.LIB. 
  7277.  
  7278.  Each of these libraries also has an associated DLL. 
  7279.  
  7280.  The order of the libraries in the link statement is critical. If the 
  7281.  Performance Analyzer libraries do not immediately precede the OS/2 libraries 
  7282.  in the link statement, Performance Analyzer may not interpret or trace the API 
  7283.  calls. 
  7284.  
  7285.  
  7286. ΓòÉΓòÉΓòÉ 16.3. Why Are There No Events in My Trace File? ΓòÉΓòÉΓòÉ
  7287.  
  7288. Question: 
  7289.  
  7290. Why are there no events logged in my trace file? 
  7291.  
  7292. Answer: 
  7293.  
  7294. Several things could have happened: 
  7295.  
  7296.      All functions were disabled in the Trace Generation window from the Edit 
  7297.       menu.  See the online help for the Trace Generation Window for more 
  7298.       information. 
  7299.  
  7300.      The application needs more time to run. Use the Timeout Control choice in 
  7301.       the Trace Generation window to control how long your application can run. 
  7302.  
  7303.      If you set a trigger on a function, the triggered function may not have 
  7304.       been reached. 
  7305.  
  7306.      Your program was not compiled and linked with the correct options.  (See 
  7307.       Why Can't Performance Analyzer Show My Executable or Object Files? for a 
  7308.       list of the options). 
  7309.  
  7310.  
  7311. ΓòÉΓòÉΓòÉ 16.4. Can Performance Analyzer Analyze Child Processes? ΓòÉΓòÉΓòÉ
  7312.  
  7313. Question: 
  7314.  
  7315. Can Performance Analyzer analyze child processes in a multiprocess application? 
  7316.  
  7317. Answer: 
  7318.  
  7319. No, Performance Analyzer does not provide this support. 
  7320.  
  7321.  
  7322. ΓòÉΓòÉΓòÉ 16.5. Why Can't I Open My Trace File? ΓòÉΓòÉΓòÉ
  7323.  
  7324. Question: 
  7325.  
  7326. I can't open a trace file from the command line. I know I successfully created 
  7327. it; why can't I open it? 
  7328.  
  7329. Answer: 
  7330.  
  7331. Make sure you are typing the correct command: 
  7332.  
  7333.  To Display        Enter 
  7334.  
  7335.  Statistical Summary icsperf /ss file.ext 
  7336.  
  7337.  Call Nesting      icsperf /cn file.ext 
  7338.  
  7339.  Time Line         icsperf /tl file.ext 
  7340.  
  7341.  Execution Density icsperf /ed file.ext 
  7342.  
  7343.  Dynamic Call Graph icsperf /cg file.ext 
  7344.  
  7345.  For more information, read the online help for the Trace Analysis Selection 
  7346.  window. 
  7347.  
  7348.  
  7349. ΓòÉΓòÉΓòÉ 16.6. Why Can't I View Execution Density or Time Line? ΓòÉΓòÉΓòÉ
  7350.  
  7351. Question: 
  7352.  
  7353. Why can't I open the Execution Density or Time Line diagram? 
  7354.  
  7355. Answer: 
  7356.  
  7357. If you chose to disable the time stamps from the Trace Generation window, these 
  7358. diagrams do not display. 
  7359.  
  7360. To view these diagrams, go to the Trace Generation window and from the Options 
  7361. menu, make sure that Time stamp events has a check mark. Then create the trace 
  7362. file again. 
  7363.  
  7364.  
  7365. ΓòÉΓòÉΓòÉ 16.7. Why Doesn't the Trace File Show All Functions? ΓòÉΓòÉΓòÉ
  7366.  
  7367. Question: 
  7368.  
  7369. Why doesn't the trace file show all the functions? 
  7370.  
  7371. Answer: 
  7372.  
  7373. One of three things may have occurred: 
  7374.  
  7375.    1. A trigger may have been set from the Trace Generation window. Read the 
  7376.       online help for Set Trigger for more information. 
  7377.  
  7378.    2. The call depth may be set to null or a low number. Read the online help 
  7379.       for Set Call Depth for more information. 
  7380.  
  7381.    3. Some of the functions may have been disabled before the trace. Read the 
  7382.       online help for the Trace Generation window for more information. 
  7383.  
  7384.  
  7385. ΓòÉΓòÉΓòÉ 16.8. How Can I Make My Trace File Smaller? ΓòÉΓòÉΓòÉ
  7386.  
  7387. Question: 
  7388.  
  7389. My trace file is very large.  How can I make it smaller? 
  7390.  
  7391. Answer: 
  7392.  
  7393. To limit the trace file information to a more manageable number of events, you 
  7394. can: 
  7395.  
  7396.      Use triggers to have a specific function start the trace. You can set 
  7397.       triggers from the Trace Generation window. 
  7398.  
  7399.      Add calls to PerfStart() and PerfStop() to your code, to specify to 
  7400.       Performance Analyzer when to begin and end tracing. 
  7401.  
  7402.      Disable functions, object files, or executables so they will not be 
  7403.       traced. You can do this from the Trace Generation window before you start 
  7404.       the trace. 
  7405.  
  7406.      Limit the tracing to specific threads or specific call depths per thread 
  7407.       by using Call Depth from the Options menu in the Trace Generation window. 
  7408.       If you set the call depth to 0 for a given thread, that thread will not 
  7409.       be traced. 
  7410.  
  7411.  
  7412. ΓòÉΓòÉΓòÉ 16.9. Why Is My Trace File Incomplete? ΓòÉΓòÉΓòÉ
  7413.  
  7414. Question: 
  7415.  
  7416. My trace file is missing some early events.  Why? 
  7417.  
  7418. Answer: 
  7419.  
  7420. Your buffer may be set to overwrite the older events. See the online help for 
  7421. the Buffer Control Action window for information on how to change the buffer. 
  7422.  
  7423.  
  7424. ΓòÉΓòÉΓòÉ 16.10. Why Do I Get Dashes in the Statistical Summary? ΓòÉΓòÉΓòÉ
  7425.  
  7426. Question: 
  7427.  
  7428. In the Statistical Summary display, why do I see "---" next to a function name? 
  7429.  
  7430. Answer: 
  7431.  
  7432. When you traced your application, there was not enough timing information 
  7433. available for Performance Analyzer to analyze the function. You need to allow 
  7434. more time for the function to run. Use the Timeout Control in the Trace 
  7435. Generation window to control how much time is allowed. 
  7436.  
  7437.  
  7438. ΓòÉΓòÉΓòÉ 16.11. Why Are Many Events Displayed as the Same String? ΓòÉΓòÉΓòÉ
  7439.  
  7440. Question: 
  7441.  
  7442. In the Statistical Summary and Call Nesting diagrams, why are multiple 
  7443. different user events incorrectly displayed as the same string? 
  7444.  
  7445. Answer: 
  7446.  
  7447. Make sure that the string you are passing to the PERF entry point is an ASCIIZ 
  7448. string. The string must exist in storage when the trace buffer containing the 
  7449. reference is written to disk. 
  7450.  
  7451. Also make sure that you have included the correct prototypes for the PERF entry 
  7452. point.  For C programs, the prototype is: 
  7453.  
  7454.    void PERF(PSZ string);
  7455.  
  7456. For C++ applications, the prototype is: 
  7457.  
  7458.    extern "C" {
  7459.      void PERF(PSZ string);
  7460.    }
  7461.  
  7462.  
  7463. ΓòÉΓòÉΓòÉ 16.12. Why Is the User Event Information Unreadable? ΓòÉΓòÉΓòÉ
  7464.  
  7465. Question: 
  7466.  
  7467. In the Statistical Summary and Call Nesting diagrams, why do user events 
  7468. display with unreadable information? 
  7469.  
  7470. Answer: 
  7471.  
  7472. Make sure that the string you are passing to the PERF entry point is an ASCIIZ 
  7473. string. The string must exist in storage when the trace buffer containing the 
  7474. reference is written to disk. 
  7475.  
  7476. Also make sure that you have included the correct prototypes for the PERF entry 
  7477. point.  For C programs, the prototype is: 
  7478.  
  7479.    void PERF(PSZ string);
  7480.  
  7481. For C++ applications, the prototype is: 
  7482.  
  7483.    extern "C" {
  7484.      void PERF(PSZ string);
  7485.    }
  7486.  
  7487.  
  7488. ΓòÉΓòÉΓòÉ 16.13. Why Is the Annotate Choice Disabled? ΓòÉΓòÉΓòÉ
  7489.  
  7490. Question: 
  7491.  
  7492. In the Call Nesting diagram, why is the Annotate choice disabled? 
  7493.  
  7494. Answer: 
  7495.  
  7496. When the Pattern Recognition choice is enabled, the Annotate choice is not 
  7497. available. Disable pattern recognition before selecting Annotate. 
  7498.  
  7499.  
  7500. ΓòÉΓòÉΓòÉ 16.14. Why Is the Pattern Recognition Choice Disabled? ΓòÉΓòÉΓòÉ
  7501.  
  7502. Question: 
  7503.  
  7504. In the Call Nesting diagram, why is the Pattern Recognition choice disabled? 
  7505.  
  7506. Answer: 
  7507.  
  7508. You must select a single thread using the Include threads option from the View 
  7509. menu: 
  7510.  
  7511.    1. Select the View menu. 
  7512.    2. Select Include threads. 
  7513.    3. Select the thread you want to view, and then select the Use pattern 
  7514.       recognition option. 
  7515.  
  7516.  If the trace file is large, pattern recognition is not available. If this is 
  7517.  your problem, the Include threads menu item is disabled (grayed out). See How 
  7518.  Can I Make My Trace File Smaller? for ways to reduce the size of your trace 
  7519.  file. 
  7520.  
  7521.  
  7522. ΓòÉΓòÉΓòÉ 16.15. Why Is the Include Functions Choice Unavailable? ΓòÉΓòÉΓòÉ
  7523.  
  7524. Question: 
  7525.  
  7526. In the Call Nesting diagram, why isn't the Include functions choice from the 
  7527. View menu available? 
  7528.  
  7529. Answer: 
  7530.  
  7531. This choice is only available when all threads are displayed. If you have 
  7532. enabled a specific thread from the Include threads menu (also from the View 
  7533. menu), you must deselect the pattern recognition checkbox and select the All 
  7534. Threads choice before you can use Include functions. 
  7535.  
  7536.  
  7537. ΓòÉΓòÉΓòÉ 16.16. Why Aren't All Events Displayed? ΓòÉΓòÉΓòÉ
  7538.  
  7539. Question: 
  7540.  
  7541. Why isn't the Execution Density diagram displaying all of the events? 
  7542.  
  7543. Answer: 
  7544.  
  7545. Check your settings in the diagram: 
  7546.  
  7547.    1. Check which functions are included in the display by selecting Include 
  7548.       functions from the View menu. 
  7549.  
  7550.    2. Check which threads are included in the display by selecting Include 
  7551.       threads from the View menu. 
  7552.  
  7553.  
  7554. ΓòÉΓòÉΓòÉ 16.17. Why Doesn't the Dynamic Call Graph Display? ΓòÉΓòÉΓòÉ
  7555.  
  7556. Question: 
  7557.  
  7558. Why doesn't the Dynamic Call Graph display? 
  7559.  
  7560. Answer: 
  7561.  
  7562. If your trace file contains only one function per thread, no dynamic calls are 
  7563. made and therefore the Dynamic Call Graph does not display. 
  7564.  
  7565.  
  7566. ΓòÉΓòÉΓòÉ 16.18. Why Can't Performance Analyzer Trace My DLL? ΓòÉΓòÉΓòÉ
  7567.  
  7568. Question: 
  7569.  
  7570. Why can't Performance Analyzer trace my dynamically-loaded DLLs? 
  7571.  
  7572. Answer: 
  7573.  
  7574. Make sure you compiled the DLLs with the correct options (/Gh to enable 
  7575. profiling and /Ti to generate debug information), and linked using the /DE 
  7576. option to include debug information in the DLL. You must also link CPPOP3A.OBJ 
  7577. into your DLL. 
  7578.  
  7579. Note:  Previous versions of C Set ++ did not support tracing dynamically-loaded 
  7580. DLLs. 
  7581.  
  7582.  
  7583. ΓòÉΓòÉΓòÉ 16.19. Why Can't I Manipulate the Focus in the Overview Window? ΓòÉΓòÉΓòÉ
  7584.  
  7585. Question: 
  7586.  
  7587. In the Dynamic Call Graph, why can't I manipulate the grey box in the Overview 
  7588. window to change the focus? 
  7589.  
  7590. Answer: 
  7591.  
  7592. Increase the size of the Overview window. (Press mouse button 1 on the corner 
  7593. of the window and drag it.) 
  7594.  
  7595.  
  7596. ΓòÉΓòÉΓòÉ 16.20. Why Can't I See the Function Names? ΓòÉΓòÉΓòÉ
  7597.  
  7598. Question: 
  7599.  
  7600. In the Dynamic Call Graph and Time Line diagram, why can't I see the names of 
  7601. the functions? 
  7602.  
  7603. Answer: 
  7604.  
  7605. You need to increase the size of the diagram. Use Zoom In to magnify the 
  7606. function names. 
  7607.  
  7608.  
  7609. ΓòÉΓòÉΓòÉ 16.21. Why Can't I See My Annotations? ΓòÉΓòÉΓòÉ
  7610.  
  7611. Question: 
  7612.  
  7613. In the Call Nesting diagram, why can't I see my annotations? 
  7614.  
  7615. Answer: 
  7616.  
  7617. You need to disable the Pattern Recognition to see the annotations. 
  7618.  
  7619.  
  7620. ΓòÉΓòÉΓòÉ 16.22. Can I Run Performance Analyzer and the Debugger at the Same Time? ΓòÉΓòÉΓòÉ
  7621.  
  7622. Question: 
  7623.  
  7624. Can I run Performance Analyzer and the debugger at the same time? 
  7625.  
  7626. Answer: 
  7627.  
  7628. No.  Because of operating-system limitations, you cannot run Performance 
  7629. Analyzer and the debugger at the same time. 
  7630.  
  7631.  
  7632. ΓòÉΓòÉΓòÉ 17. Browsing Your Program ΓòÉΓòÉΓòÉ
  7633.  
  7634. This section answers questions about using the VisualAge C++ Browser to 
  7635. understand your program. 
  7636.  
  7637.      Will the Browser Work with Old .BRS or .PDB Files? 
  7638.      What is QuickBrowse and Why Should I Use It? 
  7639.      Why Doesn't QuickBrowse Show Class Template Instances? 
  7640.      What Is the Difference Between /Fb and /Fb*? 
  7641.      What Are the .PD* Files? 
  7642.      What Does the Hold Button Do? 
  7643.      What Do the Blue Initials in Front of the Names Mean? 
  7644.      Can I Browse SOM Classes? 
  7645.      Can I Browse Programs Written in Other Languages? 
  7646.      What Does Merge Do and Why Should I Use It? 
  7647.      Why Can't I Edit Definitions for Library Member Functions? 
  7648.      Why Are Some Pop-Up Menu Items Disabled? 
  7649.      Why Doesn't Show Documentation Work with My Own Classes? 
  7650.      What Does the Order Menu Choice Do? 
  7651.      Where Is the Source View of My Functions? 
  7652.      Why Is the Text in the Graph So Small? 
  7653.      Why Is QuickBrowse Not Always Available? 
  7654.      How Do I Zoom Into a Small Area on a Graph? 
  7655.      What Are Anonymous Types? 
  7656.      What are Compiler-Generated Constructors and Destructors? 
  7657.      What Does 'n' Instances Mean? 
  7658.      What do Print Client and Print Zone Mean? 
  7659.      What does Weighting Do in the Graph Window? 
  7660.      In What Format Are the Graph Pictures Saved? 
  7661.  
  7662.  
  7663. ΓòÉΓòÉΓòÉ 17.1. Will the Browser Work with Old .BRS or .PDB Files? ΓòÉΓòÉΓòÉ
  7664.  
  7665. Question: 
  7666.  
  7667. Will the browser work with my old .BRS files from other versions of 
  7668. VisualAge C++, or with my .PDB files from C Set ++ for AIX? 
  7669.  
  7670. Answer: 
  7671.  
  7672. No, you can only use the browser with .PDB files generated by this version of 
  7673. the VisualAge C++ compiler. Unless you want to continue using the old browser, 
  7674. you can delete the .BRS files. 
  7675.  
  7676.  
  7677. ΓòÉΓòÉΓòÉ 17.2. What is QuickBrowse and Why Should I Use It? ΓòÉΓòÉΓòÉ
  7678.  
  7679. Question: What is QuickBrowse, why would I want to use it, and how can I make 
  7680. use of it? How is it different from compiling with the Generate Browser 
  7681. information (/Fb) option? 
  7682.  
  7683. Answer: 
  7684.  
  7685. Use QuickBrowse to quickly obtain and browse type information for code for 
  7686. which there is no compiler-generated (/Fb) browser information. Use QuickBrowse 
  7687. because it is faster than compiling your code, and because you may be able to 
  7688. browse files that do not compile. (Because QuickBrowse parses your code and 
  7689. ignores function bodies, as long as the type information is complete and valid, 
  7690. you can browse it with QuickBrowse.) 
  7691.  
  7692. For example, QuickBrowse is well-suited for: 
  7693.  
  7694.      Understanding class library interfaces. 
  7695.      Browsing code you are porting to OS/2 from another platform. 
  7696.      Understanding an existing code base. 
  7697.      Aiding in the design of new code. 
  7698.  
  7699.  For more information on how to accomplish these tasks with QuickBrowse, see 
  7700.  the Browser How Do I help. 
  7701.  
  7702.  To use QuickBrowse, invoke the browser on your project. If compiler-generated 
  7703.  browser information is not available, the browser displays a window to tell 
  7704.  you the information is missing.  From this window, you can choose to invoke 
  7705.  QuickBrowse for the files where data is missing. While QuickBrowse runs, 
  7706.  messages appear in the project's monitor, just as if you were doing a Build. 
  7707.  
  7708.  Although QuickBrowse is faster than compiling, compiler-generated browser 
  7709.  information is more complete than that generated by QuickBrowse. Because 
  7710.  QuickBrowse disregards function bodies, any information in that function body, 
  7711.  including information about calls and thrown exception types, is not included. 
  7712.  If you need this information, compile your source files to generate browser 
  7713.  information. 
  7714.  
  7715.  Note:  QuickBrowse is only available when you invoke the browser on a 
  7716.  VisualAge C++ project.  If you start the browser from the desktop icon or 
  7717.  command line, QuickBrowse is not available. 
  7718.  
  7719.  
  7720. ΓòÉΓòÉΓòÉ 17.3. Why Doesn't QuickBrowse Show Class Template Instances? ΓòÉΓòÉΓòÉ
  7721.  
  7722. Question: 
  7723.  
  7724. When I use QuickBrowse, class template instances do not appear in any list of 
  7725. classes, and listing the instantiations for the templates gives no results. 
  7726. Why? 
  7727.  
  7728. Answer: 
  7729.  
  7730. When you QuickBrowse source files, any class template instances at file scope 
  7731. appear as global variables. For example, given the following source code: 
  7732.  
  7733.    template<class T> class foo {
  7734.       T* bar;
  7735.    };
  7736.  
  7737.    foo<int> boo;
  7738.  
  7739. QuickBrowse produces one class named foo<class T> and one global variable boo 
  7740. of type foo<class T>. 
  7741.  
  7742.  
  7743. ΓòÉΓòÉΓòÉ 17.4. What Is the Difference Between /Fb and /Fb*? ΓòÉΓòÉΓòÉ
  7744.  
  7745. Question: 
  7746.  
  7747. What is the difference between the compiler options to generate browser 
  7748. information (/Fb) and generate all browser information (/Fb*)? 
  7749.  
  7750. Answer: 
  7751.  
  7752. The difference between the two options relates to how much browser information 
  7753. is generated from system header files (specified in angle brackets < > instead 
  7754. of double quotation marks). 
  7755.  
  7756. The generate browser information (/Fb) option discards much non-type 
  7757. information from system header files: 
  7758.  
  7759.      Non-member function declarations are not included in the .PDB file, 
  7760.       including those C and OS/2 header files. Any friendship granted to any 
  7761.       such omitted functions will not be recorded for a class.  For example, 
  7762.       given the following declarations: 
  7763.  
  7764.             // in <foo.h>
  7765.               int foobar(void);
  7766.             // in "bar.h"
  7767.               class bar {
  7768.               friend int foobar(void);
  7769.               }
  7770.  
  7771.       This friendship will not be included in the list of friends of class bar. 
  7772.      No global variable declared or defined in the system header files is 
  7773.       included in the .PDB file. This includes variables of an instantiated 
  7774.       template type. 
  7775.      Class member functions declarations will be emitted, but their inline 
  7776.       definitions, if any, will not appear in the .PDB file. 
  7777.      Non-inline function definitions will not be emitted in the .PDB file. 
  7778.  
  7779.  When you choose to generate all browser information (/Fb*), the above 
  7780.  information is included. 
  7781.  
  7782.  Note:  In general, you should only use /Fb to generate browser information. 
  7783.  The compiler generates a message if you should use /Fb* instead. 
  7784.  
  7785.  
  7786. ΓòÉΓòÉΓòÉ 17.5. What Are the .PD* Files? ΓòÉΓòÉΓòÉ
  7787.  
  7788. Question: 
  7789.  
  7790. What are the .PD* files? 
  7791.  
  7792. Answer: 
  7793.  
  7794. The .PDB files are output by the C++ compiler. There is one for every OBJ file. 
  7795. When you browse a target file (.EXE, .DLL, or .LIB), the individual .PDB files 
  7796. (for the .OBJ files contained in the target) are loaded into memory by the 
  7797. browser.  A copy of this digested data is quickly saved when you stop browsing 
  7798. the target file, and is quickly loaded when you browse the target file again. 
  7799.  
  7800. The extension of the saved file is based upon the extension of the target file: 
  7801. data for a .EXE file is saved in a .PDE file, DLL data in a .PDD file, and LIB 
  7802. data in a .PDL file. Manually loading one or more .PDB file or performing a 
  7803. Merge operation is analogous to grouping a set of .OBJ files together into a 
  7804. single .LIB file, so the saved file version in this case is a .PDL file. 
  7805.  
  7806.  
  7807. ΓòÉΓòÉΓòÉ 17.6. What Does the Hold Button Do? ΓòÉΓòÉΓòÉ
  7808.  
  7809. Question: 
  7810.  
  7811. What does the Hold button do? 
  7812.  
  7813. Answer: 
  7814.  
  7815. Typically, the results of any one action will overlay the contents of the first 
  7816. window of the right type for the action (for example, a List All Files action 
  7817. changes the content of the first List window). However, there may be times when 
  7818. you want to maintain the contents of that window, for example, to keep the list 
  7819. of all classes available as you look at the contents of different classes. 
  7820.  
  7821. When you push the Hold button, the contents of the window are maintained as 
  7822. they are and the results of any action you perform are placed in a separate 
  7823. window. 
  7824.  
  7825.  
  7826. ΓòÉΓòÉΓòÉ 17.7. What Do the Blue Initials in Front of the Names Mean? ΓòÉΓòÉΓòÉ
  7827.  
  7828. Question: 
  7829.  
  7830. What do the blue letters in front of names mean? 
  7831.  
  7832. Answer: 
  7833.  
  7834. The letters are shorthand icons for common C++ attributes: 
  7835.  
  7836.  V   virtual 
  7837.  S   static 
  7838.  C   const 
  7839.  P   pure virtual 
  7840.  E   enum 
  7841.  
  7842.  You can choose to see the attribute icons only, the full text only, or both, 
  7843.  using the Styles page in the List Window Settings Notebook. 
  7844.  
  7845.  
  7846. ΓòÉΓòÉΓòÉ 17.8. Can I Browse SOM Classes? ΓòÉΓòÉΓòÉ
  7847.  
  7848. Question: 
  7849.  
  7850. Can I browse SOM classes? 
  7851.  
  7852. Answer: 
  7853.  
  7854. Yes and no.  You can browse SOM classes compiled with the Direct-to-Som (DTS) 
  7855. feature of the VisualAge C++ compiler. You cannot browse SOM classes defined in 
  7856. IDL unless you generate C++ bindings for these classes, and then compile them 
  7857. with the DTS compiler support. 
  7858.  
  7859.  
  7860. ΓòÉΓòÉΓòÉ 17.9. Can I Browse Programs Written in Other Languages? ΓòÉΓòÉΓòÉ
  7861.  
  7862. Question: 
  7863.  
  7864. Can I use the browser to browse programs written in other languages like 
  7865. Object-Oriented REXX, Object-Oriented Cobol, or C? 
  7866.  
  7867. Answer: 
  7868.  
  7869. No.  While some similarity exists between C++ and these other OO languages, 
  7870. this is a C++ class browser. You can browse C files to some extent by compiling 
  7871. them as C++ files.  However, the data you obtain has limited value because 
  7872. there are no classes in the C language.  (Structures and unions are similar to 
  7873. C++ classes, except that they only contain data members).  File and function 
  7874. information will be present, however. 
  7875.  
  7876.  
  7877. ΓòÉΓòÉΓòÉ 17.10. What Does Merge Do and Why Should I Use It? ΓòÉΓòÉΓòÉ
  7878.  
  7879. Question: 
  7880.  
  7881. What does Merge do?  Why would I want to use it? 
  7882.  
  7883. Answer: 
  7884.  
  7885. When you browse a target program (executable file, DLL, or library), you only 
  7886. see those classes, functions, and files that were actually used in the program. 
  7887. You do not see related objects.  For example, assume that you have written a 
  7888. small program using the User Interface library, and it contains an 
  7889. IFrameWindow, a menu bar, and some static text.  Next you want to add push 
  7890. buttons and a bitmap onto your window.  You can merge the User Interface 
  7891. Library data (all of it) with your program's data, and see all the interface 
  7892. facts about all the classes in the User Interface library. 
  7893.  
  7894. Also, many programs are written as a .EXE file and one or more DLLs. If you 
  7895. browse the .EXE file, you only see the data from that file. You can merge in 
  7896. the data from the DLLs to see the whole program's information. 
  7897.  
  7898.  
  7899. ΓòÉΓòÉΓòÉ 17.11. Why Can't I Edit Definitions for Library Member Functions? ΓòÉΓòÉΓòÉ
  7900.  
  7901. Question: 
  7902.  
  7903. Why can't I edit the definitions for members of the Open Class library that are 
  7904. listed in the Load menu.  Why not? 
  7905.  
  7906. Answer: 
  7907.  
  7908. The browser differentiates between declarations and definitions of objects. The 
  7909. Edit Definition action edits the file where the object is defined. A function 
  7910. is defined where it is implemented. If you don't have the body of the function 
  7911. in any of the files that make up the target that you are browsing (for instance 
  7912. it may a function from a library), the browser cannot edit the function. 
  7913.  
  7914. Editing the file containing the declaration for a function whose full prototype 
  7915. is displayed in the browser would not give any more useful information than you 
  7916. already have.  Also, a function's declaration can appear in multiple files, and 
  7917. may be (subtly) different in each location.  Only your Build process will help 
  7918. you find all problems with mismatched function prototypes. 
  7919.  
  7920.  
  7921. ΓòÉΓòÉΓòÉ 17.12. Why Are Some Pop-Up Menu Items Disabled? ΓòÉΓòÉΓòÉ
  7922.  
  7923. Question: 
  7924.  
  7925. Why are some items greyed out (disabled) on pop-up menus? 
  7926.  
  7927. Answer: 
  7928.  
  7929. The browser prechecks the contents of its database to see if certain actions 
  7930. are valid.  For objects without definitions, it greys out the Edit Definition 
  7931. action.  For classes that have no base class, it greys out both Graph All Base 
  7932. and Derived Classes and Graph All Base Classes actions. The Expand Typedef 
  7933. action only appears on type objects that are typedefs. 
  7934.  
  7935. The prechecks are done when it is possible to do so quickly. Some actions 
  7936. require the entire database to be searched for answers.  An example of this is 
  7937. the List Friendships action.  This particular action is not prechecked and if 
  7938. invoked on a class that has not been identified as the friend of any other 
  7939. class, you will see the "No results were found" response. 
  7940.  
  7941.  
  7942. ΓòÉΓòÉΓòÉ 17.13. Why Doesn't Show Documentation Work with My Own Classes? ΓòÉΓòÉΓòÉ
  7943.  
  7944. Question: 
  7945.  
  7946. Show documentation does not work with my own classes or functions. Why not? 
  7947.  
  7948. Answer: 
  7949.  
  7950. The VisualAge C++ Open Class Library provides special files that enable Show 
  7951. documentation to display details about particular classes and members. To 
  7952. enable Show documentation for other classes, including your own, you must 
  7953. provide: 
  7954.  
  7955.    1. An online document in .INF format that describes the classes. For 
  7956.       information on creating online documentation, see the IPF Guide and 
  7957.       Reference. 
  7958.    2. An index file that lists the classes or members along with information 
  7959.       about where they are described. For information on creating index files, 
  7960.       see the documentation for KwikINF in the User's Guide. 
  7961.  
  7962.  
  7963. ΓòÉΓòÉΓòÉ 17.14. What Does the Order Menu Choice Do? ΓòÉΓòÉΓòÉ
  7964.  
  7965. Question: 
  7966.  
  7967. What does the Order menu choice do? Why is it sometimes greyed out (disabled)? 
  7968.  
  7969. Answer: 
  7970.  
  7971. The Order choice is enabled only when you are looking at the results of a List 
  7972. Members with Inheritance action.  The browser displays all the members of a 
  7973. class, and all the members that that class inherits from its base classes. 
  7974.  
  7975. The default order, Class, presents the name of the selected class first, 
  7976. followed by its base classes. When you expand the + on one of these classes, 
  7977. you see public, protected, and private; these are the Access levels. If you 
  7978. expand the + on one of these access levels, you see constructors/destructors, 
  7979. functions, and so on; these are the Type levels. 
  7980.  
  7981. If you are interested in the public functions of a class (and all the other 
  7982. classes through inheritance), you can use a different order to group the 
  7983. functions that are spread throughout the window. If you sort by Access order, 
  7984. the items are grouped according to public, protected, and private. If you sort 
  7985. the information by its Type, you see grouped together all the functions, all 
  7986. the variables, and so on. 
  7987.  
  7988. Experiment with the ordering to find out what best suits your needs. 
  7989.  
  7990.  
  7991. ΓòÉΓòÉΓòÉ 17.15. Where Is the Source View of My Functions? ΓòÉΓòÉΓòÉ
  7992.  
  7993. Question: 
  7994.  
  7995. Where is the source view of my functions? 
  7996.  
  7997. Answer: 
  7998.  
  7999. You can see the source for any program object by displaying the pop-up menu for 
  8000. the object, and selecting the Edit Definition action. This starts your editor 
  8001. on the file containing the definition of the object.  This menu option may be 
  8002. greyed out if the definition of the object is not available; see Why Can't I 
  8003. Edit Definitions for Library Member Functions? for more details. 
  8004.  
  8005. Other C++ and Smalltalk browsers contain a small edit window which is linked to 
  8006. other list boxes etc. in their browser.  This has a number of drawbacks: 
  8007.  
  8008.      The small edit windows introduce yet another editor that you may not want 
  8009.       to use. The VisualAge C++ browser uses your choice of editor, the same 
  8010.       one that you use all the time. 
  8011.      The edit window is small. With small windows you spend more time 
  8012.       scrolling and resizing than you do understanding. 
  8013.      Programming with C++ is not the same as Smalltalk.  In Smalltalk, all of 
  8014.       your program's classes and methods are stored in some environment-aware 
  8015.       database, not the file system.  When you program in C++, you are still 
  8016.       using files, and frankly the performance of opening a new file, and 
  8017.       locating a line just because the user changed focus or scrolled up with 
  8018.       the arrow keys is slow. 
  8019.  
  8020.  
  8021. ΓòÉΓòÉΓòÉ 17.16. Why Is the Text in the Graph So Small? ΓòÉΓòÉΓòÉ
  8022.  
  8023. Question: 
  8024.  
  8025. Why can't I read the text in nodes in the drawn graph?  Why does the text get 
  8026. smaller when I zoom in? 
  8027.  
  8028. Answer: 
  8029.  
  8030. One problem with drawing an arbitrary graph on a fixed size window is that as 
  8031. more and more items are displayed in the graph, the size of the items becomes 
  8032. so small that any associated label is too small to read.  That is what is 
  8033. happening here.  The type of font used in the window can also make it worse. 
  8034.  
  8035. The text does not really grow smaller when you zoom in; it just seems to. If 
  8036. the font used in the labels in the graph is a bitmap font, then the Graph 
  8037. Window is limited to the available sizes in that font. The text does not 
  8038. shrink, but the box around the text grows larger. 
  8039.  
  8040. If the font used is an Outline (or Vector) font, then the Graph Window is not 
  8041. limited to a small set of available sizes, but can draw the text in a size that 
  8042. fits the containing box.  Outline fonts are marginally slower in performance 
  8043. than Bitmap fonts, so a large graph with a lot of node text would draw more 
  8044. slowly when an Outline font is used. 
  8045.  
  8046.  
  8047. ΓòÉΓòÉΓòÉ 17.17. Why Is QuickBrowse Not Always Available? ΓòÉΓòÉΓòÉ
  8048.  
  8049. Question: 
  8050.  
  8051. Sometimes I can't use QuickBrowse.  Why? 
  8052.  
  8053. Answer: 
  8054.  
  8055. The QuickBrowse feature of the browser is not available unless you are browsing 
  8056. a project. If you started the browser from the command line, or by 
  8057. double-clicking on its desktop icon, then you are not browsing a project, and 
  8058. QuickBrowse is not available. 
  8059.  
  8060.  
  8061. ΓòÉΓòÉΓòÉ 17.18. How Do I Zoom Into a Small Area on a Graph? ΓòÉΓòÉΓòÉ
  8062.  
  8063. Question: 
  8064.  
  8065. How do I zoom into a small area on a Graph? 
  8066.  
  8067. Answer: 
  8068.  
  8069. You can do this in one of two ways: 
  8070.  
  8071.    1. Use the mouse to select an area to zoom to.  Move the mouse to the corner 
  8072.       of where you want to zoom, hold down mouse button 1, and drag the mouse 
  8073.       to the opposite corner of the area.  A small box appears between the 
  8074.       first point and the mouse pointer.  Release the mouse button, press mouse 
  8075.       button 2 to display the pop-up menu, and select Zoom in. 
  8076.  
  8077.    2. Select a node, and then either press Ctrl-C, or use mouse button 2 to 
  8078.       display the pop-up menu, and select the Center action.  This centers the 
  8079.       picture on that point or node. Then zoom in using one of: 
  8080.  
  8081.           The zoom slider control on the left side of the window 
  8082.           The Zoom in or Max Zoom in actions from either the View menu or from 
  8083.            the window background pop-up menu. 
  8084.           The Ctrl and + keys (equivalent to Zoom in). 
  8085.           The Alt and + keys (equivalent to Max Zoom in). 
  8086.  
  8087.  
  8088. ΓòÉΓòÉΓòÉ 17.19. What Are Anonymous Types? ΓòÉΓòÉΓòÉ
  8089.  
  8090. Question: 
  8091.  
  8092. Sometimes I see types called [anonymous].  What are they? 
  8093.  
  8094. Answer: 
  8095.  
  8096. Both the C and C++ languages have the concept of anonymous, or unnamed, 
  8097. structures, unions and enumerated types. For example, each of the types below 
  8098. is anonymous: 
  8099.  
  8100.    struct {
  8101.      int number;
  8102.      int code;
  8103.      char *name;
  8104.    } record;
  8105.  
  8106.    union {
  8107.      int a;
  8108.      char b;
  8109.    };
  8110.  
  8111.    enum { red, yellow, green } color_1, color_2;
  8112.  
  8113.  
  8114. ΓòÉΓòÉΓòÉ 17.20. What are Compiler-Generated Constructors and Destructors? ΓòÉΓòÉΓòÉ
  8115.  
  8116. Question: 
  8117.  
  8118. What are compiler-generated constructors and destructors, and why do I see them 
  8119. in my browser files? 
  8120.  
  8121. Answer: 
  8122.  
  8123. When you define a class, but do not define your own default constructor, copy 
  8124. constructor, or destructor, the compiler will implicitly generate one for you. 
  8125. They are included to inform you that they are there. 
  8126.  
  8127.  
  8128. ΓòÉΓòÉΓòÉ 17.21. What Does 'n' Instances Mean? ΓòÉΓòÉΓòÉ
  8129.  
  8130. Question: 
  8131.  
  8132. What does ('n' Instances) mean? 
  8133.  
  8134. Answer: 
  8135.  
  8136. When you use multiple inheritance, and two (or more) of your base classes 
  8137. inherit from a common class, you end up with an inheritance hierarchy like one 
  8138. of the following: 
  8139.  
  8140. Nonvirtual inheritance was used by B and C when they inherited from A, but 
  8141. virtual inheritance was used by F and G when they inherited from E.  An object 
  8142. of type D will contain two copies of the data contained in an object of type A. 
  8143. An object of type H will contain only one copy of the data contained in an 
  8144. object of type E. 
  8145.  
  8146. To highlight this non-diamond shape inheritance structure to you, the browser 
  8147. indicates when a derived class contains more than one copy of the data from a 
  8148. base class. 
  8149.  
  8150.  
  8151. ΓòÉΓòÉΓòÉ 17.22. What do Print Client and Print Zone Mean? ΓòÉΓòÉΓòÉ
  8152.  
  8153. Question: 
  8154.  
  8155. What do Print Client and Print Zone mean in the Graph Window? 
  8156.  
  8157. Answer: 
  8158.  
  8159. A client is the client area in the graph window, meaning the part of the graph 
  8160. that you can see on your screen in the window.  (What is shown in the window is 
  8161. not necessarily the entire graph.) Print Client prints the contents of this 
  8162. client area on a single page. 
  8163.  
  8164. A zone is a rectangular area that you select in the graph. Print Zone prints 
  8165. the contents of a zone on a single page. 
  8166.  
  8167.  
  8168. ΓòÉΓòÉΓòÉ 17.23. What does Weighting Do in the Graph Window? ΓòÉΓòÉΓòÉ
  8169.  
  8170. Question: 
  8171.  
  8172. What does Weighting (from the View menu) do in the Graph Window? 
  8173.  
  8174. Answer: 
  8175.  
  8176. Different graph layouts look better one way (for particular graph contents) 
  8177. than others. For instance, some wide graphs with wide nodes look best when 
  8178. shown horizontally, while narrower graphs look best when shown vertically. 
  8179. Also, graphs can be drawn with all roots of a tree at an equal height, all 
  8180. leaves at an equal height, or something somewhere in between. Consider the 
  8181. following three layouts for the same graph: You can choose to lay out a graph 
  8182. differently so that you can better understand its contents. You may find this 
  8183. helpful in some situations. 
  8184.  
  8185.  
  8186. ΓòÉΓòÉΓòÉ 17.24. In What Format Are the Graph Pictures Saved? ΓòÉΓòÉΓòÉ
  8187.  
  8188. Question: 
  8189.  
  8190. In what format are the Graph pictures saved? 
  8191.  
  8192. Answer: 
  8193.  
  8194. The pictures are saved as OS/2 bitmap (.BMP) files.  To specify the size of the 
  8195. bitmap to save, see the Bitmap page of the Graph settings notebook. 
  8196.  
  8197.  
  8198. ΓòÉΓòÉΓòÉ 18. Preparing to Ship Your Application ΓòÉΓòÉΓòÉ
  8199.  
  8200. This section answers questions you may have as you prepare to ship your 
  8201. application to other customers. 
  8202.  
  8203.      Which VisualAge C++ DLLs Can I Ship with My Product? 
  8204.      Should I Build My Own C Runtime DLL? 
  8205.      Can I Rebuild the User Interface Class Library DLLs? 
  8206.      Should I Bind Runtime Messages to My Application? 
  8207.      Can I Use Multiple C Runtime Libraries? 
  8208.      How Do I Imbed a Copyright Statement? 
  8209.  
  8210.  
  8211. ΓòÉΓòÉΓòÉ 18.1. Which VisualAge C++ DLLs Can I Ship with My Product? ΓòÉΓòÉΓòÉ
  8212.  
  8213. Question: 
  8214.  
  8215. Which VisualAge C++ DLLs can I ship with my product? 
  8216.  
  8217. Answer: 
  8218.  
  8219. You can ship any or all of the following DLLs with your product, provided you 
  8220. rebuild them with another name or rename them using DLLRNAME: 
  8221.  
  8222.       CPPOM30.DLL 
  8223.       CPPON30.DLL 
  8224.       CPPOS30.DLL 
  8225.       CPPOOU3.DLL 
  8226.       CPPOOD3.DLL 
  8227.       CPPOOM3.DLL 
  8228.       CPPOOB3.DLL 
  8229.       CPPOOC3.DLL 
  8230.       CPPOOR3.DLL 
  8231.       CPPOOV3.DLL 
  8232.       CPPODS3.DLL 
  8233.       CPPODI3.DLL 
  8234.       CPPOOR3U.DLL 
  8235.       CPPOOR3J.DLL 
  8236.       CPPOOR3K.DLL 
  8237.       CPPOOR3T.DLL 
  8238.       CPPOOR3P.DLL 
  8239.  
  8240.  Refer to the License Information booklet for details on shipping VisualAge C++ 
  8241.  libraries. 
  8242.  
  8243.  Note that if you use the class library resource DLLs, in addition to renaming 
  8244.  them, you must call IApplication::current().setResourceLibrary() in your 
  8245.  application, specifying the new DLL name. 
  8246.  
  8247.  You can also create your own runtime libraries and export the C library 
  8248.  functions from them.  See the Programming Guide for more information on 
  8249.  creating your own runtime libraries. 
  8250.  
  8251.  
  8252. ΓòÉΓòÉΓòÉ 18.2. Should I Build My Own C Runtime DLL? ΓòÉΓòÉΓòÉ
  8253.  
  8254. Question: 
  8255.  
  8256. Should I build my own C runtime DLL to ship with my program?  How do I do it? 
  8257.  
  8258. Answer: 
  8259.  
  8260. If you own a whole application that contains multiple .DLL and .EXE files, you 
  8261. should create a runtime DLL with only the functions your application requires 
  8262. and have all your components dynamically link to that DLL.  The advantages are: 
  8263.  
  8264.    1. Your application is smaller. 
  8265.    2. Your application is faster, because only one copy of the runtime 
  8266.       environment needs to be created for each process. 
  8267.    3. The working set is smaller for the same reason as in Should I Build My 
  8268.       Own C Runtime DLL?. 
  8269.    4. You can allocate memory in one module and free it in another. 
  8270.    5. You can open files in one module, read and write in another module, and 
  8271.       close them in another module. 
  8272.    6. All exceptions are handled by one common runtime environment. 
  8273.  
  8274.  If you do not own the whole application and you need to supply a standalone 
  8275.  DLL, you should statically bind the C runtime to your DLL. Make sure that you 
  8276.  use the #pragma handler on all the entry points to the DLL, to ensure that any 
  8277.  exceptions that occur within your DLL are handled.  However, you lose the 
  8278.  advantages mentioned in points 4 and 5 above. 
  8279.  
  8280.  VisualAge C++ includes the .DEF files that are used to build the runtime DLLs 
  8281.  shipped with it.  Do not be concerned about internal functions, because the 
  8282.  linker links in everything it needs to resolve all external references. 
  8283.  
  8284.  To make your own runtime DLL: 
  8285.  
  8286.    1. Rename the appropriate .DEF files that are provided in the LIB 
  8287.       subdirectory where you installed VisualAge C++. For example, to create a 
  8288.       multithreading DLL, rename CPPOM30.DLL to MYCRTDLL.DEF. 
  8289.  
  8290.       Remember to change the DLL name on the LIBRARY line of the .DEF file. 
  8291.  
  8292.    2. Remove the STUB line from the .DEF file. Remove unwanted functions from 
  8293.       the .DEF file.  Remember not to delete anything that is followed by a 
  8294.       **** comment: these variables and functions are always required. 
  8295.  
  8296.    3. Create an empty source file, for example, MYCRTDLL.C. 
  8297.  
  8298.    4. Compile and link the files as follows: 
  8299.  
  8300.                icc /Ge- <options> MYCRTDLL.C MYCRTDLL.DEF
  8301.       and use one of the following options: /Gm, /Gm-, or /Rn, according to 
  8302.       what type of DLL you want to build. 
  8303.  
  8304.    5. Build the import library as follows: 
  8305.  
  8306.                IMPLIB /NOI MYCRTDLL.LIB MYCRTDLL.DEF
  8307.  
  8308.    6. Use the ILIB utility to add the necessary real objects to the import 
  8309.       library, as follows: 
  8310.  
  8311.                ILIB MYCRTDLL.LIB +CPPOx30.LIB
  8312.       where x is M, S, or N, according to whether you want a multithread, 
  8313.       single-thread, or no runtime environment. 
  8314.  
  8315.    7. Compile your .EXE or .DLL files with the /Gn option.  When you link, 
  8316.       specify your own libraries, including MYCRTDLL.LIB and OS2386.LIB. 
  8317.  
  8318.  If you want to rebuild the class library DLLs, see Can I Rebuild the User 
  8319.  Interface Class Library DLLs?. 
  8320.  
  8321.  
  8322. ΓòÉΓòÉΓòÉ 18.3. Can I Rebuild the User Interface Class Library DLLs? ΓòÉΓòÉΓòÉ
  8323.  
  8324. Question: 
  8325.  
  8326. I need to ship the User Interface class library DLLs with my application, but 
  8327. they are very large.  Can I rebuild them so I use only what I need? 
  8328.  
  8329. Answer: 
  8330.  
  8331. Yes. To rebuild the User Interface class library DLLs: 
  8332.  
  8333.    1. Change to the ICLUIDLL directory under your install directory. 
  8334.  
  8335.    2. Extract the object files you need from the Open Class static library (in 
  8336.       the LIB directory), using GETOBJS. For example: 
  8337.  
  8338.                GETOBJS ..\LIB\CPPOOC30.LIB
  8339.  
  8340.    3. Identify the .OBJ files you need for the classes you use. If your 
  8341.       application uses any of the classes in a given .OBJ file, you need that 
  8342.       file. Use the cross-reference tables in the Open Class Library Reference 
  8343.       to determine which .OBJ files implement which classes. (The tables list 
  8344.       the .HPP files, but also apply for the .OBJ files.) Note that some 
  8345.       classes are implemented in multiple .OBJ files, which are numbered 
  8346.       sequentially (for example, IRESLIB.OBJ, IRESLIB1.OBJ, and so on); for 
  8347.       these classes, you must include all of these .OBJ files or none of them. 
  8348.  
  8349.    4. Edit the .RSP files and remove the lines for the .OBJ files you don't 
  8350.       need.  (The .RSP files are in the ICLUIDLL directory.) 
  8351.  
  8352.    5. Edit the .DEF files and remove the export entries for the .OBJ files you 
  8353.       don't need.  (The .DEF files are in the ICLUIDLL directory.) 
  8354.  
  8355.    6. Delete the .OBJ files you don't need from the ICLUIDLL directory. 
  8356.  
  8357.    7. Link the remaining .OBJ files, using the .RSP and .DEF files. 
  8358.  
  8359.  For more information on the Open Class library and how to rebuild the library 
  8360.  DLLs, see the Open Class Library User's Guide For information on building your 
  8361.  own runtime library DLLs, see Should I Build My Own C Runtime DLL?. 
  8362.  
  8363.  
  8364. ΓòÉΓòÉΓòÉ 18.4. Should I Bind Runtime Messages to My Application? ΓòÉΓòÉΓòÉ
  8365.  
  8366. Question: 
  8367.  
  8368. Should I bind the runtime message files to my application? What message files 
  8369. do I need? 
  8370.  
  8371. Answer: 
  8372.  
  8373. It depends.  You do not need to bind them if your application runs only on 
  8374. machines where VisualAge C++ is installed, or if all of the following are true: 
  8375.  
  8376.      You do not use the assert, perror, or strerror functions. 
  8377.      You did not compile with the /Tm option to enable the debug memory 
  8378.       management functions. 
  8379.      You do not want compiler-generated trap information. 
  8380.      You do not use any of the class library runtime messages. 
  8381.  
  8382.  If you are shipping your application to other machines that may not have 
  8383.  VisualAge C++ installed, you should probably bind the runtime messages into 
  8384.  the application. You can use MSGBIND to do this. MSGBIND is described in the 
  8385.  User's Guide. 
  8386.  
  8387.  The message files you may need are: 
  8388.  
  8389.  DDE4.MSG        Messages for the C runtime library and for the I/O Stream and 
  8390.                  Complex class libraries. 
  8391.  IBMCRERR.MSG    Messages for regular expressions. 
  8392.  DDE4C01E.MSG    Messages for the Collection class libraries. 
  8393.  CPPOOC3U.MSG    Messages for the User Interface class libraries. 
  8394.  DAXCLS.MSG      Messages for the Database Access class libraries. 
  8395.  
  8396.  The message files are in the HELP subdirectory under your main install 
  8397.  directory.  For information on specifying what messages to bind, refer to the 
  8398.  MSGBIND section in the User's Guide. 
  8399.  
  8400.  
  8401. ΓòÉΓòÉΓòÉ 18.5. Can I Use Multiple C Runtime Libraries? ΓòÉΓòÉΓòÉ
  8402.  
  8403. Question: 
  8404.  
  8405. I don't know which runtime libraries other people will use with my DLL.  Is 
  8406. there any way I can use multiple runtimes? 
  8407.  
  8408. Answer: 
  8409.  
  8410. You can have more than one C runtime (and its associated environment) in an 
  8411. .EXE and its associated DLLs.  However, the following restrictions apply: 
  8412.  
  8413.    1. You can read from and write to a stream opened in another library 
  8414.       environment, but you cannot use freopen or fclose on it. 
  8415.  
  8416.    2. fcloseall, fflushall, and similar functions work only for streams opened 
  8417.       in the environment in which they were called. 
  8418.  
  8419.    3. Signal handling is separate for each environment. 
  8420.  
  8421.    4. When you move from one environment to another, the entry point to the 
  8422.       destination environment must have a #pragma handler statement to ensure 
  8423.       that exception and signal handling functions correctly. 
  8424.  
  8425.    5. If a thread executes in several runtime environments, it may not 
  8426.       completely clean up its thread-specific storage when it terminates. 
  8427.       Normally this is not a problem, but can generate strange results if you 
  8428.       depend on everything being set to default values when you start a thread 
  8429.       (signal handlers, random number seeds, and so on). 
  8430.  
  8431.    6. Each environment has its own errno and _doserrno values. 
  8432.  
  8433.    7. The strtok, putenv, and getenv functions only work within a library 
  8434.       environment. 
  8435.  
  8436.  
  8437. ΓòÉΓòÉΓòÉ 18.6. How Do I Imbed a Copyright Statement? ΓòÉΓòÉΓòÉ
  8438.  
  8439. Question: 
  8440.  
  8441. What is the best way to imbed a copyright statement at the beginning of an 
  8442. executable file or DLL? 
  8443.  
  8444. Answer: 
  8445.  
  8446. Compile a small DOS application with the copyright statement in it, and use it 
  8447. as the DOS stub.  It is put right at the beginning of the .EXE module. This 
  8448. ensures that the copyright is near the beginning of the file, and also sets up 
  8449. the executable so it can issue appropriate statements if it is run under DOS by 
  8450. mistake. 
  8451.  
  8452. The example that follows is similar to the stub used by VisualAge C++, and is 
  8453. based on assembler.  You can create your stub using any DOS assembler or 
  8454. compiler. 
  8455.  
  8456. ;******* Data Segment (copyright statement)
  8457. DSEG    SEGMENT PARA PUBLIC 'DATA'
  8458. __COPYRIGHT DB 0dh,0ah
  8459.        DB  'IBM(R) VisualAge(TM) C++ for OS/2(R), Version 3', 0dh,0ah
  8460.        DB  '(C) Copyright IBM Corp. 1991, 1995.', 0dh,0ah
  8461.        DB  ' - Licensed Material - Program-Property of IBM - All Rights Reserved.', 0dh,0ah
  8462.         DB  0dh,0ah
  8463.         DB  'This program will not run in DOS mode'
  8464.         DB  0dh,0ah
  8465.         DB   24h                        ; End marker for DOS call
  8466.         DB   1ah                        ; EOF marker
  8467. DSEG    ENDS
  8468.  
  8469. ;****** Code segment (Assembler stub to print copyright in DOS)
  8470. CSEG    SEGMENT PARA PUBLIC 'CODE'
  8471.         ASSUME CS:CSEG,SS:STACK         ;Already set by dos loader
  8472.  
  8473. ENTPT   PROC    FAR                     ;entry point from DOS
  8474.         PUSH    DS                      ;set up the stack to have
  8475.         XOR     AX,AX                   ; the double word vector so the
  8476.         PUSH    AX                      ;  far return will go back to DOS
  8477.  
  8478.         MOV     AX,DSEG                 ;set up addressability to
  8479.         MOV     DS,AX                   ; the data segment
  8480.         ASSUME  DS:DSEG                 ;tell assembler what I just did
  8481.  
  8482. ;****** Call DOS to print the copyright notice
  8483.         MOV     DX,OFFSET DS:__COPYRIGHT
  8484.         MOV     AH,9
  8485.         INT 21h
  8486.  
  8487.         RET                             ;Return to DOS
  8488. ENTPT   ENDP
  8489. CSEG    ENDS
  8490.  
  8491. ;****** Stack segment
  8492. STACK   SEGMENT PARA STACK 'STACK'
  8493.         DB      512 DUP(?)              ;512 Byte Stack
  8494. STACK   ENDS
  8495.  
  8496. ;****** Mark the entry point
  8497.         END     ENTPT
  8498.  
  8499.  
  8500. ΓòÉΓòÉΓòÉ 19. What If I Still Have Questions? ΓòÉΓòÉΓòÉ
  8501.  
  8502. Question: 
  8503.  
  8504. I've looked through this FAQ, and I can't find the answer to my problem.  What 
  8505. do I do now? 
  8506.  
  8507. Answer: 
  8508.  
  8509. Contact VisualAge C++ Service and Support. This section tells you how. 
  8510.  
  8511. Telephone support in the USA and Canada 
  8512.  
  8513. VisualAge C++ has a free 60-day Getting Started period (GSP) to help you with 
  8514. installation, usage, and how-to problems. Call 1-800-237-5511.  The 60-day 
  8515. period starts on the date of your first call, and is offered 9-5 (in your time 
  8516. zone), Monday through Friday. If you need service outside of these hours during 
  8517. the GSP, service charges apply. Call 1-800-237-5511 for details. 
  8518.  
  8519. After your 60-day GSP, we offer a wide menu of service options tailored to a 
  8520. full spectrum of customers needs. Again, call 1-800-237-5511 for details. 
  8521.  
  8522. Quite often, you may not need technical support, for example when you have 
  8523. questions about CSD levels and availability, registration cards, or beta tests. 
  8524. In recognition of these questions, our automated response system contains a 
  8525. wealth of useful information.  You can also receive much of that information by 
  8526. fax. The response system is available 24 hours a day, 7 days a week. Call 
  8527. 1-800-668-2853.  (Outside of North America, you can access the same system at 
  8528. 416-448-4363.) 
  8529.  
  8530. Telephone support outside North America 
  8531.  
  8532. For local country support, please contact your IBM branch for details. 
  8533.  
  8534. Electronic support - worldwide 
  8535.  
  8536. You can also contact VisualAge C++ Support electronically. There is no charge 
  8537. for this service, other than what you normally pay for your electronic access. 
  8538.  
  8539.      Compuserve (OS2DF1) 
  8540.  
  8541.      INTERNET 
  8542.  
  8543.         -  va_cpp@vnet.ibm.com 
  8544.         -  workframe@vnet.ibm.com  for WorkFrame-specific questions 
  8545.  
  8546.      IBMLink/ServiceLink 
  8547.  
  8548.         -  VA C++ forum 
  8549.         -  ETR (electronic reporting of problems) 
  8550.  
  8551.      TalkLink 
  8552.  
  8553.         -  VA C++ forum 
  8554.         -  ETR (electronic reporting of problems) 
  8555.  
  8556.  If you frequent the Internet, you can also contact other knowledgeable 
  8557.  VisualAge C++ users on the USENET newsgroups. (VisualAge C++ discussions often 
  8558.  appear in the comp.os.os2.programmer hierarchy.) 
  8559.  
  8560.  Other defect reporting channels in the USA and Canada 
  8561.  
  8562.  You can also report possible VisualAge C++ code-related problems using any of 
  8563.  the following methods: 
  8564.  
  8565.  FAX         1-800-426-8602 
  8566.  MAIL 
  8567.  
  8568.                           IBM Corp
  8569.                           Personal Systems Support Family
  8570.                           11400 Burnet Road
  8571.                           Internal Zip 2901
  8572.                           AUSTIN, TX  78758
  8573.  
  8574.  ELECTRONIC  CompuServe - 76711,611 
  8575.  
  8576.  Other defect reporting channels outside the USA and Canada 
  8577.  
  8578.  Other IBM countries offer mail-in and fax support. Please contact your IBM 
  8579.  branch for details.