From One Code Base to Many Platforms Using Visual C++

Microsoft Corporation

Introduction

Multiple-platform development is a hot issue today. Developers want to be able to support diverse platforms such as the Microsoft® Windows® version 3.x, Microsoft Windows NT®, and Microsoft Windows 95 operating systems, and Apple®, Macintosh®, UNIX, and RISC (reduced instruction set computer) machines. Until recently, developers wanting to build versions of their application for more than one platform had few choices:

Today, however, a new choice exists. Developers can use their existing code written to the Windows API and, using tools available from Microsoft and third parties, recompile for all of the platforms listed above. This paper looks at the methods and some of the issues involved in doing so.

Macintosh: The Most Difficult Case

Currently the most lucrative market for graphical user interface (GUI) applications, after Microsoft Windows, is the Apple Macintosh. However, vast differences separate these wholly different operating systems, requiring developers to learn new APIs, programming paradigms, and tools. Generally, Macintosh development requires a separate code base from the Windows sources, increasing the complexity of maintenance and enhancement.

Because porting code from Windows to the Macintosh can be the most difficult porting case, this paper concentrates in this area. In general, if your code base is sufficiently portable to enable straightforward recompiling for the Macintosh (excluding any platform-specific, or "edge" code, you may elect to include), you'll find that it will come up on other platforms easily as well.

Microsoft Visual C++® Cross-Development Edition for Macintosh (Visual C++ for Mac™) provides a set of Windows NT– or Windows 95–hosted tools for recompiling your Windows code for the Motorola 680x0 and PowerPC processors, and a portability library that implements Windows on the Macintosh. This allows you to develop GUI applications with a single source code base (written to the Win32® API) and implement it on Microsoft Windows or Apple Macintosh platforms.

Figure 1, below, illustrates how Visual C++ for Mac works. Your source code is edited, compiled, and linked on a Windows NT– or Windows 95–based (Intel) host machine. The tools create 68000 and PowerPC native code and Macintosh resources. An Ethernet-based or serial transport layer (TL) moves the resulting binaries to a Macintosh target machine running remotely. The Macintosh application is started on the Macintosh and debugged remotely from the Windows-based machine.

Figure 1. Cross-development for the Macintosh

Now that Apple has two different Macintosh architectures to contend with (Motorola 680x0 and PowerPC) portability is particularly important.

Porting can involve several steps, depending on whether you are working with old 16-bit applications or with new 32-bit sources. In general, the steps to a Macintosh port are as follows:

  1. Make your application more portable by following some general portability guidelines. This will help insure not only portability to the 680x0-based Macintosh machines, but also to the newer, more powerful PowerPC machines that are based on a RISC chip.

  2. Port your application from Windows 16-bit code to 32-bit code. This may be the most complex and time-consuming part of the job.

  3. Segregate those parts of your application that are unique to Windows from similar implementations that are specific to the Macintosh. This may involve using conditional compilation or it may involve changing the source tree for your project.

  4. Port your Win32 API code to the Macintosh by using the portability library for the Macintosh and Visual C++ for compiling, linking, and debugging.

  5. Use the Microsoft Foundation Class Library (MFC) version 4.0 to implement new functionality such as OLE 2.0 containers, servers, and clients or database support using open database connectivity (ODBC). Code written using MFC is highly portable to the Macintosh.

  6. Write Macintosh-specific code to take advantage of unique Macintosh features, such as Apple Events or Publish and Subscribe.

Other Platform Strategies

As mentioned earlier, the Macintosh represents the extreme case. Other platforms can be much simpler to port to.

Windows 3.1, Windows NT, and Windows 95

