zoukankan      html  css  js  c++  java
  • C++ 打印机设置

    我在网上已不断看到一些网友关于自定义纸张打印的问题,基本上还没有较完美的解决方案,我在这里提供一个WindowsNT/2000/XP下的解决办法,供广大同仁参考。Windows9x/Me下也有解决办法,有兴趣者可共同探讨。
      该方法的主要思想是在程序开始时添加自定义纸张并设为默认纸张,程序结束前删除该自定义纸张并恢复原来的默认纸张类型。这种方法的通用性是显而易见的,如果你正在用Document/View框架,那么你就不必为了自定义纸张而去挖空心思重载其中的一些函数了。
      以下是我的程序片断,请朋友们多提宝贵意见。如果我的代码能为您所用,那是我极大的荣幸。
      注:我在论坛中回复的帖子中个别GlobalAlloc和GlobalFree打错成了Alloc和Free,予以纠正并发表在此。


     

    #i nclude
    typedef TCHAR PAPERNAME[64]; //打印机纸张名称类型
    //检测系统是否为Windows NT/2000/XP
    BOOL CPrinter::IsWindowsNT()
    {
    OSVERSIONINFO vi;
    vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&vi);
    return (vi.dwPlatformId == VER_PLATFORM_WIN32_NT);
    }
    //获得默认打印机名称和默认的纸张
    BOOL GetDefaultPrinterAndPaper(LPTSTR szPrinterName, int nPrintNameBufferLen, LPTSTR szPaperName)
    {
    *szPrinterName = 0;
    *szPaperName = 0;
    CPrintDialog pd(FALSE);
    if (pd.GetDefaults())
    {
    if (pd.m_pd.hDC) DeleteDC(pd.m_pd.hDC);
    if (pd.m_pd.hDevMode)
    {
    LPDEVMODE pdm = (LPDEVMODE)GlobalLock(pd.m_pd.hDevMode);
    *(szPaperName + 63) = 0;
    _tcsncpy(szPaperName, (LPCTSTR)pdm->dmFormName, 63); //打印纸张名称
    GlobalUnlock(pd.m_pd.hDevMode);
    GlobalFree(pd.m_pd.hDevMode);
    }
    if (pd.m_pd.hDevNames)
    {
    LPDEVNAMES pdn = (LPDEVNAMES)GlobalLock(pd.m_pd.hDevNames);
    nPrintNameBufferLen--;
    *(szPrinterName + nPrintNameBufferLen) = 0;
    _tcsncpy(szPrinterName, (LPTSTR)pdn + pdn->wDeviceOffset, nPrintNameBufferLen); //打印机名称
    GlobalUnlock(pd.m_pd.hDevNames);
    GlobalFree(pd.m_pd.hDevNames);
    }
    }
    return (*szPrinterName && *szPaperName);
    }
    //增加规格自定义纸张
    //szPaperName: 自定义纸张名称
    //PaperSize: 纸张的大小,以0.1mm为单位
    //rcPrintableMargin: 打印机的最小可打印边界,以0.1mm为单位。
    // 可参见GetDeviceCaps函数说明中的PHYSICALOFFSETX及PHYSICALOFFSETY
    BOOL AddCustomPaper(LPCTSTR szPrinterName, PAPERNAME szPaperName, SIZE PaperSize, RECT rcPrintableMargin)
    {
    BOOL bOk = FALSE;
    if (IsWindowsNT()) //Windows NT4/2000/XP才支持
    {
    FORM_INFO_1 fi1;
    fi1.Flags = FORM_USER;
    fi1.pName = (LPTSTR)szPaperName;
    fi1.Size.cx = PaperSize.cx * 100;
    fi1.Size.cy = PaperSize.cy * 100;
    fi1.ImageableArea.left = rcPrintableMargin.left * 100;
    fi1.ImageableArea.top = rcPrintableMargin.top * 100;
    fi1.ImageableArea.right = fi1.Size.cx - rcPrintableMargin.right * 100;
    fi1.ImageableArea.bottom = fi1.Size.cy - rcPrintableMargin.bottom * 100;
    HANDLE hPrinter = GetPrinterHandle(szPrinterName);
    if (hPrinter)
    {
    bOk = (SetForm(hPrinter, (LPSTR)szPaperName, 1, (LPBYTE)&fi1) || //已存在该类型纸张则更改
    AddForm(hPrinter, 1, (LPBYTE)&fi1)); //否则添加此自定义纸张
    ClosePrinter(hPrinter);
    }
    }
    return bOk;
    }
    //删除自定义规格纸张
    BOOL DeleteCustomPaper(LPCTSTR szPrinterName, LPCTSTR szPaperName)
    {
    BOOL bOk = FALSE;
    if (IsWindowsNT()) //Windows NT4/2000/XP才支持
    {
    HANDLE hPrinter = GetPrinterHandle(szPrinterName);
    if (hPrinter)
    {
    bOk = DeleteForm(hPrinter, (LPSTR)szPaperName);
    ClosePrinter(hPrinter);
    }
    }
    return bOk;
    }
    //获取打印机句柄
    HANDLE GetPrinterHandle(LPCTSTR szPrinterName)
    {
    PRINTER_DEFAULTS pds;
    HANDLE hPrinter = NULL;
    ZeroMemory(&pds, sizeof(PRINTER_DEFAULTS));
    pds.DesiredAccess = PRINTER_ALL_ACCESS;
    OpenPrinter(szPrinterName, &hPrinter, &pds);
    return hPrinter;
    }
    //由纸张名称得到对应的DEVMODE中的那个dmPaperSize值,返回-1表示有错误
    short GetPaperSize(LPCTSTR szPrinterName, LPCTSTR szPortName, PAPERNAME szPaperName)
    {
    short nPaperSize = -1;
    //获得可用打印机纸张类型数目
    int nNeeded = DeviceCapabilities(szPrinterName, szPortName, DC_PAPERNAMES, NULL, NULL);
    if (nNeeded)
    {
    PAPERNAME *pszPaperNames = new PAPERNAME[nNeeded]; //分配纸张名称数组
    //获得可用打印机纸张名称数组
    if (DeviceCapabilities(szPrinterName, szPortName, DC_PAPERNAMES, (LPTSTR)pszPaperNames, NULL) != -1)
    {
    int i;
    //查找纸张类型szPaperName在数组中的索引
    for (i = 0; i < nNeeded && _tcscmp(pszPaperNames[i], szPaperName); i++);
    if (i < nNeeded)
    {
    //获得可用打印机纸张尺寸号数目(应该等于打印机纸张类型数目)
    nNeeded = DeviceCapabilities(szPrinterName, szPortName, DC_PAPERS, NULL, NULL);
    if (nNeeded)
    {
    LPWORD pPapers = new WORD[nNeeded]; //分配纸张尺寸号数组
    //获得可用打印机纸张尺寸号数组
    if (DeviceCapabilities(szPrinterName, szPortName, DC_PAPERS, (LPSTR)pPapers, NULL) != -1)
    nPaperSize = pPapers[i]; //获得纸张类型szPaperName对应的尺寸号
    delete []pPapers;
    }
    }
    }
    delete []pszPaperNames;
    }
    return nPaperSize;
    }
    //设置打印机的默认纸张和方向
    BOOL SetPaper(LPCTSTR szPrinterName, PAPERNAME szPaperName, short nOrientation)
    {
    BOOL bOk = FALSE;
    PRINTER_INFO_2 *ppi2 = GetInfo2(szPrinterName);
    if (ppi2)
    {
    short nPaperSize = GetPaperSize(szPrinterName, ppi2->pPortName, szPaperName);
    if (nPaperSize != -1)
    {
    ppi2->pDevMode->dmFields = DM_PAPERSIZE|DM_PAPERWIDTH|DM_PAPERLENGTH|DM_ORIENTATION;
    ppi2->pDevMode->dmPaperSize = nPaperSize;
    ppi2->pDevMode->dmPaperWidth = 0;
    ppi2->pDevMode->dmPaperLength = 0;
    ppi2->pDevMode->dmOrientation = nOrientation;
    bOk = SetInfo2(ppi2);
    }
    GlobalFree((HGLOBAL)ppi2);
    }
    return bOk;
    }
    //获取打印机详细信息,返回的指针用后必须以GlobalFree释放
    PRINTER_INFO_2 *GetInfo2(LPCTSTR szPrinterName)
    {
    HANDLE hPrinter = GetPrinterHandle(szPrinterName);
    PRINTER_INFO_2 *ppi2 = NULL;
    DWORD cbNeeded = 0;
    if (hPrinter)
    {
    GetPrinter(hPrinter, 2, 0, 0, &cbNeeded);
    if (cbNeeded)
    {
    ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, cbNeeded);
    if (ppi2)
    {
    if (!GetPrinter(hPrinter, 2, (LPBYTE)ppi2, cbNeeded, &cbNeeded))
    {
    GlobalFree((HGLOBAL)ppi2);
    ppi2 = NULL;
    }
    }
    }
    ClosePrinter(hPrinter);
    }
    return ppi2;
    }
    //打印机设置
    BOOL SetInfo2(PRINTER_INFO_2 *ppi2)
    {
    HANDLE hPrinter = GetPrinterHandle(ppi2->pPrinterName);
    BOOL bOk = FALSE;
    DWORD fMode;
    if (hPrinter)
    {
    fMode = DM_IN_BUFFER | DM_OUT_BUFFER;
    bOk = (DocumentProperties(NULL, hPrinter,
    ppi2->pPrinterName,
    ppi2->pDevMode,
    ppi2->pDevMode,
    fMode) == IDOK &&
    ::SetPrinter(hPrinter, 2, (LPBYTE)ppi2, 0));
    ClosePrinter(hPrinter);
    }
    return bOk;
    }

    TCHAR szPrinterName[32];
    PAPERNAME szPaperName, szOldPaperName;
    //在您的程序开始时,获取默认打印机名和纸张名
    GetDefaultPrinterAndPaper(szPrinterName, 32, szOldPaperName);
    _tcscpy(szPaperName, _T("我的自定义纸张"));
    //增加自定义纸张
    AddCustomPaper(szPrinterName, szPaperName, CSize(1480, 2000), CRect(70, 70, 70, 70));
    //并设自定义纸张为默认纸张
    SetPaper(szPrinterName, szPaperName, DMORIENT_PORTRAIT);

    //在您的程序结束前
    //删除自定义纸张
    DeleteCustomPaper(szPrinterName, szPaperName);
    //并恢复初始默认纸张
    SetPaper(szPrinterName, szOldPaperName);
    ---------------------
    作者:laowang2
    来源:CSDN
    原文:https://blog.csdn.net/wewaa/article/details/5992011
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    cocostudio 使用教程
    anrdroid AVD启动不起来的问题。Waiting for HOME ('android.process.acore') to be launched
    Android SDK无法更新的问题解决办法
    Code(容斥,好题)
    莫比乌斯反演(转)
    随笔--新建查询
    11427
    uva11722
    uva11021
    How many integers can you find(容斥+dfs容斥)
  • 原文地址:https://www.cnblogs.com/guozht/p/9883217.html
Copyright © 2011-2022 走看看