data-id=creating-handlers
data-id=id1

Creating Handlers

Adobe Reader and Acrobat plugins and PDF Library applications can add new types of tools, annotations, actions, file systems, and so on, thereby expanding the number of supported object types. To accomplish this task, the Acrobat core API provides a collection of callback routines called handlers that support objects. Handlers perform operations, such as creating and destroy objects, handling mouse clicks, handling keyboard events, and so on.

data-id=about-handlers
data-id=id2

About handlers

To add a new handler, you must write callback functions, create the appropriate data structure containing the callbacks and other data, and pass the structure to Acrobat by invoking the appropriate method. Subsequently, Acrobat automatically invokes the correct callback when it encounters an object of the type handled by the handler.

It is possible to subclass existing handlers or to create entirely new handler types. For example, a plugin can subclass the built-in text annotation handler by adding the ability to hide annotations. To accomplish this task, perform the following tasks:

  1. Obtain the built-in text annotation handler structure by invoke the AVAppGetAnnotHandlerByName method.
  2. Copy the structure before modifying it (not modifying the original).
  3. Replace the handler’s Draw callback with one that invokes the built-in Draw callback (obtained from the structure) if annotations are visible, or simply return without drawing anything if annotations are hidden.
  4. Register the new handler by invoking the AVAppRegisterAnnotHandler method with a new type.

If a handler requires more data than provided in the predefined structures that are described in this section, you can append additional data to the predefined structures. To do this, create a new structure type with the predefined structure as its first member and the additional data as subsequent members. Before passing the expanded structure to an Acrobat method, cast the structure to the predefined structure type. Upon return of the structure from Acrobat, re-cast the structure to its expanded type to access the appended data.

Each handler data structure contains a size field, which specifies the structure’s size. This field provides future compatibility. Different versions of the structure have different sizes, allowing Acrobat to determine which version your plugin was written to use.

Note

Regardless of whether your plugin adds data to the predefined structures, it must pass the size of the predefined structure (rather than the size of its expanded structure) in the size field.

data-id=action-handlers
data-id=id3

Action handlers

Support for action types can be added by defining and registering an action handler. For example, the Acrobat Weblink plugin uses this ability to add support for URL links.

To add a new action type, you must provide a set of callbacks. Specify them in the AVActionHandlerProcs structure, and invoke the AVAppRegisterActionHandler method to register them.

By using an action handler, you can perform the following tasks:

data-id=annotation-handlers
data-id=id4

Annotation handlers

Support for annotation types in Acrobat can be added by defining and registering an annotation handler. For example, the Acrobat movie plugin uses an annotation handler to support video annotations.

To add an annotation type, you must provide a set of callbacks, specify them in the AVAnnotHandler structure, and register them with AVAppRegisterAnnotHandler.

By using an annotation handler, you can perform the following tasks:

Note

For information about working with annotations, see Creating Annotations.

data-id=avcommand-handlers
data-id=id5

AVCommand handlers

An AVCommand represents an action that a user can perform on the current document or the current selection in the current document. AVCommands are exposed to Adobe Reader or Acrobat through AVCommand handlers. You can add new command types by defining and registering an AVCommand handler. Commands can be executed interactively, programmatically, or through batch processing.

data-id=creating-an-avcommand-handler
data-id=id6

Creating an AVCommand handler

AVCommand handlers consist of a series of callback functions contained in the AVCommandHandlerRec structure (see AVExpt.h). To create a command handler, perform the following tasks:

  1. Initialize an instance of the AVCommandHandlerRec structure.
  2. Register the AVCommandHandlerRec structure by invoking the AVAppRegisterCommandHandler method.
static AVCommandHandlerRec gAVCmdHandler;
const char *kCmdName = "MinimalCommand";

static ACCB1 AVCommandStatus ACCB2 DoWorkImpl (AVCommand cmd)

{
  AVAlertNote("The DoWorkImpl method was invoked");
  return kAVCommandDone;
}

void InitializeCommandHandler()

{
  memset (&gAVCmdHandler, 0, sizeof(AVCommandHandlerRec));
  gAVCmdHandler.size = sizeof(AVCommandHandlerRec);
  gAVCmdHandler.Work = ASCallbackCreateProto (AVCommandWorkProc,
  &DoWorkImpl);
  AVAppRegisterCommandHandler (ASAtomFromString(kCmdName),
  &gAVCmdHandler);
}

Note

To view a complete example, see Running commands.

data-id=invoking-avcommands
data-id=id7

Invoking AVCommands