The chief challenge among the families of Windows operating systems is the break from 16 bits (Windows 3.11 and Windows for Workgroups 3.11 operating system with integrated networking) to 32 bits (Windows NT and Windows 95). In general, 16-bit and 32-bit code bases are somewhat incompatible, unless they are written using MFC. Developers have the choice of branching their sources into two trees, or migrating everything to 32 bits. Once the Win32 choice has been made, how are legacy platforms to be run (that is, machines still running Windows 3.11)? The obvious choice is to use the Win32s® API libraries, which thunk 32-bit calls down to their 16-bit counterparts.

RISC

Developers who want their applications to be able to take advantage of the hot new RISC hardware, such as DEC Alpha AXP machines, can use the special multiple platform editions of Visual C++. These include versions for the MIPS R4000 series of processors as well as the aforementioned DEC Alpha AXP chip and the Motorola Power PC. These toolsets run under Windows NT 3.51 and create highly optimized native Win32 applications for DEC Alpha and Motorola PowerPC platforms.

Developers who have recompiled their Win32 sources using these toolsets are amazed at how simple it is. Since the operating system is identical on all platforms, and the tools are identical, little work has to be done in order to achieve a port. The key difference in the RISC machines from Intel is the existence of a native 64-bit integer, which is far more efficient than on 32-bit (that is, Intel) processors.

UNIX

Microsoft works closely with two third-party UNIX tools providers, Bristol Technology and Mainsoft Corporation, to allow developers to recompile their Win32-based or MFC-based applications for UNIX. Developers seeking additional information should contact those companies directly.

The API Decision

You'll have to decide early on whether to write to the native API (Win32) or to MFC. In general you'll find MFC applications will port more quickly than Win32 applications. This is because one of the intrinsic benefits of an application framework is an abstraction of the code away from the native operating system to some extent. This abstraction is like an insurance policy for you. However, developers frequently have questions about MFC, such as:

General Portability Guidelines

All porting will be easier if you begin today writing more portable programs. Following some basic portability guidelines will make your code less platform-specific.

Never Assume

Never assume anything. Particularly, don't make assumptions about the sizes of types, the state of the machine at any time, byte ordering, or alignment.

Don't assume the size of primitive types, because these have different sizes on different processors. For example, an int is two bytes in Win16 and four bytes in Win32. At all costs, avoid code that relies on the size of a type. Use sizeof() instead. To determine the offset of a field in a structure, use the offsetof() macro. Don't try to compute this manually.

Use programmatic interfaces to access all system or hidden "objects," for example, the stack or heap.

Beware of Byte-Ordering Problems

Parsing data types to extract individual bytes or even bits can cause problems when porting from Windows to the Macintosh unless you are careful to write code that doesn't assume any particular byte order. LIMITS.H contains constants that can be used to help write platform-independent macros to access individual bytes in a word.

No Assembler Code

This may seem obvious, because nothing could be less portable than assembly language. Compilers, such as Microsoft Visual C++, that provide inline assemblers make it easy to slip in a little assembler code to speed things up. If you want portable code, however, avoid this temptation. It may not be necessary. Modern compilers can often generate code as good as hand-tuned native assembler code. Our own research at Microsoft indicates that performance problems are more often the result of poor algorithms than they are of poor code generation. Indeed, with RISC machines, hand-turned native assembler code may actually be worse than machine-generated code, due to the complexity of instruction scheduling and picking register usage.

Write all routines in C first; then, if you absolutely need to rewrite one in assembler, be sure to leave both implementations in your sources, controlled by conditional compiles, and keep both up to date.

ANSI

A major goal of American National Standards Institute (ANSI) C/C++ is to provide a portable implementation of the language. Theoretically, code written to strict ANSI C compliance is completely portable to any compiler that implements the standard correctly. Microsoft Visual C++ provides a compiler option (/Za) to enable strict ANSI compatibility checking.

Microsoft Visual C++ provides some language features that are in addition to ANSI C, such as four-character constants and single-line comments. Programs that use the Microsoft C extensions should be portable to all other implementations of Microsoft Visual C++. Thus, you can write programs that use four-character constants, for example, and know that your program is portable to any 16-bit or 32-bit Microsoft Windows platform or to the Macintosh.

