我知道如何使用 PrintDocument 打印图像。但是,我想使用默认的 Windows 打印功能打印我的图像。就像当您右键单击图像并单击打印时,会出现允许您设置大小选择打印机等的对话框。有谁知道如何在 C# 中实现这一点?我必须使用 WINAPI 吗?
干杯
编辑:
我说的是这个打印对话框。
您可以使用 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();
}
使用动词“ 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;
}
这对我有用:
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);
}
}