Win32 Programming Guidelines
This chapter describes how to use the compiler to create Win32 and Win32s applications. For information about:- Creating 16-bit Windows programs, see Win16 Programming Guidelines.
- Using the IDDE to create applications, see the User's Guide and Reference.
- The Win32s API, see the included Microsoft documentation.
What's in This Chapter
- How creating 32-bit Windows applications differs from creating 16-bit Windows applications.
- The distinctions between 32-and 16-bit graphical environments and Digital Mars' support for Win32, Win32s and development tools.
- How to compile and link various Win32 applications, including applications that use MFC.
- How to compile and link Win32s applications.
- How to recompile and relink 16-bit applications to be 32-bit Windows applications.
Some Basic Information
The following will help you understand the information in this chapter.- Windows 3.1 is a 16-bit graphical environment that runs on DOS, which is a 16-bit operating system. For simplicity, Windows 3.1 (and 3.0) will be referred to as Win16.
- Windows 95 and Windows NT (Windows New Technology) are 32-bit operating systems. For simplicity, Windows 95 and Windows NT will be referred to as Win32.
- Win32s is an NT emulator, or operating system extension, that allows you to run Win32 applications on a Win16 host.
- 32-bit applications for Windows are referred to as Win32 applications. 16-bit applications for Windows are referred to as Win16 applications.
- The Win32 Applications Programming Interface (API), the graphical environment for Windows 95 and NT, is very similar to the Windows 3 graphical environment.
About Win32s
Win32s is an NT emulator or operating system extension that allows you to run Win32 applications on a Windows 3.1 host. The "s" in Win32s stands for Win32 subset: Win32s supports almost all Win32 API features.Note: Win32s applications built with C++ Version 7 will only run on version 1.15 and above of Win32s.
Advantages of Win32s over Win16
Win32s, included with Digital Mars C++, gives you the following advantages over conventional Win16 applications:- The ability to run 32-bit programs under Windows 3.1.
- The ability to manipulate data and perform calculations in 32-bit mode, which improves the performance of applications that are data-, memory-or calculation intensive, such as spreadsheets, simulation packages, desktop publishing and CAD packages.
- Features previously unavailable in Windows 3.1, such as sparse memory.
Key Win32s features
Many features are available through the Win32s Applications Programming Interface (API), such as:- Complete window interface
- All graphics functions (GDI)
- Object linking and embedding (OLE), version 1.0
- Memory-mapped files (backed by disk image)
- Network support, such as Netbios and named pipes
- Common dialogs
- Named shared memory
Building Win32 and Win32s Applications
Digital Mars C++ includes a set of tools that make it easy to create and debug Win32 and Win32s applications from either the command line or within the integrated environment. By setting switches, all the tools- compiler, linker, resource compiler, and resource editors- generate the correct type of 32-bit application. The following is basic information useful for building Win32 and Win32s applications:- The compiler generates Microsoft OMF object files. OPTLINK does not use Microsoft COFF files.
- In order to compile with the correct startup code, Win32 and Win32s executables need to contain a WinMain() entry point. This causes the compiler to generate a reference to the _acrtused startup function.
- Use a module definition file to define explicitly as many criteria as possible. To establish the proper executable for NT, for example, place EXETYPE NT in your module definition file, and use the SUBSYSTEM[WINDOWS] keyword. For further information on Win32 .def files, see Definition File Directives.
- The -mn switch is the memory model switch for Win32 applications available from the command line interface. This is the 32-bit flat model, essentially a "small model" with 4GB addressing.
- Creating a resource file for a Win32 application is no different from creating one for a Win16 application. The resource compiler takes a resource definition file and produces a 32-bit .res file. Having 16-bit compatibility with the .res files helps you build Win32 applications from Win16 applications.
- When creating Win32 applications, OPTLINK provides transparent linking and binding of .res files to an .exe file. 16-bit .res files are converted to 32-bit during the link process.
Note: To developers using NT: OPTLINK (the linker) does not accept COFF resource files, but does accept standard Microsoft resources files.
Compiling Win32 Executables
This section explains how to create various kinds of Win32 executables.Compiling with MFC 3.x
If your Win32 application uses MFC 3.x libraries, see the "READ ME" file included with the distribution for a list of the options, libraries, and #defines you need to build various targets with the latest MFC release. Note that, for all MFC 3.x libraries, you need to compile with the NT (-mn) memory model.Compiling Win32 DLLs
To compile Win32 DLLs, use these compiler options:-mn -WDTo write a Win32 DLL, you need to specify the entry point DllMain(). When the compiler detects a call to DllMain() in a 32-bit compilation, it generates a reference to the _acrtused_ dll startup function, and links with the appropriate startup code.
Unlike previous versions of C++, this startup code calls static constructors and performs other initialization steps before calling DllMain().
Converting older Win32 DLLs
To convert Win32 DLLs built with previous versions of C++ to work with this version, make the changes listed below:- Remove any references to #pragma startaddress.
- Provide a reference to DllMain().
- If the entry point routine was not DllMain(), write a new DllMain() stub that calls the entry point routine upon process_attach().
- If you need to write code that is called prior to static construction, check the source for the run-time library to determine what calls are necessary to initialize the library. Then use #pragma startaddress to specify the entry point, and call the initialization routines as needed.
Building Console Applications
A console application is a character mode application that runs under Windows 95 or NT. Digital Mars C++ supports console mode applications.To compile console applications, use the -mn compiler option, and specify the SUBSYSTEM CONSOLE directive in the .def file.
Startup code for console applications
When the compiler detects a call to main() in a 32-bit compilation, it generates a reference to the _acrtused_ con startup function, and links with the appropriate startup code. You no longer need to explicitly link in cc.obj, as with previous versions of C++; it is now part of snn.lib.Compiling Win32s Executables
To compile Win32s executables, use the -mn and -WA compiler options. Note: HP Dashboard does not support Win32s. If you try to debug a Win32s application under Dashboard, the debugger receives a GPF message from the application being debugged.Compiling Win32s DLLs
To compile Win32s executables, use the -mn and -WA compiler options.Note: To create libraries from Windows NT System DLLs (kernel32.dll, for example), use the IMPLIB utility and specify the /system switch. IMPLIB is available only from the command line, not via the IDDE.
Win32 Definition File Directives
This section lists the directives used in definition files for Win32 programs. For descriptions of these directives see Definition File Directives.NAME name [BASE=number] LIBRARY name [ BASE= number | PROCESSINIT | PROCESSTERM | THREADINIT | THREADTERM ] DESCRIPTION 'descriptive line' EXETYPE NT HEAPSIZE [number, commit] STACKSIZE [number, commit] STUB 'filespec' SUBSYSTEM [ NATIVE | WINDOWS | CONSOLE | POSIX ] VERSION number[. number] CODE [READ] [WRITE] [EXECUTE ] [SHARED] DATA [READ] [WRITE] [EXECUTE] [SHARED] SEGMENTS { name [CLASS 'class'] [READ] [WRITE] [EXECUTE] [SHARED] } IMPORTS { [internal=] externalfile. func } EXPORTS { parms [=intname] [@number [NONAME]] [CONSTANT]}
Recompiling Win16 Applications for Win32
To convert to a Win32 or Win32s application to a Win16 application created with the C/C++ compilers, try these suggestions:- In order for Win32 to interpret handles properly, declare all handles as HANDLE, HINSTANCE, or similarly. Win32 will not properly interpret handles that use int or WORD. The sample program ZOOM illustrates how to declare handles correctly.
- When you compile with the -mn or -mf memory models, the following keywords are ignored: __far, __huge, __interrupt, __loadds, and __handle.
- In all Windows NT code, SS==DS==ES at all times; otherwise the NT API functions themselves can fail. When using the -mn or -mf memory models, SS==DS==ES automatically for all functions, including run-time library functions.
- Some Win16 API functions are not supported by Win32. For example, replace calls to MoveTo() with MoveToEx() calls.
- Replace all machine-specific code with non-machine specific C or C++ functions to make your code as portable as possible. For example, Use time() and localtime() instead of calling int86().
- For message passing and other functions that use wParam, declare parameters with WPARAM type. This is especially true for message passing between windows, such as with SendMessage(). Using the WPARAM type allows the parameter to be interpreted as a 16-bit value for Win16 and 32-bit value for Win32. Functions declared as lParam are dwords in both implementations.
- Win32s executables that call 16-bit DLLs need to use the Universal Thunk mechanism to communicate.
- For mixed model programs, perform these steps:
- Select the Large memory model.
- Rebuild the project as a Win16 application.
- If the project builds and runs correctly, convert it to Win32, but first make any of the adjustments previously mentioned.
Converting Non-Digital Mars Win16 Applications to Win32 Applications
The following information will help you convert 16-bit programs developed with other programming tools to be Win32 or Win32s applications.Start with a bug-free Win16 application. Be sure your Win16 application compiles and runs without any compiler or linker errors or warnings.
Convert the application to be a Win16 application. For instructions on porting code from Borland or Microsoft, see Switching to Digital Mars C++. Be sure the converted program compiles and runs with Digital Mars C++ without any errors or warnings.
Save the original source code and makefile, preferably in another project directory. Now that the application is a Digital Mars Win16 application, convert it to Win32, following the hints above.
Finally, after a clean build, preferably with no warnings, test the application.
If you are targeting both Win32 and Win32s, you should test these applications thoroughly in both environments, as there are a number of significant differences between Win32 and Win32s.