Avoid Packing Structures

Compilers normally align structures based on the target machine architecture; some RISC machines, such as the MIPS R4000, are particularly sensitive to alignment. Alignment faults may generate run-time errors or, instead, may silently and seriously degrade the performance of your application. For portability, therefore, avoid packing structures. Limit packing to hardware interfaces and to compatibility issues such as file formats and on-disk structures.

Use Function Prototypes

Using function prototypes is mandatory for fully portable code. All functions should be prototyped, and the prototype should exactly match the actual function declaration.

Porting from Win16 to Win32

Following the guidelines above will make your code a lot more portable. However, if you have 16-bit Windows code, your first step is to make it work properly under Win32. This will require additional changes in your sources.

Code written for Win32 can run on any version of Windows, including on the Macintosh, using the portability library. Portable code should compile and execute properly on any platform. Of course, if you use APIs that only function under Windows NT, they will not work when your application runs under Windows 3.x. For example, threads work under Windows NT but not under Windows 3.11. Those types of functionality differences will have to be accounted for in the design of your application.

Chief among the differences between Win16 and Win32 is linear addressing. That means pointers are now 32 bits wide and the keywords near and far are no longer supported. It also means code that assumes segmented memory will break under Win32.

In addition to pointers, handles and graphic coordinates are now 32 bits. WINDOWS.H will resolve many of these size differences for you, but some work is still necessary.

Steps to Port from Win16 to Win32

What follows is a brief overview of the steps you follow to port from Win16 to Win32. This topic is covered in far greater detail in the article "Porting 16-Bit Code to 32-Bit Windows," in the Visual C++ 4.2 documentation in the MSDN Library.

Compile Strategy

The recommended strategy to get your application running under Win32 is to recompile for 32 bits, noting error messages and warnings. Next, replace complex procedures and assembly language routines with stub procedures. Then, make your main program work properly using the techniques above. Finally, replace each stubbed-out procedure with a portable version.

Differences Between Windows and the Macintosh

After you successfully convert your Windows-based program from 16 bits to 32 bits, you're ready to embark on porting it to the Macintosh. Because significant differences exist between the two platforms, this task can appear daunting. Before you can begin to port your application, you need to better understand these differences. The Macintosh is differentiated from Windows in three general areas:

These areas of difference are described below. Porting issues that accompany these differences are discussed in the section titled "Porting from Win32 to the Macintosh."

Programming Model Differences

The Windows and Macintosh APIs are completely different. For example:

Because of the differences between the two platforms, porting a Windows-based application to the Macintosh can be monumental task without powerful tools.

Processor Differences

Windows has always run on Intel x86 processors (until Windows NT), and the Macintosh has run on Motorola 680x0 processors (of course, the PowerPC-based Macintosh is now available as well). Differences between the processor families include addressing and byte ordering, in addition to the more expected differences like opcodes, instruction sets, and the name and number of registers.

Addressing

The Intel 8086 processor, from which subsequent 80x86 processors are descended, used 16-bit addresses, which unfortunately allowed only 65,536 bytes of memory to be addressed. To allow the use of more memory, Intel implemented a segmented memory architecture to address one megabyte (2^20 bytes) of memory that used an unsigned 16-bit segment register and an unsigned 16-bit offset. This original Intel scheme has been extended to allow much larger amounts of memory to be addressed, but most existing Intel-based programming relies on separating code and data into 64K segments.

Although all Intel x86 processors since the 80386 have used 32-bit addressing, for compatibility reasons Microsoft Windows 3.x is actually a 16-bit application, and all Microsoft Windows-based applications had to be written as 16-bit applications. That meant, for example, that most pointers and handles were 16 bits wide. With the advent of Microsoft Windows NT, which is a true 32-bit operating system, all native applications are 32-bit applications, which means that pointers and handles are 32 bits wide. Because Windows NT uses linear addressing, programs can share up to 4 gigabytes of memory.

