10

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

干杯

编辑:

我说的是这个打印对话框。

在此处输入图像描述

4

3 回答 3

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();
    }
于 2013-10-29T15:18:31.910 回答
0

使用动词“ print ”启动新进程的简单方法在 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;
}
于 2016-03-27T10:48:34.313 回答
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);
  }
}
于 2018-09-08T10:36:46.747 回答