如何使用 Visual C 在 IE 中的打印模板中将 __IE_PrinterCmd_DevMode 属性设置为 DEVMODE 结构

发布于 2024-12-25 03:23:25 字数 190 浏览 5 评论 0原文

在用户关闭“打印”对话框后,IE 中的打印模板使用此属性来确定有关所选打印机的信息。如何使用 Visual C++ 中的代码将此属性设置为 DEVMODE 结构。 如何将 DEVMODE 结构转换为变体。如果可能的话,我可以将变量传递给打印模板,然后在 jscript 中设置 __IE_PrinterCmd_DevMode 属性。

The print template in IE uses this property to determine information about the selected printer after a user closes the Print dialog box. How can I set this property to a DEVMODE structure with code in Visual C++.
How can I convert DEVMODE structure to variant. If it possible, I can pass variant to print template and then set __IE_PrinterCmd_DevMode property in jscript.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

未蓝澄海的烟 2025-01-01 03:23:26

Marc Durdin 有一篇优秀的博客文章,其中包含 Delphi 中的详细示例。它可以轻松移植到 C++ 和其他语言:

使用 Microsoft WebBrowser 控件和 ShowHTMLDialogEx 揭秘打印


特别是, __IE_PrinterCmd_DevMode 应该是解锁的 HGLOBAL(通常是来自 GlobalAllocGlobalReAlloc)。这在任何地方都没有记录,我猜马克通过反复试验发现了困难的方法,最终发现它与 PRINTDLG.hDevModePRINTDLG.hDevNames 字段,如直接通过调用 PrintDlg 提供

我已经能够通过 HGLOBAL 作为模板脚本的整数并使用它们来初始化 __IE_PrinterCmd_DevMode__IE_PrinterCmd_DevNames,在创建 TemplatePrinter。如果您不想调用 ShowHTMLDialogEx你自己,你已经与你的应用程序挂钩了。我正在使用原始窗口的 external 脚本对象。要从模板访问它,我使用:

dialogArguments.__IE_BrowseDocument.parentWindow.external

PS:将 HGLOBAL 作为整数传递适用于 32 位进程,因为 JScript 的数字实际上是双浮点数,它可以表示最多 53 位的连续整数。但由于此限制,在 64 位进程上将 HGLOBAL 作为整数传递并不可靠。

也许您可以让您的 window.external 对象有一个方法,该方法需要打印模板的 dialogArguments 对象,该方法设置 __IE_PrinterCmd_DevMode__IE_PrinterCmd_DevNames 带有整数 VARIANTVT_I8VT_UI8)。

我还没有测试过。

如果您只想选择系统默认打印机以外的打印机,您也可以设置 __IE_PrinterCMD_Printer 属性。您可以在 JScript 中执行此操作,它将影响 TemplatePrinter设置后创建的行为对象。但是,仅使用此属性,您无法控制初始设置或知道用户最终选择的打印机。

Marc Durdin has an excelent blog post with a detailed example in Delphi. It's easily portable to C++ and other languages:

Demystifying printing with the Microsoft WebBrowser control and ShowHTMLDialogEx

In particular, __IE_PrinterCmd_DevMode should be an unlocked HGLOBAL (typically a valid return value from GlobalAlloc or GlobalReAlloc). This is not documented anywhere, I guess Marc discovered the hard way by trial and error, finally finding it working with the values in the PRINTDLG.hDevMode and PRINTDLG.hDevNames fields, as directly provided by a call to PrintDlg.

I've been able to pass HGLOBALs as integers to a template's script and use them to initialize __IE_PrinterCmd_DevMode and __IE_PrinterCmd_DevNames, before creating a TemplatePrinter. This is handy if you don't want to call ShowHTMLDialogEx yourself and you already have a hook into your application. I'm using the original window's external scripting object. To access it from the template, I use:

dialogArguments.__IE_BrowseDocument.parentWindow.external

PS: Passing an HGLOBAL as an integer works on a 32-bit process, because JScript's numbers are actually double floats, which can represent sequential integers up to 53-bit. But due to this limitation, passing an HGLOBAL as an integer on a 64-bit process is not reliable.

Maybe you can make your window.external object have a method, which expects a print template's dialogArguments object, that sets the __IE_PrinterCmd_DevMode and __IE_PrinterCmd_DevNames with integer VARIANTs (VT_I8 or VT_UI8).

I haven't tested this yet.

If you just want to select a printer other than the system default, you may just as well set the __IE_PrinterCMD_Printer property. You can do it in JScript, it'll affect the TemplatePrinter behavior objects that you create after setting it. However, with this property alone, you cannot control the initial settings or know which printer the user finally chose.

桃扇骨 2025-01-01 03:23:26

我刚刚遇到了同样的问题,并发现 __IE_PrinterCmd_DevMode 和 __IE_PrinterCmd_DevNames 可以从 IntPtr 设置。

这是在 X86 应用程序上,因此不确定在 x64 或 AnyCPU 上会发生什么。

按照建议,我使用一个类通过外部对象传递 DevMode 和 DevNames。

这是代码的主要部分,为此:

Public Class PrintObjCls
 Public Printer As String
 Public DevMode As IntPtr
 Public DevNames As IntPtr
 Public Printing As Boolean
 Public Failed As Boolean 
 Public Progress As Integer
End Class

Sub PrintToTemplate(Web as WebBrowser, Settings as PrinterSettings)
 Dim Obj As New PrintObjCls
 Obj.Printer = Settings.PrinterName
 Obj.DevMode = Settings.GetHdevmode
 Obj.DevNames = Settings.GetHdevnames
 Web.ObjectForScripting = Obj
End Sub

然后在打印模板中

var ext = doc.parentWindow.external;
dialogArguments.__IE_PrinterCMD_Printer = ext.Printer;
dialogArguments.__IE_PrinterCmd_DevMode = ext.DevMode;
dialogArguments.__IE_PrinterCmd_DevNames = ext.DevNames;

I have just had this same issue and have found that __IE_PrinterCmd_DevMode and __IE_PrinterCmd_DevNames can be set from an IntPtr.

This is on a X86 application, so not sure what would happen on x64 or AnyCPU.

As suggested, I use a class to pass in the DevMode and DevNames through the external object.

Here's the main parts of the code, for this:

Public Class PrintObjCls
 Public Printer As String
 Public DevMode As IntPtr
 Public DevNames As IntPtr
 Public Printing As Boolean
 Public Failed As Boolean 
 Public Progress As Integer
End Class

Sub PrintToTemplate(Web as WebBrowser, Settings as PrinterSettings)
 Dim Obj As New PrintObjCls
 Obj.Printer = Settings.PrinterName
 Obj.DevMode = Settings.GetHdevmode
 Obj.DevNames = Settings.GetHdevnames
 Web.ObjectForScripting = Obj
End Sub

Then in the Print Template

var ext = doc.parentWindow.external;
dialogArguments.__IE_PrinterCMD_Printer = ext.Printer;
dialogArguments.__IE_PrinterCmd_DevMode = ext.DevMode;
dialogArguments.__IE_PrinterCmd_DevNames = ext.DevNames;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文