In contrast, the Motorola 68000 and PowerPC processor have always provided the ability to address a "flat" 32-bit memory space. In theory, a flat memory space of this kind simplifies memory addressing. In practice, because 4-byte addresses are too large to use all the time, Macintosh code is generally divided into segments no larger than 32K.

Byte ordering

Microsoft Windows and Windows NT run only on so-called "little-endian" machines—processors that place the least significant byte first and the most significant byte last. In contrast, the Motorola 680x0 and PowerPC (a so-called "big-endian" architecture) place the most significant byte first, followed by the next most significant byte, and so on, with the least significant byte last.

Compilers normally handle all details of byte ordering for your application program. Nevertheless, well-written portable code should never depend on the order of bytes.

User Interface Differences

Microsoft Windows and the Macintosh present quite different user interfaces in many key areas, including menus, filenames, and multiple-document interface (MDI) applications.

Menus

Only one menu bar exists on the Macintosh, and it is always in the same place, regardless of the number or arrangement of windows on the screen. The "active window" contains the menu, which dynamically changes as necessary when different windows are made active. Windows, on the other hand, gives each top-level window its own menu. In addition, under MDI, each child window can also have its own menu. MDI is discussed in greater detail below.

Macintosh applications generally have an "Apple menu" (the leftmost menu) that contains all the installed Desk Accessories and usually contains an About entry for the application. Under System 7, the extreme right side of the Macintosh menu contains an icon for Apple's Balloon Help and the Application menu for switching between applications.

Windows-based applications always have a System menu at the upper-left corner of their top-level window. This menu contains system-level functions for sizing, moving, and closing the window, as well as an item that calls the Task Manager for switching applications.

Generally, Windows-based applications contain keyboard equivalents in their menus. These are underlined letters in each menu entry that the user can select with the keyboard in lieu of the mouse. This, however, is convention rather than requirement. Although some Macintosh applications have these equivalents, most do not.

Filenames

Filenames and pathnames represent one of the most fundamental differences between Windows and the Macintosh, as well as perhaps the one most difficult to deal with. Many programmers report dealing with filenames as the area of porting in which the most time and energy is spent.

Your Windows-based application probably already handles (and expects) filenames such as "C:\ACCTG\DATA\SEPT93.DAT." Applications for the MS-DOS and Windows operating systems are bound by the traditional 8.3 filename format. Macintosh applications, on the other hand, can handle filenames such as "September, 1993 Accounting Data."

Multiple document interface Windows

MDI windows allow for multiple child windows within the borders of a top-level window (the "MDI frame"). Many Windows-based applications, such as the Microsoft Word word processor for Windows, are MDI applications. Characteristic of MDI applications are clipped child windows that can be minimized to an icon within the MDI frame. Each MDI child window can also have its own menu.

The Macintosh does not support MDI windows. An application can have multiple windows open; those windows, however, cannot be made into icons, and they share a common menu. Depending on the application, this difference may necessitate significant redesign for a Macintosh port.

Porting from Win32 to the Macintosh

Porting your Win32-based application to the Macintosh may be as simple as recompiling with Visual C++ Cross-Development Edition for the Macintosh. It's more likely, however, that some parts of your application will need some revision before it works correctly on both platforms. The Visual C++ portability library implements most, but not all, of the Win32 API on the Macintosh. Many of the functions not implemented relate to Windows features that are either not meaningful or not possible on the Macintosh.

Porting your code requires that you understand those API differences and make appropriate changes where necessary. Many of these differences are discussed below, although the list is not complete. For greater details, see the Microsoft Visual C++ Cross-Development Edition for the Macintosh documentation.

File System

Possibly the greatest amount of work you'll do to port your application will be in dealing with file system differences. Naming for files and paths is different on the two systems, and the Macintosh has file attributes and features that don't exist under Windows. You'll want to familiarize yourself with how the Macintosh handles files before you attempt to port your application.