To programmatically invoke AVCommands using AVCommand methods, perform the following tasks:

  1. Instantiate the command by invoking the AVCommandNew method, providing the registered name of the command:
ASAtom cmdName;
 AVCommand cmd;
 cmdName = ASAtomFromString ("MinimalCommand");
 cmd = AVCommandNew(cmdName);
  1. Configure the command by setting required and optional parameters.
  2. Run the command by invoking the AVCommandExecute or AVCommandWork method.
data-id=configuring-avcommands
data-id=id8

Configuring AVCommands

Prior to executing an AVCommand, you configure three categories of properties:

data-id=setting-input-parameters
data-id=id9

Setting input parameters

At minimum, you must configure input parameters. The command must be provided with a PDDoc object that represents the PDF document on which to operate, as shown in the following example. For information about a PDDoc object, see Creating a PDDoc object.

//Create a PDDoc object based on the current PDF document
AVDoc avDoc = AVAppGetActiveDoc();
AVPageView pageView = AVDocGetPageView(avDoc);
PDPageNumber pageNum = AVPageViewGetPageNum(pageView);
PDDoc pdDoc = AVDocGetPDDoc(avDoc);

//Create an ASCab object to store input parameters
ASCab inputs = ASCabNew();
ASCabPutPointer (inputs, kAVCommandKeyPDDoc, PDDoc, pdDoc, NULL);

