zoukankan      html  css  js  c++  java
  • 如何以编程方式打印到在 MFC 中的非默认打印机

    http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105790245b09c0252bd7a74a2485d315d2390f07506694ea7a7d0d5d83d87f6305ac4957f7b86c65377571eb8f8dd50a8bb485582a9f5631671df65663d50edcba5154cb37e12efeae69f0caf625e7aec5a5de4320c944040a9780fb4d7467&p=c4759a46d7c002fb09be9b7c5b5390&newp=b471c54ad5c242fe19f3cb2d02148c231610db2151ddd4122e958d17&user=baidu&fm=sc&query=%B7%C7%C4%AC%C8%CF%B4%F2%D3%A1%BB%FA&qid=f3d87aaa0004b57b&p1=2

    文章编号: 166129 - 查看本文应用于的产品

    : Microsoft Visual c + +.net (2002) 支持这两个托管的代码模型所提供的.net 框架和非托管本机 Windows 代码模型。本文中信息的部分或全部适用于托管的 Visual c + + 代码,可能只能通过使用.net 框架应用。
    展开全部 | 关闭全部

    Collapse image本文内容

    Collapse image概要

    在 开发 MFC 应用程序,它有时是用于以编程方式打印到网络打印机或 $ 辅助打印机的非默认打印机的 (不带打印对话框)。若要执行此操作需要 DEVMODE 和 DEVNAMES 结构。这篇文章显示了一个可以设置最多使用 GetPrinter() 调用这些数据结构的方式,并提供有关如何使用它们的示例。

    : 在这篇文章中的某些代码不能应用于 Windows 95 和 Windows 98 由于 GetPrinter 可能不适用于网络打印机。

    Collapse image更多信息

    在 MFC 应用程序的正常打印操作,过程中打印对话框将显示该对话框可选择要打印到的打印机。在打印对话框中显示的默认打印机是在操作系统中指定的默认打印机。 MFC 将存储在默认打印机 CWinApp::m_hDevMode 和 CWinApp::m_hDevNames 中应用程序的受保护的数据成员。因为 MFC 将初始化为 NULL 这些变量,MFC 的打印体系结构默认操作系统的默认打印机第一次执行时打印操作。操作系统默认打印机的 DEVMODE 和 DEVNAMES 然后复制到在 MFC 应用程序的 m_hDevMode 和 m_hDevNames 数据成员。

    有时,可能会在需要打印到默认打印机以外的其他打印机,而无需用户通过打印对话框中指定它的情况。辅助打印机或 $ 网络打印机 (假定您的操作系统都已经安装了驱动程序),可以使用非默认打印机

    无 论您需要使用非默认打印机在永久的基础上或只有一个打印作业,您将需要 DEVMODE 和 DEVNAMES 结构创建 DC 上的打印机。从 GetPrinter() PRINTER_INFO_2 结构包含填充 DEVMODE 和 DEVNAMES 结构所需的全部信息。

    创建一个 DEVMODE 和 DEVNAMES 结构

    下面的代码示例演示如何使用 GetPrinter() 创建 DEVMODE 和 DEVNAMES 结构基于打印机名称。该代码是全局函数的返回数据结构,通过它的参数。
    #include <winspool.h>
    
    // returns a DEVMODE and DEVNAMES for the printer name specified
    BOOL GetPrinterDevice(LPTSTR pszPrinterName, HGLOBAL* phDevNames, HGLOBAL* phDevMode)
    {
        // if NULL is passed, then assume we are setting app object's
        // devmode and devnames
        if (phDevMode == NULL || phDevNames == NULL)
            return FALSE;
    
        // Open printer
        HANDLE hPrinter;
        if (OpenPrinter(pszPrinterName, &hPrinter, NULL) == FALSE)
            return FALSE;
    
        // obtain PRINTER_INFO_2 structure and close printer
        DWORD dwBytesReturned, dwBytesNeeded;
        GetPrinter(hPrinter, 2, NULL, 0, &dwBytesNeeded);
        PRINTER_INFO_2* p2 = (PRINTER_INFO_2*)GlobalAlloc(GPTR,
            dwBytesNeeded);
        if (GetPrinter(hPrinter, 2, (LPBYTE)p2, dwBytesNeeded,
           &dwBytesReturned) == 0) {
           GlobalFree(p2);
           ClosePrinter(hPrinter);
           return FALSE;
        }
        ClosePrinter(hPrinter);
    
        // Allocate a global handle for DEVMODE
        HGLOBAL  hDevMode = GlobalAlloc(GHND, sizeof(*p2->pDevMode) +
           p2->pDevMode->dmDriverExtra);
        ASSERT(hDevMode);
        DEVMODE* pDevMode = (DEVMODE*)GlobalLock(hDevMode);
        ASSERT(pDevMode);
    
        // copy DEVMODE data from PRINTER_INFO_2::pDevMode
        memcpy(pDevMode, p2->pDevMode, sizeof(*p2->pDevMode) +
           p2->pDevMode->dmDriverExtra);
        GlobalUnlock(hDevMode);
    
        // Compute size of DEVNAMES structure from PRINTER_INFO_2's data
        DWORD drvNameLen = lstrlen(p2->pDriverName)+1;  // driver name
        DWORD ptrNameLen = lstrlen(p2->pPrinterName)+1; // printer name
        DWORD porNameLen = lstrlen(p2->pPortName)+1;    // port name
    
        // Allocate a global handle big enough to hold DEVNAMES.
        HGLOBAL hDevNames = GlobalAlloc(GHND,
            sizeof(DEVNAMES) +
            (drvNameLen + ptrNameLen + porNameLen)*sizeof(TCHAR));
        ASSERT(hDevNames);
        DEVNAMES* pDevNames = (DEVNAMES*)GlobalLock(hDevNames);
        ASSERT(pDevNames);
    
        // Copy the DEVNAMES information from PRINTER_INFO_2
        // tcOffset = TCHAR Offset into structure
        int tcOffset = sizeof(DEVNAMES)/sizeof(TCHAR);
        ASSERT(sizeof(DEVNAMES) == tcOffset*sizeof(TCHAR));
    
        pDevNames->wDriverOffset = tcOffset;
        memcpy((LPTSTR)pDevNames + tcOffset, p2->pDriverName,
            drvNameLen*sizeof(TCHAR));
        tcOffset += drvNameLen;
    
        pDevNames->wDeviceOffset = tcOffset;
        memcpy((LPTSTR)pDevNames + tcOffset, p2->pPrinterName,
            ptrNameLen*sizeof(TCHAR));
        tcOffset += ptrNameLen;
    
        pDevNames->wOutputOffset = tcOffset;
        memcpy((LPTSTR)pDevNames + tcOffset, p2->pPortName,
            porNameLen*sizeof(TCHAR));
        pDevNames->wDefault = 0;
    
        GlobalUnlock(hDevNames);
        GlobalFree(p2);   // free PRINTER_INFO_2
    
        // set the new hDevMode and hDevNames
        *phDevMode = hDevMode;
        *phDevNames = hDevNames;
        return TRUE;
    }
    				


    作为了快速参考下面是 DEVNAMES 的声明与每个字段的简短说明:
    // commdlg.h
    // the first three members are character offsets from the beginning of the // structure pointing to the specific string
    typedef struct tagDEVNAMES {
       WORD wDriverOffset;  // file name of driver (without extension)
       WORD wDeviceOffset;  // device name
       WORD wOutputOffset;  // device name of physical output medium
       WORD wDefault;       // DN_DEFAULTPRN if default printer chosen
    } DEVNAMES;
    				


    设置应用程序的默认打印机

    若要设置默认打印机,您需要设置 m_hDevNames 和 m_hDevMode 数据成员 (它受保护) 该 CWinApp 的成员函数通过该应用程序的派生对象,GetPrinterDevice()。您可以实现下面的函数,并调用它时您需要更改默认打印机。
    void CMainFrame::OnActionSetnondefaultprinter() 
    {
        HGLOBAL hDevMode = NULL;
        HGLOBAL hDevNames = NULL;
        if (GetPrinterDevice(_T("\\RED-PRN-25\PRIV0006"), &hDevNames, &hDevMode))
            AfxGetApp()->SelectPrinter(hDevNames, hDevMode);
        else
            AfxMessageBox(_T("Failed to select custom printer"));
    }
    				


    绕过打印对话框时使用应用程序的默认打印机

    若要绕过打印对话框,OnPreparePrinting 需要被重写,以便可以将 m_bDirect 标志设置为 TRUE。然后调用 DoPreparePrinting,以设置-> m_pd.hDevMode m_pPD pInfo 的值和 pInfo-> m_pPD-> m_pd.hDevNames 到相应的应用程序对象的数据成员和创建 DC 上的打印机。
    BOOL CNonDefPrinterView::OnPreparePrinting(CPrintInfo* pInfo)
    {
        pInfo->m_bDirect = TRUE; // TRUE if bypassing Print Dialog
        return DoPreparePrinting(pInfo);
    }
    				


    绕过打印对话框时使用非默认打印机

    要跳过打印对话框,并使用非默认打印机,您需要-> m_pd m_pPD pInfo 数据成员自己设置和创建 DC 上的打印机。以下是将实现此目的的代码:
    BOOL CNonDefPrinterView::OnPreparePrinting(CPrintInfo* pInfo)
    {
        // set to non-default printer without changing default app printer
        HGLOBAL hDevMode;
        HGLOBAL hDevNames;
    
        if (!GetPrinterDevice(_T("\\RED-PRN-25\PRIV0006"), &hDevNames, &hDevMode))
            AfxMessageBox(_T("GetPrinterDevice called failed
    "));
    
        pInfo->m_pPD->m_pd.hDevMode = hDevMode;
        pInfo->m_pPD->m_pd.hDevNames = hDevNames;
        pInfo->m_pPD->CreatePrinterDC();
    
        return TRUE;
    }
    				

    本示例显示了使用 GetPrinterDevice 函数。有关更多详细信息,请参见上面。
  • 相关阅读:
    WPF 关于拖拽打开文件的注意事项
    asp.net core 3.1中对Mongodb BsonDocument的序列化和反序列化支持
    用百度webuploader分片上传大文件
    多线程学习笔记
    web.config数据库连接字符串加密
    Visual Studio 2010 常用快捷方式
    Team Foundation Server 2013 日常使用使用手册(四)分支与合并
    Team Foundation Server 2013 日常使用使用手册(三)上传新工程、创建任务、创建bug、设置预警
    Team Foundation Server 2013 日常使用使用手册(二)修改、签入、撤销、回滚、对比代码变更
    Team Foundation Server 2013 日常使用使用手册(一)-本地连接TFS、查看任务
  • 原文地址:https://www.cnblogs.com/CodeGear/p/4166491.html
Copyright © 2011-2022 走看看