Code that parses MS-DOS-style paths will need to be completely rewritten to run on the Macintosh. You can use the portability library functions WrapFile and UnwrapFile to provide direct access to the Macintosh file system APIs. WrapFile takes a Macintosh FSSpec and stores it in a formatted data buffer for internal manipulation. You can then use this data buffer in place of a path/filename combination in the rest of your Windows-based program. UnwrapFile takes the formatted data buffer and returns a Macintosh FSSpec filename.

You'll also want to allocate larger buffers for filenames to account for longer Macintosh filenames. This is a change you'd probably make anyway, since all new Microsoft operating systems are supporting long filenames (such as Windows 95 and Windows NT with New Technology file system [NTFS] volumes).

Resources

On the Macintosh, everything in your application program is a resource: code, data, dialog boxes, bitmaps, and so forth. In Windows, resources are objects such as icons, dialog boxes, and menus. Code and data are not usually resources. Microsoft Visual C++ converts your Windows resources and objects to the appropriate Macintosh resources. You build, modify, and compile your resources as you would for your Windows-based program. You can also create and link Macintosh-specific resources into your Macintosh executable file.

Create and edit all your resources in Visual C++. After your executable file is on the target Macintosh, you can use ResEdit to tweak your resources. However, changes made with ResEdit won't be reflected in the source files or in the next build of your program. Being able to use ResEdit on resources is handy for creating localized versions of your application, because the changes do not require you to recompile your sources.

Graphics (GDI)

Most GDI functions should work on the Macintosh under the portability library, but there are some differences between Windows and the Macintosh models.

Pens and brushes

Windows has both pens and brushes, but the Macintosh has only pens, so the GDI APIs in the portability library emulate Windows brushes. Pens on the Macintosh are square, and pens in Windows are rounded. On wide pen strokes, end points and line joins will be different under the portability library than they are under Windows. If your application depends on square line joints, you will need to call the Macintosh Toolbox directly to use true Macintosh-style pens.

Multiple-monitor support

One of the clever features of the Macintosh is its ability to support multiple monitors. Normally, you would have to write application-specific code to take advantage of multiple monitors. If you use high-level Windows messages to handle window resizing (maximize, minimize, and so forth), however, the portability library will handle multiple-monitor situations properly without additional code. If, on the other hand, you have written your own code to handle maximizing your window, multiple-monitor support will not work. You'll have to write Macintosh-specific code to handle the situation.

BitBlt vs. CopyBits

Windows supports 256 binary raster operations (ROPs) under BitBlt, whereas the Macintosh supports only 16 ROPs with CopyBits. If you use a ROP that the Macintosh doesn't support, see if you can rewrite it. Many of the unsupported ROPs can be duplicated by doing successive BitBlts with different functions—for example, by ANDing and then XORing a region.

Fonts

Fonts in Windows are much more complex than they are on the Macintosh. Windows keeps track of a variety of attributes for each font, including face name, style, height, descent, internal leading, and overhang. Much of this complexity stems from the variety of different printing devices supported under Windows. The Macintosh, on the other hand, has a much simpler font model. Fonts on the Macintosh are identified only by face name, style, and size. The portability library attempts to map your Windows font to the appropriate font on the Macintosh.

Some font data that Windows keeps track of is not available on the Macintosh. The Win32 API function GetTextMetrics makes a "best guess" at those values in Macintosh fonts. You may need to change programs that rely on the exact results of GetTextMetrics.

Printers

Windows supports a richer printer model than the Macintosh. For example, Windows allows multiple printers to be connected to your computer at one time, but the Macintosh allows only one. Windows lets you change from portrait to landscape printing in the middle of a print job; the Macintosh does not. Windows allows you to change paper bins in the middle of a print job; the Macintosh does not. If your application code counts on any of these Windows features, you will need to rewrite it for the Macintosh.

Palettes and colors

