Quantcast
Channel: Adobe Community: Message List - Acrobat SDK
Viewing all articles
Browse latest Browse all 10848

call plugin C function from Javascript form event

$
0
0

I have a C DLL that needs to get the string from the form text box, process it, and return true or false during a form validate event to indicate whether the string passes or fails for the form box. The pdf runs on unnetworked Windows PCs and has access to all privilaged JS functions.The easiest way to do this is to create a JS function that is implemented in C/C++ using a HFT plugin and the JS function written in C is called from the field's form validate event handler written in JS. But it seems to me there is no really good way to do this through the official API.

 

AFExecuteThisScript from the Forms HFT goes the wrong way from C to JS. ExecuteThisScript from AFormApp/acroform.api also goes the wrong way from C/OLE to JS. I've never tried GetJSObject from CAcroPDDoc/acrobat.exe, but I dont think it understand an IDispatch or IEventSource obj. Here are some quotes from the official docs that reenforce my understanding.

 

 

JSObject cannot add new properties, methods, or objects to JavaScript. Due to this limitation, the global.setPersistent property is not meaningful.

 

JSObject can process most elemental Visual Basic types for property puts and input parameters to method calls, including Variant, Array, Boolean, String, Date, Double, Long, Integer, and Byte. JSObject can accept Object parameters, but only when the Object was the result of a property get or method call to a JSObject. JSObject fails to accept values of type Error and Currency.

 

AcroFormRegisterObserver is deprecated in 8.0, and has no examples or docs of its usage. "FieldValidateChange" seems to be what I want to hook, but even if it does work, what is "void * info" in AF_NotificationProc? How do I find out in the notification callback what field in the form this was?

 

Another idea is having the validate JS event code do loopback over tcpip. This involves a non-acrobat process, or in-acrobat process, using a plugin, create a OS thread, which uses OS socket facilities to open a listening port, and basically wrapping the C DLL that has the field validation logic. Net.HTTP is async only, so the validate event handler will return control back to the internal idle loop in Acrobat, leaving the form in a non validated state for a second or 2 until the JS callback ("oHandler") runs.  The other choice I see for loopback is SOAP object in sync mode. I dont like the idea of doing loopback within the same process basically.

 

Another idea is app.execMenuItem, register a menu item in C with AVMenuItemSetExecuteProc.  Then the JS event code calls app.execMenuItem which in turn executes the C code function. My testing shows escript.api shows up in the callstack and if I put a C breakpoint in menu item callback C function, all of acrobat's GUI in all windows freezes. So I think app.execMenuItem is syncronous, and the closest thing to calling C code from the JS engine in acrobat. But app.execMenuItem has a problem. There is no way to pass any data to the menu item. The JS validate event code would need to serialize the validate event object, assign it to the doc obj, then do the execMenuItem, then the C func does a AFExecuteThisScript with "event.value = serializedvalidateevent;" as the script to fetch it into C land, deserialize char** pRetValue in C, then perform the validation logic in C (hand off to frunction from non-acrobat aware DLL), then do sprintf to create a new script, and a 2nd AFExecuteThisScript to return the result to JS land attaching it to the doc obj. Then the menu item C func returns. Then the validate event JS code reads the C to JS result member of the doc obj, and acts accordinglying. I wrote some code and tested this theiry and it works, but the idea is rediculously complicated for comunicating between JS and C.

 

Another idea is messageHandler.postMessage. I am not sure if this is syncronous or async (the validate event returns after the postMessage, a HostContainer.postMessage would be required to deliver the result, but the field is now showing a possibly invalid value for a second). But postMessage is from acropdf.dll, and AFAIK that means I will loose the acrobat menubar (toolbars appear in browser windows, the acrobat menubar doesnt) and the UI is standalone acrobat, not acrobat embedded in another app.

 

Looking at Acrobat 4, and AFGetScriptingContext and an example online of AFGetScriptingContext's usage. It appears Acrobat used to expose a complete SpiderMonkey engine for plugins. Looking at the export table of AcroJS32.dll shows all of SpiderMonkey's normal function calls. Adding your own JS methods written in C++ is as easy as following Mozilla's docs. But in Acrobat 7 and newer (I dont have access to 5 or 6), there is no AcroJS32.dll, instead there is Escript.api which just exports PlugInMain so this thing probably offers a HFT of its own to control the JS engine from other plugins. Acroform.api's AFGetScriptingContext is hardcoded to always return 0 in 7 and newer. So is there anyway for a plugin to register itself with Escript.api's HFT or that is undocumented and the execMenuItem insanity is the only way to write a JS function in C for Acrobat?


Viewing all articles
Browse latest Browse all 10848


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>