如何以编程方式打印到在 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 函数。有关更多详细信息,请参见上面。
原文地址:https://www.cnblogs.com/CodeGear/p/4166491.html