//Set the input parameters
if (kAVCommandReady != AVCommandSetInputs(cmd, inputs)) {

// Handle error
//Destroy the ASCab container
ASCabDestroy (inputs);

Note

For more information about the AVCommandSetInputs method, see the Acrobat and PDF Library API Reference.

data-id=setting-configuration-parameters
data-id=id10

Setting configuration parameters

Optionally you can set configuration parameters. The default UI policy is for commands to be fully interactive. To invoke the command programmatically, create an ASCab object and populate it with the appropriate parameters, as shown in the following example.

// Create an ASCab object to store config parameters
ASCab config = ACabNew();
ASCabPutInt (config, "UIPolicy", kAVCommandUISilent);

if (kAVCommandReady != AVCommandSetConfig (cmd, config)) {

// Handle error
ASCabDestroy (config);
}
data-id=setting-avcommand-parameters
data-id=id11

Setting AVCommand parameters

An AVCommand parameter set is specific to each command. For example, the Document Summary command accepts values for these parameters: Title, Subject, Author, Keywords, Binding, and LeaveAsIs. (See the Acrobat and PDF Library API Reference.)

You can create an ASCab object to store the appropriate parameters; then create empty ASText objects to hold the parameter values and place these values into the ASCabs object. The following example uses this approach to set the Document Summary Title and Subject values.

const char *docTitleValue = "Document Title";
const char *docSubjectValue = "Document Subject";

//Create an ASCab object to hold command parameters
ASCab params = ASCabNew();
ASText text = ASTextNew();
ASTextSetEncoded(text, docTitleValue,(ASHostEncoding)PDGetHostEncoding());
ASCabPutText (params, docTitleValue, text);

//Clear the ASText object
text = ASTextNew();
ASTextSetEncoded(text, docSubjectValue,(ASHostEncoding)PDGetHostEncoding());
ASCabPutText(params, docSubjectValue, text);
data-id=running-commands
data-id=id12

Running commands

The following code example shows an entire example of creating an AVCommand and running it.

void InitializeCommandHandler()

{

//Declare local variables
static AVCommandHandlerRec gAVCmdHandler;
const char *kCmdName = "MinimalCommand";
ASAtom cmdName;
AVCommand cmd;
const char *docTitleValue = "Document Title";
const char *docSubjectValue = "Document Subject";


//Create a PDDoc object based on the current PDF document
AVDoc avDoc = AVAppGetActiveDoc();
AVPageView pageView = AVDocGetPageView(avDoc);
PDPageNumber pageNum = AVPageViewGetPageNum(pageView);
PDDoc pdDoc = AVDocGetPDDoc(avDoc);


//Create an AVCommandHandlerRec object
memset (&gAVCmdHandler, 0, sizeof(AVCommandHandlerRec));
gAVCmdHandler.size = sizeof(AVCommandHandlerRec);
gAVCmdHandler.Work = ASCallbackCreateProto (AVCommandWorkProc, DoWorkImpl);
AVAppRegisterCommandHandler (ASAtomFromString(kCmdName),&gAVCmdHandler);


//Invoke the AVCommand
cmdName = ASAtomFromString ("MinimalCommand");
cmd = AVCommandNew(cmdName);


//Set the input parameters
ASCab inputs = ASCabNew();
ASCabPutPointer (inputs, kAVCommandKeyPDDoc, PDDoc, pdDoc, NULL);


//Set the input parameters and destroy the container ASCab
if (kAVCommandReady != AVCommandSetInputs (cmd, inputs)) {
   // Handle error
}


//Create an ASCab object to hold command parameters
ASCab params = ASCabNew();
ASText text = ASTextNew();
ASTextSetEncoded(text, docTitleValue,(ASHostEncoding)PDGetHostEncoding());
ASCabPutText (params, docTitleValue, text);


//Clear the ASText object
text = ASTextNew();
ASTextSetEncoded(text, docSubjectValue,(ASHostEncoding)PDGetHostEncoding());
ASCabPutText(params, docSubjectValue, text);


//Invoke the command
AVCommandExecute(cmd);
}


static ACCB1 AVCommandStatus ACCB2 DoWorkImpl (AVCommand cmd)

{
AVAlertNote("The DoWorkImpl method was invoked");
return kAVCommandDone;
}
data-id=exposing-avcommands-to-the-batch-framework
data-id=id13

Exposing AVCommands to the batch framework

Acrobat or Adobe Reader builds the list of commands that users see in the Batch Sequences and Batch Edit Sequence dialog boxes from an internal list of AVCommands referred to as the global command list.

data-id=adding-a-handler-to-the-global-command-list
data-id=id14

Adding a handler to the global command list

To expose a command to the batch framework, the AVCommand handler must first add an instance of the command to this global list by invoking the AVAppRegisterGlobalCommand method.

AVCommand cmd = AVCommandNew(ASAtomFromString(kCmdName));
 AVAppRegisterGlobalCommand(cmd);

Although this step can be performed at any time once the command handler is registered, handlers commonly register commands from within the AVCommandRegisterCommandsProc callback (of the AVCommandHandlerRec structure).

data-id=supporting-properties
data-id=id15

Supporting properties

When building a list of batchable commands, Adobe Reader or Acrobat iterates through its internal command list, querying each command for the CanBatch and GroupTitle properties. To be exposed through the batch framework user interface, a command must support these properties (that is, return true and a valid ASText object, respectively). The AVCommand handler must implement the GetProps callback of the AVCommandHandlerRec structure.

If an AVCommand supports these properties, Adobe Reader or Acrobat queries a number of additional properties as the user interacts with the batch framework. Of these additional properties, only two are required: Title and Generic Title. A command must provide the title strings that will be displayed in the Batch Sequences and Batch Edit Sequence dialog boxes.

const char *kCmdTitle = "Command Title";
const char *kGroupTitle = "Group Title";
const char *kCmdGenericTitle = "Generic Title";

ASBool doItAll = false;
if (ASCabNumEntries(params) == 0)
doItAll = true;
if (doItAll || ASCabKnown (params, kAVCommandKeyGroupTitle))
{

// Create a new text object and insert it into the ASCab
text = ASTextNew();
ASTextSetEncoded (text, kGroupTitle, (
ASHostEncoding)PDGetHostEncoding());
ASCabPutText(params, kAVCommandKeyGroupTitle, text);
}
if (doItAll || ASCabKnown (params, kAVCommandKeyCanBatch))
ASCabPutBool (params, kAVCommandKeyCanBatch, true );
if (doItAll || ASCabKnown (params, kAVCommandKeyGenericTitle))
{

//Create a new text object and insert it into the ASCab
text = ASTextNew();
ASTextSetEncoded (text, kCmdGenericTitle,
(ASHostEncoding)PDGetHostEncoding());
ASCabPutText (params, kAVCommandKeyGenericTitle, text);
}
if (doItAll || ASCabKnown (params, kAVCommandKeyTitle))
{

// Create another text object and insert it into the ASCab
text = ASTextNew();
ASTextSetEncoded (text, kCmdTitle,
(ASHostEncoding)PDGetHostEncoding());
ASCabPutText (params, kAVCommandKeyTitle, text);

Note

The params object was declared in Running an AVCommand.

data-id=file-format-conversion-handlers
data-id=id16

File format conversion handlers

A plugin can add file conversion handlers to Acrobat (but not Adobe Reader) for performing the following file conversion operations:

To add a new file conversion handler, you provide a set of callback functions, specify them in the AVConversionToPDFHandler or AVConversionFromPDFHandler structures, and invoke the AVAppRegisterToPDFHandler or AVAppRegisterFromPDFHandler methods to register them.

Specify the file types that the plugin can convert and whether it can perform synchronous conversion (required for the handler to be accessible from the batch framework). Upon registration, the conversion handlers are automatically added to the respective Open and Save As dialog boxes.

By using a file format conversion handler, you can perform the following tasks:

data-id=file-specification-handlers
data-id=id17

File specification handlers

A file specification handler converts between a PDFileSpec object and an ASPathName object. Each file specification handler works with a single file system, which the handler specifies.

To create a new file specification handler, a plugin or application must provide callbacks that:

data-id=selection-servers
data-id=id18

Selection servers

A selection server enables the selection of specific data types such as annotations, text, or graphics. You can also create selection servers to enable the selection of data types not already supported. To add a new selection server, you must provide a set of callbacks, specify them in the AVDocSelectionServer data structure, and register them using an AVDocRegisterSelectionServer object.

By using a selection server, you can perform the following tasks:

For a complete list of the callbacks in a selection server, see the description of AVDocSelectionServer in the Acrobat and PDF Library API Reference.

Note

The SelectionServer sample plugin that is located in the Acrobat SDK shows an example of a selection server.

data-id=tool-callbacks
data-id=id19

Tool callbacks

To add a new tool, you must provide a set of callbacks, specify them in the AVTool data structure, and register them using AVAppRegisterTool. By using tool callbacks, you can perform the following tasks:

Note

For a complete list of callbacks, see the description of AVTool in the Acrobat and PDF Library API Reference.

data-id=window-handlers
data-id=id20

Window handlers

When a plugin creates a window, it can register the window, so that it behaves like other windows in Acrobat; for example, when Adobe Reader or Acrobat is minimized or hidden. For each window that a plugin provides, a window handler must be provided. Window handlers are used only in the Mac OS version of Adobe Reader or Acrobat. Windows versions of Acrobat instead use the platform’s native window handling mechanisms. (See Opening a PDF document in an external window.)

To define a window handler, you must provide a set of callbacks, specify them in an AVWindowHandler structure, and pass the structure to AVWindowNew or AVWindowNewFromPlatformThing. The window handler’s callbacks are automatically called by Acrobat. Default behavior is used for any missing callbacks.

By using a window handler, you can perform the following tasks:

For a complete list of callbacks in a window handler, see the description of AVWindowHandler in the Acrobat and PDF Library API Reference.

data-id=file-systems
data-id=id21

File systems

Plugins can add new file systems to Acrobat or Adobe Reader, to access files on a device that cannot be accessed as a local hard disk, such as a socket or a modem line.

To add a new file system, you must provide a set of callbacks and specify them in the ASFileSysRec structure. This structure is passed as a parameter to calls that require a file system. A file system handler does not require explicit registration.

By using a file system handler, you can perform the following tasks:

For details about each of the callbacks in a file system, see the description of ASFileSysRec in the Acrobat and PDF Library API Reference.

data-id=progress-monitors
data-id=id22

Progress monitors

Progress monitors provide feedback to a user on the progress of a time-consuming operation. Some potentially time-consuming methods in the Acrobat core API require a progress monitor as a parameter. Acrobat has a default progress monitor, which generally is sufficient for plugins to use. The built-in progress monitor can be obtained by using the AVAppGetDocProgressMonitor method.

Plugins can use the default progress monitor or implement their own by providing a set of callbacks, specifying them in the ASProgressMonitorRec data structure, and passing a pointer to the structure to the methods that require a progress monitor (there is no explicit registration method).

Using a progress monitor, you can perform the following tasks:

For details, see the description of ASProgressMonitorRec in the Acrobat and PDF Library API Reference.

data-id=transition-handlers
data-id=id23

Transition handlers

Transitions allow effects such as dissolves or wipe-downs when displaying a new page. New transition types can be added by defining and registering a transition handler.

To add a new transition, you must provide a set of callbacks, specify them in the AVTransHandler data structure, and register them by invoking the AVAppRegisterTransHandler method.

Using a transition handler, you can perform the following tasks:

data-id=adding-message-handling
data-id=id24

Adding message handling

Plugins can add their own DDE messages and Apple events to those supported by Acrobat and Adobe Reader. On Windows, plugins can register to receive DDE messages directly. On Mac OS, plugins must hook into Acrobat or Adobe Reader’s Apple event handling loop to handle Apple events. To do this, replace the API’s AVAppHandleAppleEvent method. For information about replacing methods, see Replacing HFT methods.

If a plugin receives an Apple event it does not want to handle, it should invoke the implementation of the method it replaced, allowing other plugins or Acrobat or Adobe Reader the opportunity to handle the Apple event.

Note

Plugins should use the DDEML library to handle DDE messages. Problems may arise if they do not.