none
Print multiple images via Photo Printing Dialog RRS feed

  • Question

  • Hi there!

    First of all I'd like to say sorry about my English!

    Is there any way that I can print multiple pictures at ONE Photo Printing Dialog? 

    I've tried Verb = "Print", but it can only print ONE image.
    What I want to do is, selecting a few images, right clicking and selecting Print option. (Thats how user can select page layout)

    Is there any way to do that with C#?

    Best regards!

    Thursday, October 12, 2017 5:42 PM

Answers

  • Thank you for the fast answer!
    I'am not good at C++, can you provide a very basic sample code please?

    I quickly converted it to C# (tested on Windows 10) =>

    {
       System.Windows.Forms.OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
       openFileDialog1.Filter = "JPEG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif|All Files (*.*)|*.*|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png|TIFF Files (*.tif, *.tiff)|*.tif;*.tiff|Icon Files (*.ico)|*.ico";
       openFileDialog1.FilterIndex = 1;
       openFileDialog1.Multiselect = true;
       DialogResult result = openFileDialog1.ShowDialog();
       if (result == DialogResult.OK)
       {
           HRESULT hr = HRESULT.E_FAIL;
           IntPtr pidlParent = IntPtr.Zero, pidlFull = IntPtr.Zero, pidlItem = IntPtr.Zero;
           var aPidl = new IntPtr[255];
           uint rgflnOut = 0;
           uint nIndex = 0;
           int nCount = openFileDialog1.FileNames.Length;
           if (nCount == 1)
           {
               hr = SHILCreateFromPath(openFileDialog1.FileNames[0], out pidlFull, ref rgflnOut);
               if (hr == HRESULT.S_OK)
               {
                   pidlItem = ILFindLastID(pidlFull);
                   aPidl[nIndex++] = ILClone(pidlItem);
                   ILRemoveLastID(pidlFull);
                   pidlParent = ILClone(pidlFull);
                   ILFree(pidlFull);
               }
           }
           else if (nCount > 1)
           { 
               string sPath = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
               hr = SHILCreateFromPath(sPath, out pidlParent, ref rgflnOut);
               foreach (String file in openFileDialog1.FileNames)
               {
                   hr = SHILCreateFromPath(file, out pidlFull, ref rgflnOut);
                   if (hr == HRESULT.S_OK)
                   {
                       pidlItem = ILFindLastID(pidlFull);
                       aPidl[nIndex++] = ILClone(pidlItem);
                       ILFree(pidlFull);
                   }
               }
           }
           if (nIndex > 0)
           {
               System.Runtime.InteropServices.ComTypes.IDataObject pdo;
               hr = SHCreateFileDataObject(pidlParent, nIndex, aPidl, null, out pdo);
               if (hr == HRESULT.S_OK)
               {
                   Guid CLSID_PrintPhotosDropTarget = new Guid("60fd46de-f830-4894-a628-6fa81bc0190d");
                   Type DropTargetType = Type.GetTypeFromCLSID(CLSID_PrintPhotosDropTarget, true);
                   object DropTarget = Activator.CreateInstance(DropTargetType);
                   IDropTarget pDropTarget = (IDropTarget)DropTarget;
    
                   int pdwEffect = DROPEFFECT_NONE;
                   POINT pt;
                   pt.X = 0;
                   pt.Y = 0;
                   hr = pDropTarget.Drop(pdo, 0, pt, pdwEffect);
               }                        
           }
           if (pidlParent != IntPtr.Zero)
           {
               ILFree(pidlParent);
           }
    
           for (int i = 0; i < nIndex; i++)
           {
               if (aPidl[i] != IntPtr.Zero)
               {
                   ILFree(aPidl[i]);
               }
           }
       }
    }

    Declarations :

    public enum HRESULT : int
    {
       DRAGDROP_S_CANCEL = 0x00040101,
       DRAGDROP_S_DROP = 0x00040100,
       DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102,
       DATA_S_SAMEFORMATETC = 0x00040130,
       S_OK = 0,
       S_FALSE = 1,
       E_NOINTERFACE = unchecked((int)0x80004002),
       E_NOTIMPL = unchecked((int)0x80004001),
       OLE_E_ADVISENOTSUPPORTED = unchecked((int)80040003),
       E_FAIL = unchecked((int)0x80004005),
       MK_E_NOOBJECT = unchecked((int)0x800401E5)
    }
    
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
    
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr ILFindLastID(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr ILClone(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern Boolean ILRemoveLastID(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern void ILFree(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "#740")]
    public static extern HRESULT SHCreateFileDataObject(IntPtr pidlFolder, uint cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, out System.Runtime.InteropServices.ComTypes.IDataObject ppdtobj);
    
    public const int DROPEFFECT_NONE = (0);
    [ComImport]
    [Guid("00000122-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDropTarget
    {
        HRESULT DragEnter(
            [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    
        HRESULT DragOver(
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    
        HRESULT DragLeave();
    
        HRESULT Drop(
            [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    }

    • Marked as answer by CKOCE Friday, October 13, 2017 5:31 PM
    Friday, October 13, 2017 5:08 PM

All replies

  • Hello CKOCE,

    I’m not clear about your request.Do you mean print multiple images on a single page or select multiple pictures at once to print a queue .

    The two ways of printing both use PrintDocument class in C# . If it is the former situation , you should redefine layout of multiple photos on a single page and print once.If it is the latter case , you should specify  each photo path and loop to print. Please clarify your purposes.

    Sincerely,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, October 13, 2017 7:45 AM
    Moderator
  • Hi.

    My point is,  print images as shown below using C#.
    As you know, you can set print layout on this Print Pictures dialog. My application creates multiple jpg images on the background. So, i want to print them via this dialog to allow user to select layout.

    https://i.stack.imgur.com/mboSe.gif


    • Edited by CKOCE Friday, October 13, 2017 10:44 AM
    Friday, October 13, 2017 10:43 AM
  • Hi.

    My point is,  print images as shown below using C#.
    As you know, you can set print layout on this Print Pictures dialog. My application creates multiple jpg images on the background. So, i want to print them via this dialog to allow user to select layout.

    https://i.stack.imgur.com/mboSe.gif


    It can be done with CLSID_PrintPhotosDropTarget

    (MSDN : Photo Printing Wizard)

    I used SHCreateFileDataObject to get the IDataObject interface from the files. (I only tested in C++ (VS 2015, Windows 10) because it is easier...)





    • Edited by Castorix31 Friday, October 13, 2017 2:01 PM
    Friday, October 13, 2017 1:27 PM
  • Thank you for the fast answer!
    I'am not good at C++, can you provide a very basic sample code please?
    • Edited by CKOCE Friday, October 13, 2017 2:20 PM
    Friday, October 13, 2017 2:11 PM
  • Thank you for the fast answer!
    I'am not good at C++, can you provide a very basic sample code please?

    I quickly converted it to C# (tested on Windows 10) =>

    {
       System.Windows.Forms.OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
       openFileDialog1.Filter = "JPEG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif|All Files (*.*)|*.*|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png|TIFF Files (*.tif, *.tiff)|*.tif;*.tiff|Icon Files (*.ico)|*.ico";
       openFileDialog1.FilterIndex = 1;
       openFileDialog1.Multiselect = true;
       DialogResult result = openFileDialog1.ShowDialog();
       if (result == DialogResult.OK)
       {
           HRESULT hr = HRESULT.E_FAIL;
           IntPtr pidlParent = IntPtr.Zero, pidlFull = IntPtr.Zero, pidlItem = IntPtr.Zero;
           var aPidl = new IntPtr[255];
           uint rgflnOut = 0;
           uint nIndex = 0;
           int nCount = openFileDialog1.FileNames.Length;
           if (nCount == 1)
           {
               hr = SHILCreateFromPath(openFileDialog1.FileNames[0], out pidlFull, ref rgflnOut);
               if (hr == HRESULT.S_OK)
               {
                   pidlItem = ILFindLastID(pidlFull);
                   aPidl[nIndex++] = ILClone(pidlItem);
                   ILRemoveLastID(pidlFull);
                   pidlParent = ILClone(pidlFull);
                   ILFree(pidlFull);
               }
           }
           else if (nCount > 1)
           { 
               string sPath = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
               hr = SHILCreateFromPath(sPath, out pidlParent, ref rgflnOut);
               foreach (String file in openFileDialog1.FileNames)
               {
                   hr = SHILCreateFromPath(file, out pidlFull, ref rgflnOut);
                   if (hr == HRESULT.S_OK)
                   {
                       pidlItem = ILFindLastID(pidlFull);
                       aPidl[nIndex++] = ILClone(pidlItem);
                       ILFree(pidlFull);
                   }
               }
           }
           if (nIndex > 0)
           {
               System.Runtime.InteropServices.ComTypes.IDataObject pdo;
               hr = SHCreateFileDataObject(pidlParent, nIndex, aPidl, null, out pdo);
               if (hr == HRESULT.S_OK)
               {
                   Guid CLSID_PrintPhotosDropTarget = new Guid("60fd46de-f830-4894-a628-6fa81bc0190d");
                   Type DropTargetType = Type.GetTypeFromCLSID(CLSID_PrintPhotosDropTarget, true);
                   object DropTarget = Activator.CreateInstance(DropTargetType);
                   IDropTarget pDropTarget = (IDropTarget)DropTarget;
    
                   int pdwEffect = DROPEFFECT_NONE;
                   POINT pt;
                   pt.X = 0;
                   pt.Y = 0;
                   hr = pDropTarget.Drop(pdo, 0, pt, pdwEffect);
               }                        
           }
           if (pidlParent != IntPtr.Zero)
           {
               ILFree(pidlParent);
           }
    
           for (int i = 0; i < nIndex; i++)
           {
               if (aPidl[i] != IntPtr.Zero)
               {
                   ILFree(aPidl[i]);
               }
           }
       }
    }

    Declarations :

    public enum HRESULT : int
    {
       DRAGDROP_S_CANCEL = 0x00040101,
       DRAGDROP_S_DROP = 0x00040100,
       DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102,
       DATA_S_SAMEFORMATETC = 0x00040130,
       S_OK = 0,
       S_FALSE = 1,
       E_NOINTERFACE = unchecked((int)0x80004002),
       E_NOTIMPL = unchecked((int)0x80004001),
       OLE_E_ADVISENOTSUPPORTED = unchecked((int)80040003),
       E_FAIL = unchecked((int)0x80004005),
       MK_E_NOOBJECT = unchecked((int)0x800401E5)
    }
    
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
    
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr ILFindLastID(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr ILClone(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern Boolean ILRemoveLastID(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern void ILFree(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "#740")]
    public static extern HRESULT SHCreateFileDataObject(IntPtr pidlFolder, uint cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, out System.Runtime.InteropServices.ComTypes.IDataObject ppdtobj);
    
    public const int DROPEFFECT_NONE = (0);
    [ComImport]
    [Guid("00000122-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDropTarget
    {
        HRESULT DragEnter(
            [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    
        HRESULT DragOver(
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    
        HRESULT DragLeave();
    
        HRESULT Drop(
            [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    }

    • Marked as answer by CKOCE Friday, October 13, 2017 5:31 PM
    Friday, October 13, 2017 5:08 PM
  • Thank you for the fast answer!
    I'am not good at C++, can you provide a very basic sample code please?

    I quickly converted it to C# (tested on Windows 10) =>

    {
       System.Windows.Forms.OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
       openFileDialog1.Filter = "JPEG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif|All Files (*.*)|*.*|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png|TIFF Files (*.tif, *.tiff)|*.tif;*.tiff|Icon Files (*.ico)|*.ico";
       openFileDialog1.FilterIndex = 1;
       openFileDialog1.Multiselect = true;
       DialogResult result = openFileDialog1.ShowDialog();
       if (result == DialogResult.OK)
       {
           HRESULT hr = HRESULT.E_FAIL;
           IntPtr pidlParent = IntPtr.Zero, pidlFull = IntPtr.Zero, pidlItem = IntPtr.Zero;
           var aPidl = new IntPtr[255];
           uint rgflnOut = 0;
           uint nIndex = 0;
           int nCount = openFileDialog1.FileNames.Length;
           if (nCount == 1)
           {
               hr = SHILCreateFromPath(openFileDialog1.FileNames[0], out pidlFull, ref rgflnOut);
               if (hr == HRESULT.S_OK)
               {
                   pidlItem = ILFindLastID(pidlFull);
                   aPidl[nIndex++] = ILClone(pidlItem);
                   ILRemoveLastID(pidlFull);
                   pidlParent = ILClone(pidlFull);
                   ILFree(pidlFull);
               }
           }
           else if (nCount > 1)
           { 
               string sPath = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
               hr = SHILCreateFromPath(sPath, out pidlParent, ref rgflnOut);
               foreach (String file in openFileDialog1.FileNames)
               {
                   hr = SHILCreateFromPath(file, out pidlFull, ref rgflnOut);
                   if (hr == HRESULT.S_OK)
                   {
                       pidlItem = ILFindLastID(pidlFull);
                       aPidl[nIndex++] = ILClone(pidlItem);
                       ILFree(pidlFull);
                   }
               }
           }
           if (nIndex > 0)
           {
               System.Runtime.InteropServices.ComTypes.IDataObject pdo;
               hr = SHCreateFileDataObject(pidlParent, nIndex, aPidl, null, out pdo);
               if (hr == HRESULT.S_OK)
               {
                   Guid CLSID_PrintPhotosDropTarget = new Guid("60fd46de-f830-4894-a628-6fa81bc0190d");
                   Type DropTargetType = Type.GetTypeFromCLSID(CLSID_PrintPhotosDropTarget, true);
                   object DropTarget = Activator.CreateInstance(DropTargetType);
                   IDropTarget pDropTarget = (IDropTarget)DropTarget;
    
                   int pdwEffect = DROPEFFECT_NONE;
                   POINT pt;
                   pt.X = 0;
                   pt.Y = 0;
                   hr = pDropTarget.Drop(pdo, 0, pt, pdwEffect);
               }                        
           }
           if (pidlParent != IntPtr.Zero)
           {
               ILFree(pidlParent);
           }
    
           for (int i = 0; i < nIndex; i++)
           {
               if (aPidl[i] != IntPtr.Zero)
               {
                   ILFree(aPidl[i]);
               }
           }
       }
    }

    Declarations :

    public enum HRESULT : int
    {
       DRAGDROP_S_CANCEL = 0x00040101,
       DRAGDROP_S_DROP = 0x00040100,
       DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102,
       DATA_S_SAMEFORMATETC = 0x00040130,
       S_OK = 0,
       S_FALSE = 1,
       E_NOINTERFACE = unchecked((int)0x80004002),
       E_NOTIMPL = unchecked((int)0x80004001),
       OLE_E_ADVISENOTSUPPORTED = unchecked((int)80040003),
       E_FAIL = unchecked((int)0x80004005),
       MK_E_NOOBJECT = unchecked((int)0x800401E5)
    }
    
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
    
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr ILFindLastID(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr ILClone(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern Boolean ILRemoveLastID(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern void ILFree(IntPtr pidl);
    
    [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "#740")]
    public static extern HRESULT SHCreateFileDataObject(IntPtr pidlFolder, uint cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, out System.Runtime.InteropServices.ComTypes.IDataObject ppdtobj);
    
    public const int DROPEFFECT_NONE = (0);
    [ComImport]
    [Guid("00000122-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDropTarget
    {
        HRESULT DragEnter(
            [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    
        HRESULT DragOver(
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    
        HRESULT DragLeave();
    
        HRESULT Drop(
            [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
            [In] int grfKeyState,
            [In] POINT pt,
            [In, Out] ref int pdwEffect);
    }

    You are great! It is working perfectly! 
    POINT was missing, I've added. 

    Thank you so much!

    I've been looking for this for 4 days :)

    Friday, October 13, 2017 5:32 PM