The first step, of course, is to have the script. To make the script work best with a menu item, it's important to have it as a function, so that the function call can be easily added to the menu item. For the purpose of this post, I'm going to use the script posted in another forum post: viewtopic.php?p=187589#p187589
The next step is to come up with an icon. Some things to think about when making the icon:
Image size: I usually make the icons 40 pixels x 40 pixels (only because I used to do 20x20 and they were too small in some cases -- actually more common sizes are 32x32 or 48x48). The javascript specification says they must be 20 x 20, but PDF-XChange is pretty forgiving and will resize it. I have no idea how other pdf software reacts to larger icons. On PDF-XChange the larger size means it will show up better on the ribbon layout. To edit the icon, I use Gimp but you can use whatever software suits you.
Transparency: The icons look better if you make the background transparent rather than a color.
File format: I save the icon with the file format .png and make sure to not save the resolution: Thievery: I'm no graphic artist so for the scripts I post on this forum I usually take screen captures of the icons in PDF-XChange and modify them - hopefully they don't sue me


Now you can add it to your script:
Method 1
Save the png file just created and load it when the menu loads. This uses a PDF-XChange added method viewtopic.php?p=112037#p112037
- I'd recommend saving the png into the same place as the script (ie the Javascripts folder in %APPDATA%\Tracker Software\PDFXEditor\3.0\Javascripts ). I'm saving it with filename 'SaveNC.png'.
- An easy way to get the correct spelling and path to use is the following function: It will output the path to the javascript folder so that if someone else uses the script, the path to application data is also correct for them. Add '/SaveNC.png' (your filename from the above) to the end.
Code: Select all
app.getPath('user','javascript')
If you want to save into the application JavaScripts folder, you can get that with app.getPath('app','javascript'); - Add the code to the beginning of the script; I posted a pdf with all the information about both the base javascript functions, and the new PDF-XChange improvements here: viewtopic.php?p=184605#p184605
For this I'm going to add it to a menu item, but adding a tool button is very similarCode: Select all
app.addMenuItem( { cName: "saveNoAnnots", cUser: "Save Without Markup", oIcon: util.iconStreamFromImage( app.getPath('user','javascript') + '/SaveNC.png'), cParent: "File", // Adding to the file menu for the regular UI nPos: "cmd.saveTo", // Adding after the "Save To" option cRbParent: 'JS:QuickAccess', // add to the quick access bar on the ribbon nRbPos: "cmd.save", // put the icon after the 'save' button cEnable: "event.rc = (event.target != null);", // this line is optional: this disables to the tool button when there's no file active cExec: "saveWithoutAnnots(this, true);", });
- 'cName' The first line is a text string that is unique to your new menu item. I just make it something like the function name, but PDF-XChange have a hierachical naming method like 'cmd.document.export.toImages' that makes sense - i.e. one could use a 'domain' and then the tool name such as mathew.util.savena etc...
- 'cUser' The second line is the text that the user will see in the menu. For this example, because I'm adding it to the quickaccess toolbar, this text won't show, but will pop-up as a tooltip when the user hovers over the button.
- 'oIcon' The third line uses the PDF-XChange method util.iconStreamFromImage() to load the icon from the file directly.
- 'cParent' is the location it should appear in the regular UI (ie I'm adding it to the file menu)
- 'nPos' can be a number or a text string. To find the text strings, you'll need to run this in the console, and search through the somewhat cryptic output (code copied from PDF-XChange example file):
Code: Select all
/************************************************************************ To see the actual Classic/Ribbon UI structure you may use the following script: ************************************************************************/ function FancyMenuList(m, nLevel) { var s = ""; for (var i = 0; i < nLevel; i++) s += " "; var n = m.cName; if (n == "") n = "-----" console.println(s + n); if (m.oChildren != null) for (var i = 0; i < m.oChildren.length; i++) FancyMenuList(m.oChildren[i], nLevel + 1); } var m = app.listMenuItems(); //to get list of items inside ClassicUI.MenuBar or inside the RibbonUI, // also the optional cName parameter can be used to get items-list of certain menu/toolbar/tab //var m = app.listToolbarButtons(); // to get list of items inside the Addon toolbar for (var i = 0; i < m.length; i++) FancyMenuList(m[i], 0);
- 'cRbParent' is the menu to show it in the ribbon menu. Here I'm adding it to the quick access bar
- 'nRbPos' is the position in the menu. Again it can be a number, or string.
- 'cExec' is the function you want to call, inside quotation marks (ie as a string). Watch out with this one: If your function call has a string as a paramenter, for example, you'll need to be careful about either using single quotes around double quotes (or the other way around) or escaping all the quotation marks inside.
- 'cHotkey' is an optional parameter (I didn't include it in the example above) that specifies a shortcut key for the menu item.
- Examples: "Ctrl+Shift+K", "Ctrl+Alt+Num0", "Ctrl+Comma", "Ctrl+Tab", "Ctrl+Space", "Ctrl+Shift+K,C"
Special key names: Ctrl, Shift, Alt, AltGr, Esc, Escape, Tab, Enter, Return, Break, Space, Sp, BackSpace, BkSp, ScrollLock, Ins, Insert, Del, Delete, PgUp, PageUp, PgDn, PageDown, Home, End, Up, Down, Left, Right, EqualSign, Minus, Subtract, Sub, NumPlus, NumAdd, NumMinus, NumSubtract, NumSub, Num0, Num1 ... Num9, NumMult, NumDiv, NumDec, Semicolon, Comma, Period, Dot, Slash, BackSlash, Tilde, LeftSqBrkt, RightSqBrkt, SingleQuote, F1, F2 ... F24
- Examples: "Ctrl+Shift+K", "Ctrl+Alt+Num0", "Ctrl+Comma", "Ctrl+Tab", "Ctrl+Space", "Ctrl+Shift+K,C"
- Run this in the console to check that it works. If so, save the script with the suffix .js into the Javascripts folder and restart PDF-XChange. Now it acts almost the same as a built-in menu item.
The second method is almost identical to the above method, and is the one I use. Instead of loading the image from a file, I encode the image data directly into the script.
- I made a pdf utility file to help getting the icon data and posted it here: viewtopic.php?t=42029
- Open the pdf tool and click on the button 'Pick Image File' to open the image file you created:
- When you press 'OK' it should put the image data into the two form fields:
The top form field is the straight image data. The second one includes a line of script that includes decompressing a compressed representation of the above data. I always use this. Copy it and paste into the beginning of the script file. - The code is very similar to the first method with just the image data added at the beginning and the line oIcon referring to this icon data:
Code: Select all
var myIcon = {count:0, width:40, height:40, read:function(nBytes=this.data.length/2){return this.data.slice(this.count,this.count+=2*nBytes);}, data:(a=>{let[b,c]=a.split(":");c=c?.match(/.{8}/g);let d=(a,b)=>a.replace(/./g,a=>parseInt(a,10+b)-b);return b.replace(/([g-p]+)([0-9a-f]+|[q-z]+)/gi,(a,b,e)=>(/[q-z]/.test(e)?c[d(e,26)]:e).repeat(d(b,16)));})("hqhstjhshFFA084D1hFFBBA8DClqhstjjshzhFFB39DD8kqjjshzhrrhukqjjshrriukqmshsqhrxigthsuhsvhsqhshzjukqmshrxijthsvhzhrrjukqmshsuijthFFFDFCFDhrrkukqmsiltlukqmslthkrwmtlukqmsiltlukqmsiltlukqmslthkrwmtlukqmsltjrwigrhFFF1F1F3huh05F4F4F4jqmsnthrhFFF8E9B8howhFFFADF89hFFFAE296hFFF4F2EAh12F4F4F4jqmsmthrhFFF8E8B6howjvhFFFCDC77h0CF4F4F4jqmslthrwhrhnwhrqkvhFFFED550hswjqmslthrwhrhmwhrqlvhFFFFD550hsxjqmsmthrkwhhruhrvjrtkvkqmshrxlthrkwhgruhrvkrtkvkqmshsqhrxkthrhjwhrqpvkqhishrhiwhrqhgvkqhishrkwnruhrvnrtkvkqhishrkwmruhrvlrthFFECB821hFFECBB2ChFFEABA2FkvkqhishrpwhrqmvhFFF4F1E7krhFFF4F2EBhFFE8D8BAkqhishrowhrqlvirhsyhxisrhxhszirhswiqhhshzhrkwjruhrvjrthFFEDBA21hrthtqhtrhrymxhryhFFFAAF97hE8F4EFEEhqh0AF4F4F4psjthrkwiruhrvlrthtqhFFFBAB93hgxhtshrhqoshzjthrlwhrqkvhFFFDD862htthtrhgxhrshyhtuhqoshrrjthrkwhrqmvhrhrypxhrsiyhrzhrnshzhujthrhFFF8E8B4iwhrqhFFFFD759lvhrhsypxhrskyhtvhqlshzhrrhukthrhFFF8E8B3iwmvhrpxhrsmyiqjshzhrriukthulrkvhrhsrixhtwothtxiyhssjqhshzhrrjuktiujthrkvhrhsrixhtwothtxiyhsskqluktiujthrjvhtthrmxhrspylqkuktiujthrivhFFF4F1E9hthrhszkxhrspyhtynqhhuhrhvhFFF5EED7juhrhryixhrspyhrzhrhpqhrkqhrhFFFBAF97hxhrshgyhtzimqhuqhtshgyhFFFB9C7Ehrilqh0EF4F4F4hqhuqhtuhrzmyhrzhtzhrhqhsxilqh14F4F4F4hqirhtvhyisshyhtyirjq:00000000FFF4F4F4FF9E81D1FFFFFFFFFF7E57C2FFFFD54FFFFFDF7BFFFF9372FFFF7043FF9777CDFFFFDF78FF8059C2FFFF825BFFEDB920FFF1CA58FFF1CA55FFCDCDCDFFE9E3F3FFFD9372FFFE7145FF9F83D1FFFD9474FFFE7448FFBCA9DDFFFCFCFCFFE8E2F206F4F4F401F4F4F4FFF9B8A4FFF9B8A3FFF4F1F1FFFAB19AFFFC9B7CFFF4F3F2FFFAA286FFF9AF97FFFFFDFCFFFFFCFCFFF9AF98FFFAA489FFF4EFEE")}; app.addMenuItem( { cName: "saveNoAnnots", cUser: "Save Without Markup", oIcon: myIcon, cParent: "File", // Adding to the file menu for the regular UI nPos: "cmd.saveTo", // Adding after the "Save To" option cRbParent: 'JS:QuickAccess', // add to the quick access bar on the ribbon nRbPos: "cmd.save", // put the icon after the 'save' button cEnable: "event.rc = (event.target != null);", // this line is optional: this disables to the tool button when there's no file active cExec: "saveWithoutAnnots(this, true);", });
- See my description above or the pdf documentation I made for the parameters.
- That's it. You save this file into the javascripts folder and you don't need to also save the png there. It will load the next time you restart PDF-XChange.
Plus
Actually there is another simple method to add an icon that I didn't mention above: It's not a custom icon, it's one of the built-in icons to PDF-XChange. Instead of creating the icon file, and saving it or encoding it, you use cIconID instead of oIcon thus:
Code: Select all
cIconID: 'ico.text',