Print image using windows print image dialog

给你一囗甜甜゛ 提交于 2019-12-22 04:34:14

问题


I know how to print an image using PrintDocument. However, i want to print my Image using the default windows print function. Like when you right click an image and click print, the dialog comes up that allows you to set size choose printer etc. Does anyone know how to achieve this in C#? Do i have to use WINAPI ?

Cheers

Edit:

I'm talking about this print dialog.


回答1:


You can launch that dialog with the Process class.

    private void button1_Click(object sender, EventArgs e)
    {
        string fileName = @"C:\Development\myImage.tif";//pass in or whatever you need
        var p = new Process();
        p.StartInfo.FileName = fileName;
        p.StartInfo.Verb = "Print";
        p.Start();
    }



回答2:


The simple approach with launching a new process using verb "print" is not working on Windows XP at all (it opens Windows Picture and Fax Viewer instead of the Printing Wizard). Also it does not work as intended on Windows 10 (at first run the Default app chooser for images is opened, then the default photo viewer is opened).

The correct approach would be using CLSID_PrintPhotosDropTarget COM object. My code is in C++ (and ATL) but I hope you could translate it in C#. I jast pass file names, but AFAIK you can pass picture itself directly without writing it on disk implementing IDataObject interface.

bool DisplaySystemPrintDialogForImage(const std::vector<CString>& files, HWND hwnd) {
    static const CLSID CLSID_PrintPhotosDropTarget ={ 0x60fd46de, 0xf830, 0x4894, { 0xa6, 0x28, 0x6f, 0xa8, 0x1b, 0xc0, 0x19, 0x0d } };

    CComPtr<IShellFolder> desktop; // namespace root for parsing the path
    HRESULT hr = SHGetDesktopFolder(&desktop);
    if (!SUCCEEDED(hr)) {
        return false;
    }

    CComPtr<IShellItem> psi;
    CComPtr<IDataObject> pDataObject;

    std::vector<LPITEMIDLIST> list;

    for (const auto& fileName : files) {
        PIDLIST_RELATIVE newPIdL;
        hr = desktop->ParseDisplayName(hwnd, nullptr, const_cast<LPWSTR>(static_cast<LPCTSTR>(fileName)), nullptr, &newPIdL, nullptr);
        if (SUCCEEDED(hr)) {
            list.push_back(newPIdL);
        }
    }

    if (!list.empty()) {
        hr = desktop->GetUIObjectOf(hwnd, list.size(), const_cast<LPCITEMIDLIST*>(&list[0]), IID_IDataObject, 0, reinterpret_cast<void**>(&pDataObject));
        if (SUCCEEDED(hr)) {
            // Create the Photo Printing Wizard drop target.
            CComPtr<IDropTarget> spDropTarget;

            hr = CoCreateInstance(CLSID_PrintPhotosDropTarget, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spDropTarget));
            if (SUCCEEDED(hr)) {
                // Drop the data object onto the drop target.
                POINTL pt = { 0 };
                DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;

                spDropTarget->DragEnter(pDataObject, MK_LBUTTON, pt, &dwEffect);

                spDropTarget->Drop(pDataObject, MK_LBUTTON, pt, &dwEffect);
                return true;
            }
        }
    }
    return false;
}



回答3:


This works for me:

internal static class ShellHelper
{
  [ComImport]
  [Guid("00000122-0000-0000-C000-000000000046")]
  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  public interface IDropTarget
  {
    int DragEnter(
        [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
        [In] int grfKeyState,
        [In] Point pt,
        [In, Out] ref int pdwEffect);

    int DragOver(
        [In] int grfKeyState,
        [In] Point pt,
        [In, Out] ref int pdwEffect);

    int DragLeave();

    int Drop(
        [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
        [In] int grfKeyState,
        [In] Point pt,
        [In, Out] ref int pdwEffect);
  }

  internal static void PrintPhotosWizard(string p_FileName)
  {
    IDataObject v_DataObject = new DataObject(DataFormats.FileDrop, new string[] { p_FileName });
    MemoryStream v_MemoryStream = new MemoryStream(4);
    byte[] v_Buffer = new byte[] { (byte)5, 0, 0, 0 };
    v_MemoryStream.Write(v_Buffer, 0, v_Buffer.Length);
    v_DataObject.SetData("Preferred DropEffect", v_MemoryStream);
    Guid CLSID_PrintPhotosDropTarget = new Guid("60fd46de-f830-4894-a628-6fa81bc0190d");
    Type v_DropTargetType = Type.GetTypeFromCLSID(CLSID_PrintPhotosDropTarget, true);
    IDropTarget v_DropTarget = (IDropTarget)Activator.CreateInstance(v_DropTargetType);
    v_DropTarget.Drop((System.Runtime.InteropServices.ComTypes.IDataObject)v_DataObject, 0, new Point(), 0);
  }
}


来源:https://stackoverflow.com/questions/19662130/print-image-using-windows-print-image-dialog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!