Using Editor Plugin SDK
Moderators: TrackerSupp-Daniel, Tracker Support, Paul - Tracker Supp, Vasyl-Tracker Dev Team, Chris - Tracker Supp, Sean - Tracker, Ivan - Tracker Software, Tracker Supp-Stefan
Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.
When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.
When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
Using Editor Plugin SDK
How to add a button to a submenu "Advanced" of the main menuBar?
-
- User
- Posts: 5522
- Joined: Fri Nov 21, 2014 8:27 am
- Contact:
Re: Using Editor Plugin SDK
Hello p0w3r,
Please search in the Editor SDK forum - there were several topics on how to add a custom/existing command to the needed bar.
Cheers,
Alex
Please search in the Editor SDK forum - there were several topics on how to add a custom/existing command to the needed bar.
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Re: Using Editor Plugin SDK
Hi
Can you give an example of .pvp plugin with a some functions?
How to use the code from FullDemo (https://github.com/tracker-software/PDF ... p/FullDemo) in plugin (https://github.com/tracker-software/PDF ... uginSample)?
Thanks
Can you give an example of .pvp plugin with a some functions?
How to use the code from FullDemo (https://github.com/tracker-software/PDF ... p/FullDemo) in plugin (https://github.com/tracker-software/PDF ... uginSample)?
Thanks
-
- User
- Posts: 5522
- Joined: Fri Nov 21, 2014 8:27 am
- Contact:
Re: Using Editor Plugin SDK
Hello p0w3r,
Here's a sample project on this matter:
https://github.com/tracker-software/PDF ... uginSample
Cheers,
Alex
Here's a sample project on this matter:
https://github.com/tracker-software/PDF ... uginSample
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Re: Using Editor Plugin SDK
Hi Alex,
Why am I getting an error "Object reference not set to an instance of an object."?
Thanks
Why am I getting an error "Object reference not set to an instance of an object."?
Code: Select all
public void Setup(PXV_Inst pInstance)
{
m_Inst = pInstance;
}
public void Init()
{
//throw new NotImplementedException();
try
{
m_Inst.ActiveMainView.LoadPanesLayout();
// Message: Object reference not set to an instance of an object.
//StackTrace: at PluginSample.MyTestPlugin.Setup(PXV_Inst pInstance) in C:\PDFEditorPluginSample - master\PluginSample\Class1.cs:line 55
}
catch (Exception ex)
{
m_Inst.ShowMsgBox("Message: " + ex.Message + "\nSource: " + ex.Source + "\nTargetSite: " + ex.TargetSite + "\nStackTrace: " + ex.StackTrace + "\nInnerException" + ex.InnerException);
}
}
-
- User
- Posts: 5522
- Joined: Fri Nov 21, 2014 8:27 am
- Contact:
Re: Using Editor Plugin SDK
Hello ActiveMainView,
Is there an ActiveMainView available (is it a non-null value)? You should check all of that things - plugins can be used without the user interface (IPXV_Inst only) - thus you will need to take that into account.
Cheers,
Alex
Is there an ActiveMainView available (is it a non-null value)? You should check all of that things - plugins can be used without the user interface (IPXV_Inst only) - thus you will need to take that into account.
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Re: Using Editor Plugin SDK
Hi Support,
I encountered the same issues using the PluginSample.
The Plugin would be really simple: It should just add a button to the ribbon. (Or as last resort: register a custom command that then can be dragged by the user to any ribbon or command bar, from Help -> Customize Toolbars -> Commands).
Every code snippet I found on the forum requires ActiveMainView or MainFrm. The last method that is called when PDF-XChange Editor is started is
But there those objects are always null.
I got a non-null MainFrm in m_Inst.DoAsync() after Thread.Sleep(1000) to await loading of the UI. But this can't be the solution?
So my question is:
What is the correct event/callback/way to add Buttons to the ribbon within the scaffold of the PluginSample solution?
How can I add my own command to the Help -> Customize Toolbars -> Commands - Menu?
Thanks and kind regards,
Olli
I encountered the same issues using the PluginSample.
The Plugin would be really simple: It should just add a button to the ribbon. (Or as last resort: register a custom command that then can be dragged by the user to any ribbon or command bar, from Help -> Customize Toolbars -> Commands).
Every code snippet I found on the forum requires ActiveMainView or MainFrm. The last method that is called when PDF-XChange Editor is started is
Code: Select all
class MyTestPlugin : IPXV_Plugin
{
public void Init()
{
var mainFormsCount = m_Inst.MainFrmCount; // always 0
var mainFrm = m_Inst.ActiveMainFrm; // null
var mainView = m_Inst.ActiveMainView; // null
}
}
But there those objects are always null.
I got a non-null MainFrm in m_Inst.DoAsync() after Thread.Sleep(1000) to await loading of the UI. But this can't be the solution?
So my question is:
What is the correct event/callback/way to add Buttons to the ribbon within the scaffold of the PluginSample solution?
How can I add my own command to the Help -> Customize Toolbars -> Commands - Menu?
Thanks and kind regards,
Olli
-
- User
- Posts: 5522
- Joined: Fri Nov 21, 2014 8:27 am
- Contact:
Re: Using Editor Plugin SDK
Hello oknpp,
The Init method is being called when the MainFrame is not ready yet. Here's a description for all of the interface methods in one batch (by the way - there is a description for them on the help wiki) - all code is C++, but you can easily convert it to the C#:
Then you will need a custom event listener that will listen to all of the needed events:
And the class itself that is the event listener should be derived from the IEventHandler interface - here's a C++ declaration for it:
The e.customizeCmdLayout event is called when the all of the commands are being added/refreshed and then is the time to add your custom commands. For this you will have to implement your own command handler class:
Both of the Event listener and Command Handler should be a part of the Plugin's class.
When you have a command handler, you can listen to the e.customizeCmdLayout event and add your commands:
Cheers,
Alex
The Init method is being called when the MainFrame is not ready yet. Here's a description for all of the interface methods in one batch (by the way - there is a description for them on the help wiki) - all code is C++, but you can easily convert it to the C#:
Code: Select all
//Unique plugin GUID indentifier
STDMETHODIMP get__GUID(GUID* pGuid);
//Plugin name that will be shown in the Editor's plugins list
STDMETHODIMP get_Name(BSTR* ppName);
//Copyright information
STDMETHODIMP get_CopyrightInfo(BSTR* ppCopyrightInfo);
//Plugin version, that should be increased when new functionality is being added
STDMETHODIMP get_version(ULONG* pVer);
//Plugin's developer identifier (obtained when the SDK key is bought)
STDMETHODIMP get_VendorID(ULONG* pVendorID);
//The plugin description that will be used in the Editor's plugins array
STDMETHODIMP get_Description(BSTR* pDescription);
//Additional information about the usage rights
STDMETHODIMP get_LegalInfo(BSTR* pLegal);
//Information about the plugin developer
STDMETHODIMP get_Publisher(BSTR* pPublisher);
//Additional flags, that can be used for extended plugin features
STDMETHODIMP get_Features(ULONG* pFlags);
//Starting method for plugin initialization - here we get the IPXV_Inst
STDMETHODIMP Setup(IPXV_Inst* pInstance);
//Custom extension registration (if needed)
STDMETHODIMP RegisterExts();
//Reading the needed extensions that are needed for the plugin
STDMETHODIMP FinalizeRegistering();
//Initialization of the plugin with the Editor's UI available (commands, handlers etc)
STDMETHODIMP Init();
//Plugin unload
STDMETHODIMP Unload();
//Showing the plugin preferences dialog, that can be called from the Editor's plugins list
STDMETHODIMP ShowPrefsDlg(SIZE_T hWndParent);
//Importing the unique plugin data when importing the plugin settings
STDMETHODIMP ImportAdditionalData(IAFS_Name* pPathToAppData, IAFS_Name* pPathToUserData) override;
//Exporting the unique plugin data when importing the plugin settings
STDMETHODIMP ExportAdditionalData(IAFS_Name* pPathToAppData, IAFS_Name* pPathToUserData) override;
//This method is being called when the Editor's settings are being reset
STDMETHODIMP ResetSettings(ULONG nFlags) override;
Code: Select all
//Custom listener for the Editor's events
m_pListener = new PDFXEventListener(this);
//The event server is responsible for registration of the event listeners
CComPtr<PXV::IEventServer> es;
m_pInst->get_EventServer(&es);
//Registering our listener to handle the e.customizeCmdLayout event (we'll need the numeric ID of the event here that can be obtained by the Str2ID method of the IPXV_Inst)
es->RegisterNativeEventHandler(id_e_customizeCmdLayout, m_pListener, 0);
es->RegisterNativeEventHandler(id_e_mainView_customizeCmdBars, m_pListener, 0);
es->RegisterNativeEventHandler(id_e_document_toolActivated, m_pListener, 0);
es->RegisterNativeEventHandler(id_e_uiLanguageChanged, m_pListener, 0);
Code: Select all
//Class that implements a listener (IEventHandler) of the registered events that are being sent by the Editor
class PDFXEventListener : public cCoClassDispatchT<PDFXEventListener, IEventHandler> //cCoClassDispatchT - wrapper that implements the AddRef/Release methods for the interface implementation class (in our case - IEventHandler)
{
public:
PDFXEventListener(PDFXETestPlugin* pPlugin)
{
m_pPlugin = pPlugin;
}
public: //IEventHandler interface method implementation
virtual STDMETHODIMP OnEvent(LONG nEventID, IEvent* pEvent, IUnknown* pFrom);
public:
PDFXPlugin* m_pPlugin = nullptr;
};
Code: Select all
//Class that implements a custom command handler interface
class PDFXECmdHandler : public cCoClassUnknownT<PDFXECmdHandler, IUIX_CmdHandler>
{
public:
PDFXECmdHandler(PDFXPlugin* pPlugin)
{
m_pPlugin = pPlugin;
}
public:// IUIX_CmdHandler interface methods implementation
// Method that returns state for the given command (active, disabled etc)
virtual STDMETHODIMP OnGetItemState(IUIX_Cmd* pCmd, IUIX_CmdItem* pItem, IUIX_Obj* pOwner, LONG* pState);
// Method that catches events that happen to our commands (for example it was clicked)
virtual STDMETHODIMP OnNotify(LONG nCode, IUIX_Cmd* pCmd, IUIX_CmdItem* pItem, IUIX_Obj* pOwner, SIZE_T pNotifyData);
//Method that returns a custom command implementation if needed (edit, combo, list etc)
virtual STDMETHODIMP OnCreateNewCtl(IUIX_Cmd* pCmd, IUIX_CmdBar* pParent, IUIX_Obj** ppCtl);
//Returns the size of the custom command implementation control
virtual STDMETHODIMP OnGetCtlSizes(IUIX_CmdItem* pItem, SIZE* pSize, SIZE* pMinSize, SIZE* pMaxSize);
//Here you can manually draw the commands icon in the given rectangle if needed
virtual STDMETHODIMP OnDrawItemIcon(IUIX_RenderContext* pRC, IUIX_CmdItem* pItem, RECT* pIconRect, RECT* pClip);
//Returns the command's submenu if it has one
virtual STDMETHODIMP OnGetItemSubMenu(IUIX_CmdItem* pItem, IUIX_CmdMenu** ppSubMenu);
public:
PDFXETestPlugin* m_pPlugin = nullptr;
};
When you have a command handler, you can listen to the e.customizeCmdLayout event and add your commands:
Code: Select all
//////////////////////////////////////////////////////////////////////////
//PDFXEventListener
//////////////////////////////////////////////////////////////////////////
STDMETHODIMP PDFXEventListener::OnEvent(LONG nEventID, IEvent* pEvent, IUnknown* pFrom)
{
HRESULT hr = S_OK;
if (!pEvent || !pFrom)
return hr;
//This event is being called when the Editor UI commands layout was initialized or modified
//We'll need this to add our custom commands into the Editor's menus
if (nEventID == id_e_customizeCmdLayout)
{
CustomizeCmdLayout(pFrom);
}
//This is needed for correct language change
else if (nEventID == id_e_uiLanguageChanged)
{
m_pPlugin->UpdateCommandsUILang();
}
return hr;
}
void PDFXEventListener::CustomizeCmdLayout(IUnknown* pFrom)
{
//pFrom - a pointer to the event source - in this case it will be the IPXV_View
CComPtr<PXV::IPXV_View> pView;
pFrom->QueryInterface(&pView);
if (!pView)
return;
LONG nViewID = 0;
pView->get_ID(&nViewID);
if (nViewID != id_mainView)
return;
// Here the commands should be added
VARIANT_BOOL bIsRibbon = VARIANT_FALSE;
pView->get_IsRibbonMode(&bIsRibbon);
if (!bIsRibbon)
CustomizeClassicCmdLayout(pView);
else
CustomizeRibbonCmdLayout(pView);
}
bool PDFXEventListener::CustomizeClassicCmdLayout(PXV::IPXV_View* pView)
{
CComPtr<IPXV_MainView> pMV;
if (pView)
pView->QueryInterface(&pMV);
if (!pMV)
return false;
CComPtr<IUIX_CmdBar> pMB;
pMV->get_MenuBar(&pMB);
if (!pMB)
return false;
LONG nIdx = -1;
//Searching whether we have already added the command
pMB->FlatFindFirstItemByCmdID(id_cmd_pdfx_TEST, &nIdx);
if (nIdx < 0)
{
LONG nHelpIndex = -1;
pMB->FlatFindFirstItemByCmdID(id_cmd_help, &nHelpIndex);
CComPtr<IUIX_CmdItem> pItm;
//We'll add it near the help command
pMB->FlatInsertItem2(id_cmd_pdfx_TEST, nHelpIndex + 1, 0, 0, &pItm);
if (pItm)
{
CComPtr<IUIX_CmdMenu> pMenu;
m_pPlugin->m_pUI->CreateCmdMenu(&pMenu);
if (pMenu)
{
pItm->put_SubMenu(pMenu);
nIdx = nHelpIndex + 1;
}
}
}
//If we did find it, then adding a submenu if it does not exit yet
if (nIdx >= 0)
{
CComPtr<IUIX_CmdItem> pCI;
pMB->FlatGetItem(nIdx, &pCI);
if (pCI)
{
CComPtr<IUIX_CmdMenu> pSubMenu;
pCI->get_SubMenu(&pSubMenu);
if (!pSubMenu)
{
m_pPlugin->m_pUI->CreateCmdMenu(&pSubMenu);
pCI->put_SubMenu(pSubMenu);
}
const long aMenuItems[] =
{
id_cmd_pdfx_test1,
0,
id_cmd_pdfx_test2,
id_cmd_pdfx_test3,
0,
id_cmd_pdfx_test4,
};
if (pSubMenu)
{
for (const auto& id : aMenuItems)
{
if (id > 0)
pSubMenu->InsertItem2(id, -1, 0, 0, nullptr, nullptr);
else
pSubMenu->InsertSeparator(-1);
}
}
}
return true;
}
return false;
}
void PDFXEventListener::CustomizeRibbonCmdLayout(PXV::IPXV_View* pView)
{
CComPtr<IUIX_CmdPane> pPane;
pView->get_CmdPaneTop(&pPane);
if (!pPane)
return;
CComPtr<IUIX_Obj> pPaneObj;
pPane->get_Obj(&pPaneObj);
if (!pPaneObj)
return;
CComPtr<IUIX_CmdRibbonTabs> pTabs;
pPane->get_Tabs(&pTabs);
if (!pTabs)
return;
LONG nTabInsertPos = -1;
pTabs->FindByID2(id_rtab_help, &nTabInsertPos);
CComBSTR t1, t2;
//Creating new ribbon tab near the help tab
m_pPlugin->m_pInst->ID2Str(id_pdfx_rtab, &t1);
m_pPlugin->m_pInst->GetLocalStr2(id_pdfx_rtab, &t2);
CComPtr<IUIX_CmdRibbonTab> pTab;
pTabs->InsertNew(t1, t2, PXV::UIX_CmdRibbonTabStyle_Customizable, ++nTabInsertPos, nullptr, &pTab);
const long aMenuItems[] =
{
-id_pdfx_rbar_TEST,
id_cmd_pdfx_test1,
0,
id_cmd_pdfx_test2,
id_cmd_pdfx_test3,
0,
id_cmd_pdfx_test4,
};
CComPtr<IUIX_CmdBar> pBar;
for (auto id : aMenuItems)
{
if (id < 0)
{
id = -id;
pBar = nullptr;
m_pPlugin->m_pInst->ID2Str(id, &t1);
m_pPlugin->m_pInst->GetLocalStr2(id, &t2);
m_pPlugin->m_pUI->CreateCmdBar(pPaneObj, nullptr, t1, t2, UIX_CmdBarStyle_Customizable, &pBar);
if (!pBar)
break;
CComPtr<IUIX_Obj> pViewObj;
pView->get_Obj(&pViewObj);
pBar->put_Owner(pViewObj);
pTab->Insert(pBar, -1);
continue;
}
if (!pBar)
break;
if (id > 0)
{
pBar->FlatInsertItem2(id, -1, 0, 0, nullptr);
}
else
pBar->FlatInsertSeparator(-1, 0, nullptr);
}
}
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Re: Using Editor Plugin SDK
Hi Alex,
thanks for the detailed answer. That helped me so much.
Cheers, Olli
thanks for the detailed answer. That helped me so much.
Cheers, Olli
-
- User
- Posts: 5522
- Joined: Fri Nov 21, 2014 8:27 am
- Contact:
Using Editor Plugin SDK
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