Many differences exist between the Windows and Macintosh palette models. You may need to change application code that makes certain assumptions about palettes or depends on unsupported behavior.

Metafiles

Most of the metafile APIs have been implemented in the portability library, but some restrictions apply. Metafiles are implemented on the Macintosh as Macintosh Pictures. This makes it cheap and easy to store graphics on the Clipboard because the Clipboard uses Pictures. Programs that parse metafiles in order to modify their contents, however, will not work properly on the Macintosh, because Macintosh metafiles are not stored in the Windows file format.

Strings and Character Sets

Many different string types are found on PCs: ANSI, original equipment manufacturer (OEM), Unicode, and Double-Byte Character Set (DBCS). The default character set for Windows is ANSI, but for MS-DOS it's OEM (code page 437). These character sets are identical from 0 to 128 and different from 129 to 255. The portability library does not support the AnsiToOem or OemToAnsi APIs. The portability library assumes the Macintosh character set, which is similar to the OEM set. Using the Macintosh character set means your strings can be localized for international versions using ResEdit, and it also means that your application should run on foreign systems that use DBCS character sets.

User Input

The portability library handles most mouse and keyboard APIs and messages appropriately on the Macintosh. Generally, if your code works properly under Windows, it will work on the Macintosh.

User Interface Porting Issues

Where possible, the portability library provides the Macintosh equivalent of the Windows user interface APIs and presents a Macintosh look and feel. Some differences, however, need to be accounted for.

Minimized windows

Because the Macintosh does not support minimized (icons) windows, passing the SW_MINIMIZE constant to ShowWindow doesn't change the size or position of the window.

Grow boxes

The Macintosh uses a grow box in the lower-right corner of all resizable windows. Windows uses a thick frame for resizing. The portability library will not add a grow box automatically unless the window meets certain criteria.

Child windows

Windows uses the concept of child windows extensively, but child windows don't exist on the Macintosh. Applications that use child windows (such as MDI applications) would normally be particularly difficult to port. The portability library, however, implements child windows on the Macintosh almost completely. The only difference is with child windows that have title bars, which are mapped to top-level windows on the Macintosh.

MDI applications

MDI applications present many differences between Windows and the Macintosh, because MDI doesn't exist on the Macintosh. The chief architectural difference is that the MDI frame window on the Macintosh is never made visible. If your application depends on having a "desktop" area on which it draws, you will need to create child windows on which to draw.

Menus

Because the Macintosh has only one menu, the active top-level window controls the menu when it becomes active. If you have top-level windows without menus, the Macintosh menu bar goes blank when one of those windows becomes active. (The portability library provides ways to override this behavior, but it involves writing Macintosh-specific code.) This is not a problem, however, for most MDI applications. When you create menus, remember that although Windows menus wrap if the window is too narrow, Macintosh menus that are too wide to fit will not appear.

Keyboard equivalents

Windows keyboard equivalents (underlined letters on menu choices) are available to portability library applications. The F10 key activates the keyboard equivalents. Alternatively, your application can trap a different key on "small" Macintosh keyboards and send WM_SYSCOMMAND/SC_KEYMENU to DefWindowProc.

Special menus

Right-aligned help menus (that is, top-level help menus created with the MF_HELP bit set) are automatically appended to the System 7 Help Menu. Microsoft-style help menus (not right-aligned) are not affected in any way.

System menus are not available on the Macintosh. If your application adds items to the Windows System menu, however, these are placed in the Apple menu under the portability library. The Apple DA menu is appended to the end of the menu owner's system menu, which is where the About box normally goes on the Macintosh. The portability library provides a default "About..." string that you can customize for your application.

Controls

Far more differences exist between Windows and Macintosh controls than can be covered here. Two areas of special interest, however, are control behavior and user interface. Most user interface issues are handled transparently by the portability library. Where possible, the portability library follows Macintosh conventions, which leads to incompatibilities between the two versions of your program.

