使用Windows打印图像对话框打印图像

时间:2013-10-29 15:13:40

标签: c# winforms image printing

我知道如何使用PrintDocument打印图像。但是,我想使用默认的Windows打印功能打印我的图像。就像右键单击图像并单击打印一样,会出现一个对话框,允许您设置大小选择打印机等。有人知道如何在C#中实现这一点吗?我必须使用WINAPI吗?

干杯

编辑:

我在谈论这个打印对话框。

enter image description here

3 个答案:

答案 0 :(得分:6)

您可以使用Process类启动该对话框。

    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();
    }

答案 1 :(得分:0)

使用动词“打印”启动新流程的简单方法根本不适用于Windows XP(它会打开Windows图片和传真查看器而不是打印向导)。此外,它在Windows 10上无法正常工作(首次运行图像的默认应用选择器打开,然后打开默认的照片查看器。)

正确的方法是使用 CLSID_PrintPhotosDropTarget COM对象。 我的代码是用C ++(和ATL)编写的,但我希望你能用C#翻译它。 我传递文件名,但是AFAIK你可以直接传递图片本身,而无需在实现IDataObject接口的磁盘上写入。

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;
}

答案 2 :(得分:0)

这对我有用:

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);
  }
}