This book's examples were written and compiled with Microsoft's Visual C++ 4.0. Additionally, the Netscape Plug-in SDK was also written in Visual C++. This development environment includes many tools such as Visual Workbench, App Studio, AppWizard, ClassWizard, and several others. All the functionality needed to build and test a plug-in is included in Visual C++: text editor, compiler, linker, resource editor, and debugger. The Microsoft Foundation Class Library (MFC), included with the product, is somewhat of an industry standard. MFC, as shown in many of this book's examples, makes plug-in development much simpler.
Although the book contains many examples using Visual C++, none of the examples explains how to create a plug-in from scratch. This chapter contains a step by step example of how to write a plug-in starting with files from the Server CPU Monitor example. Complete screen shots show all settings and procedures needed to build a plug-in. If you are relatively new to Visual C++, this is the chapter for you. Many hours of frustration can be avoided by following these simple steps.
It's interesting to note that this example does not use the MFC AppWizard (dll). For Netscape Navigator plug-in development, there is no need to overcomplicate your project by using the AppWizard. This example adds MFC later with the project settings. There is one important thing to remember if you use the sans AppWizard method to create an MFC plug-in: Be sure to define a global instance of CWinApp. In this example, it is done in the file npshell.cpp:
CWinApp theApp;
Defining CWinApp initializes MFC. If you forget to do this, you'll see some very odd assertions while running your plug-in!
If you want to follow along with the example, you need to get the files shown in the following lists from the Server CPU Monitor sample.
For the \CODE\CPUMON directory, you need these files:
For the \CODE\INC directory, you need these files:
For the \CODE\COMMON directory, you need these files:
Put all files in the same directory to match this example.
After you copy the files to a new directory, change the header include paths. All the CPP files except stdafx.cpp include a relative path for stdafx.h. Change these to local:
#include "..\inc\stdafx.h"
should be
#include "stdafx.h"
The next three sections give step by step instructions for creating a plug-in from scratch with MicroSoft's IDE. The first section shows you how to set up a new project that creates a Windows plug-in DLL. Then, the next section shows how to build the plug-in. Lastly, the third section covers testing and debugging your Microsoft built plug-in.
To set up a project for Visual C++, first you must create a new project with the proper project types. Then, create and change the resource file. Finally, you add the source files and change the build settings. Steps 1 through 7 demonstrate this.
First, start the Developer Studio by double-clicking on the Microsoft Developer Studio icon. After that moment of great excitement, create a new Project Workspace with File|New in the main menu. Figure 27.1 shows Project Workspace selected in the New dialog.
Figure 27.1 : Creating a New Project Workspace.
Select Dynamic-Link Library with the name of npcpumon, Win32, and the location of the directory in which your files are stored. Figure 27.2 shows the project of name npcpumon in location d:\src\cpumon for platform Win32 and a type of Dynamic-Link Library.
Figure 27.2 : Creating a new DLL.
Now that you have a project, create a resource by using the Insert|Resource menu item. The location of this menu item is shown in Figure 27.3.
Figure 27.3 : Inserting a resource.
Select a resource type of Version and click OK. Figure 27.4 shows the resource type of Version selected.
Figure 27.4 : Selecting Version resource type.
You need to change the Block Header properties to Windows, Multilingual. If you don't do this, your plug-in will not be recognized by the Navigator! Double-click on the block header to bring up the properties dialog. In Figure 27.5, you can see that the language ID is English (United States) and the code page is Windows, Multilingual. After these modifications are complete, save the resource as npcpumon.rc.
Figure 27.5 : Changing the Block-Header properties.
Next, open the resource as Text. You do this so that you can add your plug-in specific information to the version block. The resource editor is not capable of adding new information in the version block, so you must use the text editor. Figure 27.6 shows how to change the Open As drop-down to Text.
Figure 27.6 : Opening the resource as text.
Add the MIME type, file extension, and file open name to the resource. This example uses application/x-tex, tex, and CPU Monitor (*.tex), respectively. In Figure 27.7, you can see this new information as a highlighted block of text.
Figure 27.7 : Adding the plug-in resource information.
Add the files for the Server CPU Monitor to the project with the Insert|Files into Project menu item. Figure 27.8 shows the location of this menu item. These files are npcpumon.cpp, npcpumon.def, npcpumon.rc, npshell.cpp, npwin.cpp, npwindow.cpp, and stdafx.h.
Figure 27.8 : Bringing up the Insert Files dialog.
You can select all the files at the same time by holding down the Ctrl key. Figure 27.9 shows all the files highlighted.
Figure 27.9 : The Insert Files into Project dialog.
Bring up the Project Settings dialog by selecting the Build|Settings main menu item. Figure 27.10 shows this menu item.
Figure 27.10 : Bringing up the Project Settings dialog.
In the General tab area (see Figure 27.11), select "Use MFC in a Static Library" to add the MFC library to the project. You probably should statically link to MFC, rather than dynamically link, to avoid conflicts with Netscape's linkage of MFC.
Figure 27.11 : Statically linking to MFC.
Put in the Netscape Navigator path, executable, and working directory in the Debug tab area. This enables you to run Navigator for debugging the plug-in. Figure 27.12 shows the following Navigator path:
Figure 27.12 : Pathing in Navigator.
d:\Program Files\Netscape\Navigator\Program\netscape.exe
Now switch to the C/C++ tab area (see Figure 27.13). Under Category Preprocessor, add the preprocessor definition _USRDLL. This is required by MFC.
Switch to the Link tab area (see Figure 27.14). Set the Output filename to reflect the path of the Navigator's plugins directory and the name of the plug-in.
Figure 27.14 : Setting the plug-in's Output directory.
To build the plug-in, the next two steps show how to start a full build and check the output for errors.
Using Build|Build npcpumon.dll or Build|Rebuild All in the main menu, build the plug-in DLL. Figure 27.15 shows the location of these menu items.
Figure 27.15 : Starting a build.
Upon completion, the output should look something like what you see in Figure 27.16, with 0 errors and 0 warnings.
The next seven steps show how to debug this newly created plug-in. To do this, you must create a test file, set a breakpoint, run the Navigator, and open the test file.
The Server CPU Monitor sample plug-in needs a file with the extension .tex opened in Navigator to load the plug-in. Normally, this file would contain the URL of a CGI program that returns server statistics. (See Chapter 19, "The CPU Monitor Plug-In," for further information.) For the purposes of this example, just create a dummy file with garbage in it with a .tex extension.
| Note |
The extension .tex and MIME type application/x-tex were picked almost randomly to use with the Server CPU Monitor. That way, the server configuration did not have to change in order to try the sample. Use this MIME type and extension for testing only! |
Set a breakpoint in the code. A good place for the breakpoint is in the NPP_StreamAsFile API in the file npshell.cpp. This API will be called with the name of your test file. In Figure 27.17, a breakpoint is set by clicking on the hand in the toolbar.
Figure 27.17 : Setting a breakpoint.
Run Navigator by clicking on the Run button. A warning error is produced because netscape.exe does not contain debugging information. Just click OK. This warning error is shown in Figure 27.18.
Figure 27.18 : Running Netscape Navigator.
Verify that your plug-in's resources have been properly read by Navigator with the Help|About Plug-ins menu item. Figure 27.19 shows the location of this menu item.
Figure 27.19 : About Plug-ins.
| Warning |
Just because you can see your resources in About Plug-ins does not mean that the plug-in DLL is loadable. Navigator pulls these resources from the plug-in DLL without loading it. This can create confusion if, say, you forget to add a .def file to your project. Without the .def file exporting the entry points, Navigator can't load the plug-in, but you can see it in Help|About Plug-ins! |
Use the File|Open File menu item in Navigator to open the test file. In Figure 27.20, you can see the location of this menu item.
Figure 27.20 : Bringing up the File Open dialog.
Make sure that CPU Monitor (*.tex) is in the Files of type section. Select this type, as shown in Figure 27.21, to display the test file. Then, select the test file and open it.
Figure 27.21 : Verify files of type.
If all has gone well, you should hit the breakpoint set previously. Verify the test filename by bringing up a QuickWatch on fname. You can do this by right-clicking on the fname variable. In Figure 27.22, fname is shown as d:\src\cpumon\cpumon.tex.
Figure 27.22 : Hitting the breakpoint.
Because there was garbage and not a URL in the test file, you get an assertion (shown in Figure 27.23). To avoid this, you need to run the CPU Monitor sample in the configuration outlined in Chapter 19 or just add code to avoid this error.
Figure 27.23 : The assertion is displayed.
If you are using this chapter as a basis for a new plug-in, you should replace the files npcpumon.cpp and npcpumon.h with files of your own. Of course, rename the project and files to reflect your plug-in. Don't forget that the plug-in DLL must begin with np or it will not be loaded by the Navigator!
The next chapter takes you through a similar step by step example of building a plug-in with Watcom C++ 10.x.