Here's an example of UI differences: Windows allows you to tab to each control on a dialog box, giving that control the focus. The Macintosh, on the other hand, allows focus to go only to edit controls and list boxes.

Edit controls on the two systems are incompatible in several areas of behavior. Windows edit controls allow up to 64K of text, and support WM_UNDO and tabs. Macintosh edit controls support up to 32K of text and have no "undo" or tab support.

Clipboard

Macintosh Clipboard format names are limited to four characters. Use the following method in your code:

#ifdef _MAC
   cf = RegisterClipBoardFormat( "RTF" ):
#else
   cf = RegisterClipBoardFormat( "RichTextFormat" );
#endif

Miscellaneous differences

Other differences between Windows and the Macintosh abound, but most are trivial. For example, buttons in Windows dialog boxes have sharp corners, but buttons on Macintosh dialog boxes have rounded corners. Also, Windows controls have a three-dimensional look, but most Macintosh controls are two-dimensional. For the most part, the portability library takes care of those differences for you. You can read about other porting differences in the "Macintosh Porting Reference” in the  Visual C++ 4.2 documentation in the MSDN Library.

Porting by Using Microsoft Foundation Classes

The Microsoft Foundation Class Library—a C++ class library designed specifically for Windows-based applications—has been ported to the Macintosh (Mac MFC). Writing to MFC provides you the greatest degree of portability. Because MFC provides a greater level of abstraction than does writing directly to the Win32 API, it's easier to implement MFC correctly on the Macintosh.

Code written to MFC should recompile and execute correctly on the Macintosh with very few, if any, changes. C++ code generated by Microsoft Visual C++ should present no problems.

One difference between the Intel and Macintosh versions of MFC is that the Macintosh version, unlike the Intel version, does not support linking to MFC as a DLL. For 680x0 based applications, MFC must be statically linked into your application on the Macintosh. For Power Macintosh applications, you can statically link with MFC, or for better code sharing between applications, the portability libraries are provided code fragments. Your Windows-based version can still call the MFC DLLs.

A few MFC APIs that are mostly concerned with file system differences have changed between Windows and the Macintosh. A few APIs in standard MFC are not supported in Mac MFC—for example, CWnd::ArrangeIconicWindows, CDC::FloodFill, and CWinApp::LoadOEMIcon. Most of these represent functionality that has no counterpart on the Macintosh.

Some design changes will be necessary for your Macintosh port. For example, dialog boxes on the Macintosh are not commonly gray as they are under Windows. Also, Macintosh menu conventions differ from Windows—for example, the Macintosh uses Quit instead of Exit. You can use conditional resources to have platform-specific versions of resources.

Because MFC code is so portable, we urge you to write all new code in MFC for your application. MFC is flexible about calling native Win32 APIs directly, which gives you some flexibility in migration.

Writing Macintosh-Specific Code

Microsoft Visual C++ allows you to write directly to the System 7 API at any time. There are three situations in which you may want to do this:

  1. You want to take advantage of unique System 7.x features for which no corresponding portability library APIs exist. You could write native code, for example, to take advantage of Balloon Help on the Macintosh.

  2. You want to call native Macintosh routines rather than use the portability library. You may find places where—depending on the design of the application—calling Toolbox routines directly can speed up portions of your program. Generally, however, this won't be necessary.

  3. You have existing modules written directly to the System 7 API that you want to compile and link into your program.

Since _MAC is defined by default when compiling for the Macintosh, it's easy to include native Toolbox code that is set out for conditional compilation. You can even write an entire program to the native Macintosh API. Examples of native Macintosh programs are included with Microsoft Visual C++ Cross-Development Edition for Macintosh.

Summary

Finally you can keep doing what you know how to do best, writing to the Windows API, and still allow for versions of your application that run on other platforms. Visual C++ now gives you special versions that allow you to do this. Keeping your code portable, thinking about portability all the time, and using the right tools will help you make the multiple platform jump as effortless as possible.