Skip to content

Instantly share code, notes, and snippets.

@Polaringu
Created January 31, 2018 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Polaringu/499c1ff6e72fe8a8c87aecbacca0c97b to your computer and use it in GitHub Desktop.
Save Polaringu/499c1ff6e72fe8a8c87aecbacca0c97b to your computer and use it in GitHub Desktop.
//Drop target that will contain the custom drag and drop implementation for the given object
public MyDropTarget myDropTarget = null; //PS: Do not forget to dispose of it (we do it in Form1_FormClosed)
//Method where the myDropTarget is initialized
void InitializePagesViewAsDropTarget()
{
PDFXEdit.IUIX_Obj obj = pdfCtl.Doc.ActiveView.PagesView.Obj;
//Setting style of the object so it will accept dropping
obj.SetStyleEx((int)PDFXEdit.UIX_ObjStyleExFlags.UIX_ObjStyleEx_DropTarget, (int)PDFXEdit.UIX_ObjStyleExFlags.UIX_ObjStyleEx_DropTarget);
//Creating the drop target and filling it's supported formats
myDropTarget = new MyDropTarget(obj, this);
myDropTarget.AddSuppTextDrop(false);
myDropTarget.AddSuppTextDrop(true);
}
//Class that implements the drop target functionality for the needed object
//In this example the PagesView was used as the "needed object"
public partial class MyDropTarget :
PDFXEdit.IUIX_ObjImpl,
PDFXEdit.IDropTarget,
IDisposable
{
//Here we push implementation of drag and drop functions of the PagesView
public MyDropTarget(PDFXEdit.IUIX_Obj obj, MainFrm parentForm)
{
Obj_ = obj;
if (Obj_ != null)
Obj_.PushImpl(this);
Parent = parentForm;
}
~MyDropTarget()
{
Dispose();
}
//Disposing of all of the links we made with objects and parent
public void Dispose()
{
Parent = null;
if (Disposed_)
return;
Disposed_ = true;
if (Obj_ != null)
{
Obj_.PopImpl(this);
System.Runtime.InteropServices.Marshal.ReleaseComObject(Obj_);
Obj_ = null;
}
}
//Main form - a parent that in our case holds the PDFXEdit control
public MainFrm Parent = null;
//Object for which we are implementing drag and drop
public PDFXEdit.IUIX_Obj Obj_;
//Used for single dispose control
private bool Disposed_ = false;
//Used for checking whether the DragEnter function gave successful results (formats check) - used in DragOver function
private bool SuccessEnter = false;
//List of supported formats that will be dragged onto our object
List<System.Runtime.InteropServices.ComTypes.FORMATETC> m_SuppFmtEtc = new List<System.Runtime.InteropServices.ComTypes.FORMATETC>();
// IUIX_ObjImpl
public PDFXEdit.IUIX_Obj Obj
{
get { return this.Obj_; }
}
//Event listener that listens for e_QueryDropTarget
public void OnEvent(PDFXEdit.IUIX_Obj pSender, PDFXEdit.IUIX_Event pEvent)
{
pEvent.Handled = false;
if (pEvent.Code == (int)PDFXEdit.UIX_EventCodes.e_QueryDropTarget)
{
pEvent.Handled = true;
IntPtr res = IntPtr.Zero;
try
{
//We need to return com interface for PDFXEdit.IDropTarget from the current class as a pEvent.Result
res = System.Runtime.InteropServices.Marshal.GetComInterfaceForObject(this, typeof(PDFXEdit.IDropTarget));
}
catch (Exception e)
{
Debug.WriteLine("pdfCtl.OnEvent: e.nEventID=={0}", e.Message);
}
if (res != IntPtr.Zero)
pEvent.Result = (uint)res; // = (long)res for x64
}
else if (pEvent.Code == (int)PDFXEdit.UIX_EventCodes.e_BeforeDestroy)
{
Dispose();
}
else if (pEvent.Code == (int)PDFXEdit.UIX_EventCodes.e_Last)
{
Dispose();
}
}
//Method that adds text support formats into the m_SuppFmtEtc
public bool AddSuppTextDrop(bool bUnicode)
{
System.Runtime.InteropServices.ComTypes.FORMATETC FmtEtc = new System.Runtime.InteropServices.ComTypes.FORMATETC();
if (bUnicode == false)
FmtEtc.cfFormat = 1; //CF_TEXT
else
FmtEtc.cfFormat = 13; //CF_UNICODETEXT
FmtEtc.dwAspect = System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT;
FmtEtc.lindex = -1;
FmtEtc.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_HGLOBAL;
return AddSuppFmt(FmtEtc);
}
//Method that adds a new format into the m_SuppFmtEtc
public bool AddSuppFmt(System.Runtime.InteropServices.ComTypes.FORMATETC FmtEtc)
{
if (FmtEtc.cfFormat == 0)
return false;
for (int i = 0; i < m_SuppFmtEtc.Count(); i++)
{
if (FmtEtc.cfFormat == m_SuppFmtEtc[i].cfFormat)
{
m_SuppFmtEtc[i] = FmtEtc;
return true;
}
}
m_SuppFmtEtc.Add(FmtEtc);
return true;
}
//Method that gets FORMATETC and STGMEDIUM from the IDataObject
public bool GetFormatAndStgMedium(PDFXEdit.IDataObject pDataObj, ref System.Runtime.InteropServices.ComTypes.FORMATETC fmt, ref System.Runtime.InteropServices.ComTypes.STGMEDIUM med)
{
//Running through the m_SuppFmtEtc and checking whether the dragged IDataObject is correct for one of them
System.Runtime.InteropServices.ComTypes.IDataObject obj = (System.Runtime.InteropServices.ComTypes.IDataObject)pDataObj;
for (int i = 0; i < m_SuppFmtEtc.Count(); i++)
{
try
{
//Getting STGMEDIUM data from IDataObject with the FORMATETC from the current iteration
obj.GetData(m_SuppFmtEtc[i], out med);
if (med.tymed != System.Runtime.InteropServices.ComTypes.TYMED.TYMED_NULL)
{
fmt = m_SuppFmtEtc[i];
return true;
}
}
catch (Exception e)
{
Debug.WriteLine("pdfCtl.OnEvent: e.nEventID=={0}", e.Message);
}
}
return false;
}
public void OnPostEvent(PDFXEdit.IUIX_Obj pSender, PDFXEdit.IUIX_Event pEvent)
{
}
public void OnPreEvent(PDFXEdit.IUIX_Obj pSender, PDFXEdit.IUIX_Event pEvent)
{
}
/// <summary>
/// Provides access to Win32-level constants, structures, and functions.
/// </summary>
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern int GlobalSize(IntPtr hMem);
//
public void DragEnter(PDFXEdit.IDataObject pDataObj, uint grfKeyState, PDFXEdit._POINTL pt, ref uint pdwEffect)
{
pdwEffect = (uint)DragDropEffects.None;
SuccessEnter = false;
System.Runtime.InteropServices.ComTypes.FORMATETC fmtEtc = new System.Runtime.InteropServices.ComTypes.FORMATETC();
System.Runtime.InteropServices.ComTypes.STGMEDIUM medium = new System.Runtime.InteropServices.ComTypes.STGMEDIUM();
//Getting FORMATETC and STGMEDIUM from the IDataObject
if (GetFormatAndStgMedium(pDataObj, ref fmtEtc, ref medium) == true)
{
//If we succeeded then doing the page hit test
//PDFXEdit.PXC_Point ptn = new PDFXEdit.PXC_Point();
//if (Parent.HitTestPage(pt, out ptn) >= 0)
pdwEffect = (uint)DragDropEffects.Copy; //If we are on a page then changing the cursor
SuccessEnter = true;
}
}
public void DragLeave()
{
SuccessEnter = false;
}
public void DragOver(uint grfKeyState, PDFXEdit._POINTL pt, ref uint pdwEffect)
{
pdwEffect = (uint)DragDropEffects.None;
//If we got valid FORMATETC and STGMEDIUM in the DragEnter method then we can do the page hit test
if (SuccessEnter != false)
{
//PDFXEdit.PXC_Point ptn = new PDFXEdit.PXC_Point();
//if (Parent.HitTestPage(pt, out ptn) >= 0)
pdwEffect = (uint)DragDropEffects.Copy;
}
}
public void Drop(PDFXEdit.IDataObject pDataObj, uint grfKeyState, PDFXEdit._POINTL pt, ref uint pdwEffect)
{
SuccessEnter = false;
System.Runtime.InteropServices.ComTypes.FORMATETC fmtEtc = new System.Runtime.InteropServices.ComTypes.FORMATETC();
System.Runtime.InteropServices.ComTypes.STGMEDIUM medium = new System.Runtime.InteropServices.ComTypes.STGMEDIUM();
//Getting FORMATETC and STGMEDIUM from the IDataObject
if (GetFormatAndStgMedium(pDataObj, ref fmtEtc, ref medium) == true)
{
//If it's a global drag and drop and we've got the correct data
if (medium.tymed == System.Runtime.InteropServices.ComTypes.TYMED.TYMED_HGLOBAL)
{
//Getting data from the STGMEDIUM
var ptr = GlobalLock(medium.unionmember);
if (ptr != IntPtr.Zero)
{
try
{
var length = (Int32)GlobalSize(ptr);
var data = new byte[length];
Marshal.Copy(ptr, data, 0, length);
//Now we have a result string that has our dragged text
string result = System.Text.Encoding.UTF8.GetString(data).TrimEnd('\0');
//Adding Text annotation that contains that text
Parent.AddAnnotFromText(pt, result);
}
finally
{
GlobalUnlock(medium.unionmember);
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment