PRODUCT : Borland C++ NUMBER : 728 VERSION : 2.0 OS : DOS DATE : October 19, 1993 PAGE : 1/6 TITLE : Issues with Petzold's Programming Windows and BC++ COMPILING IN C++ ---------------- When using Borland C++, problems with the examples from Charles Petzold's Programming Windows will often result from compiling them unmodified in C++ mode. Here are some symptoms of this problem which you may run across when compiling the examples from Programming Windows: 1. HELLOWIN example does not display the text until it is painted a second time 2. KEYLOOK example hangs with hourglass 3. CLOVER example does not print anything 4. GetSystemMetrics (or other API functions) give unusual results The quick and obvious solution to this problem is to switch the compiler back to C mode. However, it IS quite possible to compile these programs in C++ by making some minor modifications. The Petzold DEF files do not contain the C++ name mangled names for the exported functions. If the programs are to be compiled as C++, the _export modifier should be used for any functions to be exported. The function entries in the EXPORTS section of the DEF file can then be removed. Following this method, the declaration for a sample exported function would be: long FAR PASCAL _export WndProc (HWND, WORD, WORD, LONG) ; An alternative way to export the functions would be to leave the EXPORTS entry in the DEF file as is and declare the function as extern "C" in the C++ source code. This will "turn off" name mangling for that function and thus the identifier for that function will match the one exported in the DEF file. Following this method, the declaration for a sample exported function would be: extern "C" long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ; COMPILING IN C -------------- PRODUCT : Borland C++ NUMBER : 728 VERSION : 2.0 OS : DOS DATE : October 19, 1993 PAGE : 2/6 TITLE : Issues with Petzold's Programming Windows and BC++ The same symptoms described in the section above can occur when compiling in C mode if you have not included the program's .DEF file when linking your program. If you are using BC or BCX, this means you need to have a project file that includes your .DEF file in addition to your .C file (and .RC file if one exists). If you are using BCC or BCCX and calling TLINK directly, this means that you have forgotten to include the .DEF file on your TLINK command line. See the Borland C++ User's Guide for more information on TLINK. SYSMETS EXAMPLE --------------- In the SYSMETS2 example (page 73), max and min can return incorrect values because NUMLINE returns an unsigned int rather than an int. The problem has to do with the NUMLINES macro defined at the top of SYSMETS.H (page 59). As required by ANSI, sizeof returns an unsigned. This, combined with the max and min macros, results in nVscrollPos never appearing to be less than 0. Changing the NUMLINES macro to: #define NUMLINES ((int)sizeof sysmetrics/(int) sizeof sysmetrics[0]) will resolve this problem. In addition, it should be noted that the max and min macros are not defined in the C++ language. The reason for this omission is to allow C++ programmers to overload the function names min and max. To compile this example as C++, the min and max macros should be copied from windows.h directly into the SYSMETS2.C source file. DDEPOP / SHOWPOP EXAMPLE ------------------------ Line 573 of DDEPOP.C declares a character array in the function PostDataMessage as follows: char szPopulation [10]; This line should read: char szPopulation [11]; PRODUCT : Borland C++ NUMBER : 728 VERSION : 2.0 OS : DOS DATE : October 19, 1993 PAGE : 3/6 TITLE : Issues with Petzold's Programming Windows and BC++ Without this modification, a UAE will occur when running its client program SHOWPOP.EXE. Note that there is a similar declaration on line 239 in the function ServerProc. Do not confuse this declaration with the one on line 573. Since the array szPopulation is never used in the function ServerProc, you may remove the declaration of szPopulation from line 239. BTNLOOK EXAMPLE --------------- On line 24 of BTNLOOK.C, change BS_USERBUTTON to BS_OWNERDRAW. BS_USERBUTTON is not a style documented by Microsoft for Microsoft Windows 3.0. READ VERSUS _LREAD ------------------ Microsoft Windows defines a set of functions for file management which are separate from the file management functions used in traditional DOS applications. Microsoft C 6.0 happens to allow the free mixture of Windows file handles created with OpenFile() and standard DOS file handles created with open(). This "feature" is undocumented and therefore not standard Windows programming. In Borland C++, Windows file handles and DOS file handles are not the same and cannot be freely mixed in calls to functions. Some of the Programming Windows examples make calls to OpenFile() and use the resulting handle in a call to read(). To make such examples work when compiling with Borland C++, it will be necessary to commit your program to one system of file management or the other. If you choose to use OpenFile(), calls to read() and write() should be converted to calls to _lread() and _lwrite(). If you choose to continue with calls to read() and write(), the call to OpenFile should be converted to a call to open(). MAKE FILES ---------- The make files provided for the examples in Programming Windows were designed with Microsoft C in mind and are not compatible with Borland C++. Here is an example Borland makefile which can be used for the simpler single file Windows programs. PRODUCT : Borland C++ NUMBER : 728 VERSION : 2.0 OS : DOS DATE : October 19, 1993 PAGE : 4/6 TITLE : Issues with Petzold's Programming Windows and BC++ --- cut here --- # # Borland C++ makefile for Charles Petzold's Programming Windows # examples # # Instructions: 1) Change "file" to the name of the example # program being compiled. # 2) If the example you are compiling does # not have an RC file, remove all # references to "file.res". # 3) Modifications will be necessary for # multifile examples. Consult the # Borland C++ User's Guide. # file.exe : file.obj file.def file.res bccx -W file.obj rc file.res file.exe # if the example does not contain an RC file, remove # "file.res" from the line above file.obj : file.c bccx -W -c file.c # if the example does not contain an RC file, remove the rule # below file.res : rc -r file.rc --- cut here --- Note that a DEF file called file.def would be linked in automatically. If file.def does not exist, default values would be used. More complex, multifile examples are most easily built using the project manager of BCX or BC. Select "Open Project" from the "Project" menu. Give your project a name (this will also be the name of your executable). A project window will appear. Select the project window and hit the "insert" key. You will be prompted for the names of the source files to be included in your project. Also remember to include your RC file and your DEF file in your project. After all items are entered into your project, select "Windows App" under the "Options | Application" menu. You PRODUCT : Borland C++ NUMBER : 728 VERSION : 2.0 OS : DOS DATE : October 19, 1993 PAGE : 5/6 TITLE : Issues with Petzold's Programming Windows and BC++ may now compile the program by selecting "Build All" from the "Compile" menu. If you require or prefer to use a make file rather than the project manager, the utility PRJ2MAK can be used to convert the project file described above into a Borland Make-compatible make file. More information on Borland Make and the Project Manager can be found in the Borland C++ User's Guide. Information on PRJ2MAK can be found in the document UTIL.DOC which you can find in your DOC subdirectory of Borland C++. WARNINGS -------- Many of the examples in Programming Windows will issue warnings which can be ignored, such as the following: Warning file.c 57: Parameter 'lpszCmdParam' is never used in function WinMain(unsigned int,unsigned int,char far*,int) The compiler correctly flags an unused parameter as a potential problem in the code. In most programs, it would be wasteful to define a function which is passed parameters which are never used. However, the parameters for a Windows call back function must all be declared so that Windows can pass messages to your program. This warning message can be eliminated by inserting the line: #pragma argsused right before the declaration of the function. Another common warning is the following: Warning: Attempt to export non-public symbol WndProc This indicates that there is a function exported in your DEF file which was not found in your program by the linker. This warning should not be ignored since, in many cases, attempting to export a nonexistent symbol implies that you may have missed exporting a symbol which DOES exist. It may be that you are compiling your PRODUCT : Borland C++ NUMBER : 728 VERSION : 2.0 OS : DOS DATE : October 19, 1993 PAGE : 6/6 TITLE : Issues with Petzold's Programming Windows and BC++ program in C++ without modifying the example (see "COMPILING IN C++" at the top of this document). DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.