Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.
These two events are the primary communication channels between an active document and its host (browser). CommandTargetQuery lets the active document tell the host what commands it’s interested in. CommandTargetExec fires when the user does something in the host that the active doc might want to respond to.
PROCEDURE acdActiveDoc.CommandTargetQuery
LPARAMETERS aCommands, nCommandTextFlag, cCommandTextOut
PROCEDURE acdActiveDoc.CommandTargetExec
LPARAMETERS nCommandID, nExecOption, uArgIn, uArgOut
Parameter |
Value |
Meaning |
aCommands |
Array |
A two-column array listing the commands (using a set of numeric values documented in the Help for CommandTargetExec) that the host thinks might happen soon. The active document can fill in the second column to indicate whether or not each command is permitted. |
nCommandTextFlag |
Numeric |
A numeric value indicating what extra information the host wants back from the active document. |
cCommandTextOut |
Character |
A parameter passed by reference to receive the extra information requested. |
nCommandID |
Numeric |
The command triggered by the user or host to which the active document can respond. The list of values is documented in Help. |
nExecOption |
Numeric |
A value (documented in Help) indicating the normal reaction to the specified command. |
uArgIn |
Numeric (perhaps other) |
An additional value passed with some commands to provide the active document with more information. |
uArgOut |
Expression |
A parameter passed by reference to let the active document return information to the host. |
These are two of the most obscure events we’ve had to decipher. Here’s the deal. An active document is a special kind of application designed to let you run a regular VFP app inside a browser. (Don’t ask us why you’d want to do that. Okay, do ask. You’ll find our thoughts in the ActiveDoc section.)
When you put your application inside a browser, things can happen that your application doesn’t know about. Things like the user navigating to a Web site or choosing a menu item from the browser’s menu that isn’t under the app’s control. The Help for CommandTargetExec has a whole list of the kind of things that can happen and, in fact, shows the number assigned to each of those to identify it.
These two events give your app control over what happens when one of those things occurs. CommandTargetQuery fires when one or more of those actions is possible, and lets you decide whether the user should even be allowed to trigger one of those actions. It receives a two-column array as a parameter. The first column contains a list of all the actions that might happen. (For example, when the user clicks the browser’s File menu, the array contains the codes for the items located on the File menu.) Code in the active doc fills in the second column to indicate whether the active doc wants the opportunity to respond to this action. Like so many things in VFP, the choices are additive. You can include more than one by adding the values together.
CommandTargetExec can fire when one of the actions actually occurs. Whether it fires or not, though, depends on the choices made in CommandTargetQuery. If the action was enabled, CommandTargetExec fires, giving the active doc the chance to respond, and passing the action code as well as some information about the usual way of handling that action (like whether the user is customarily prompted before proceeding). However, the active doc can treat the action however it wants (including doing something totally unrelated). Then, the active doc returns a value to the host indicating whether or not the action has been taken care of. If the active doc hasn’t taken care of it, the host performs the normal default action.
Both of these events have a couple of extra parameters to allow additional data to be passed back and forth. For CommandTargetQuery, the host can request localized information about the command (with nCommandTextFlag) and the active doc can return the information in cCommandTextOut, but only for the first action in the array. We thought this might let us customize the status bar text for host menu items when an active doc is running, but it appears that the host ignores the value in cCommandTextOut unless it asked for it. (Actually, since we haven’t encountered a case where the host asks, and Help implies we shouldn’t expect to any time soon, for all we know, it’s always ignored.)
The additional parameters to CommandTargetExec aren’t so esoteric. They’re simply a mechanism for any of the actions to pass some additional information to the active doc and to get additional information back. For each of them, Help lists only one case where it’s used—we confirmed that they behave as expected in those cases.
* Running an active doc application in IE 4,
* when IE's File menu is dropped open,
* CommandTargetQuery receives a 6-row array. The
* code here shows how you might respond to a couple
* of those items.
* This code goes in CommandTargetQuery
FOR n = 1 TO ALEN(aCommands, 1)
DO CASE
CASE aCommands[n, 1] = 6 && Print
aCommands[n, 2] = 2 && Enabled
CASE aCommands[n, 1] = 4 && SaveAs
aCommands[n, 2] = 2 && Enabled
ENDCASE
ENDFOR
* Then suppose we want to subvert the behavior of those
* two actions. Put this code in CommandTargetExec.
* This.oForm is a custom property referencing a form in the app.
* We don't recommend reacting to these menu choices
* like this in real apps, but the Print action could,
* for example, run a report.
DO CASE
CASE nCommandID = 6 && Print
This.oForm.Caption = "Printed"
CASE nCommandID = 4 && SaveAs
CLEAR EVENTS
ENDCASE