【问题标题】:Win32 printing - cannot set landscape modeWin32 打印 - 无法设置横向模式
【发布时间】:2009-03-25 01:50:52
【问题描述】:

我有一个旧应用程序需要以横向模式打印。我找到的文档说要获得一个 DEVMODE 结构,更改几个字段,然后将其放回原处。我得到的是:

    HANDLE printer_handle;
    LPHANDLE printer_handle_pointer(&printer_handle);
    OpenPrinter(printer_name.get(), printer_handle_pointer, NULL);
    size_t devmode_size = DocumentProperties(hWnd, printer_handle_pointer, printer_name.get(), NULL, NULL, 0);
    DEVMODE * devmode = reinterpret_cast<DEVMODE *>(new char[devmode_size]);
    DocumentProperties(NULL, printer_handle_pointer, printer_name.get(), devmode, NULL, DM_OUT_BUFFER);
    devmode->dmSize = sizeof( DEVMODE);
    devmode->dmFields |= DM_ORIENTATION;
    devmode->dmOrientation = DMORIENT_LANDSCAPE;
    DocumentProperties(NULL, printer_handle_pointer, printer_name.get(), devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER);
    hdcPrint = CreateDC(NULL, printer_name.get(), NULL, devmode);

我当前的问题是第一个 DocumentProperties(返回 DEVMODE 结构大小的那个)返回 -1(实际上是无符号等价物),表示出现错误情况。这在 Debug 和 Release 模式下都会发生(我在网上看到的一份报告在 Debug 中遇到了这个问题,但在 Release 中没有)。 printer_name.get() 是有效的,但我不知道如何在调试器中检查 hWndprinter_handle_pointer 的正确性。

所以,如果有人能告诉我我做错了什么,或者如何更好地诊断它,或者如何判断句柄是否有效并指向有效信息,我将不胜感激。

我在 Vista Business SP1 上使用 VS 2008SP1,如果这有什么不同的话。原始应用是在某些版本的 XP 上使用早期版本的 VS 编写的。

【问题讨论】:

    标签: winapi visual-c++ printing


    【解决方案1】:

    你发布了真实的代码吗?

    另外,看看 DocumentProperties 函数签名:

    LONG DocumentProperties(
         __in   HWND hWnd,
         __in   HANDLE hPrinter,         
         __in   LPTSTR pDeviceName,
         __out  PDEVMODE pDevModeOutput,
         __in   PDEVMODE pDevModeInput,
         __in   DWORD fMode
    

    第三个参数采用HANDLE,而不是代码中的HANDLE(或LPHANDLE)指针:

    DocumentProperties(NULL, 
                       printer_handle_pointer, /* <--- ? */
                       printer_name.get(), 
                       devmode, 
                       NULL, 
                       DM_OUT_BUFFER);
    

    改用:

    DocumentProperties(NULL, 
                       printer_handle, /* <--- ? */
                       printer_name.get(), 
                       devmode, 
                       NULL, 
                       DM_OUT_BUFFER);
    

    查看this 示例代码,使用DocumentProperties 函数修改Devmode

    我通常使用GetPrinterW 来获得PRINTER_INFO_2W 结构。 pDevMode 成员返回开发模式。使用这种开发模式我很幸运。

    【讨论】:

    • 感谢您的指点,但 GetPrinter() 技术对我来说并没有更好的效果。
    【解决方案2】:

    来自DocumentProperties 的 Microsoft 文档:

    要更改应用程序本地的打印设置,应用程序应遵循以下步骤:

    1. 通过调用 DocumentProperties 并在 fMode 参数中指定零来获取完整 DEVMODE 结构所需的字节数。
    2. 为完整的 DEVMODE 结构分配内存。
    3. 通过调用 DocumentProperties 获取当前的打印机设置。将指向在步骤 2 中分配的 DEVMODE 结构的指针作为 pDevModeOutput 参数传递,并指定 DM_OUT_BUFFER 值。
    4. 修改返回的 DEVMODE 结构的适当成员,并通过设置 DEVMODE 的 dmFields 成员中的相应位来指示更改了哪些成员。
    5. 调用 DocumentProperties 并将修改后的 DEVMODE 结构作为 pDevModeInput 和 pDevModeOutput 参数传回,并指定 DM_IN_BUFFER 和 DM_OUT_BUFFER 值(使用 OR 运算符组合)。可以使用第三次调用 DocumentProperties 返回的 DEVMODE 结构作为调用 CreateDC 函数的参数。

    您似乎缺少第 1 步,这可能是您第一次调用 DocumentProperties 失败的原因。

    在我自己的程序中,我还设置了页面大小、交换长度和宽度。这是用于具有自定义纸张尺寸的特殊小型标签打印机,但我不知道是否需要更多花园品种的打印机。

    double width = 8.5;
    double height = 11.0;
    devmode.dmFields = DM_ORIENTATION | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH;
    devmode.dmOrientation = DMORIENT_LANDSCAPE;
    devmode.dmPaperSize = DMPAPER_USER;
    devmode.dmPaperLength = (short)(width * 25.4 * 10);
    devmode.dmPaperWidth = (short)(height * 25.4 * 10);
    

    【讨论】:

    • 其实我里面有第1步(行开头“size_t devmode_size”),问题是devmode_size(返回值)不准确。我显然不清楚。
    • 我稍微改变了问题,让它更清楚。希望这会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    相关资源
    最近更新 更多