【问题标题】:DeviceCapabilities of a network printer网络打印机的 DeviceCapabilities
【发布时间】:2016-08-19 18:32:08
【问题描述】:

我正在尝试使用DeviceCapabilities 获取网络打印机支持的页面大小列表,并且与sPort 参数完全混淆。

DWORD nPapersCount = ::DeviceCapabilities(sPrinter, sPort, DC_PAPERS, nullptr, nullptr);

谁能建议我,我应该在 sPort 中为网络打印机提供什么以及如何可靠地获取该端口?

作为实验,我尝试了格式为“\\Share”的 PC 名称,其端口为“\\Share\LPT1”,只是“LPT1”,但没有运气。

另外,我发现EnumPorts函数,所以我可以获取远程服务器上的打印机端口列表,但我不知道如何处理服务器上多台打印机的端口列表。

typedef struct _PORT_INFO_2 {
  LPTSTR pPortName;
  LPTSTR pMonitorName;
  LPTSTR pDescription;
  DWORD  fPortType;
  DWORD  Reserved;
} PORT_INFO_2, *PPORT_INFO_2;

【问题讨论】:

    标签: c++ winapi networking printing gdi+


    【解决方案1】:

    您无法猜测端口名,特别是在网络打印机的情况下。使用PrintDlg 从当前选定的打印机获取信息(这可以在不显示打印对话框的情况下完成)。

    端口名可通过PRINTDLG 结构的hDevNames 成员获得。

    DEVNAMES structure:

    typedef struct tagDEVNAMES {
      WORD wDriverOffset;
      WORD wDeviceOffset;
      WORD wOutputOffset; //<= port name
      WORD wDefault;
    } DEVNAMES, *LPDEVNAMES;
    

    Unicode 示例:

    PRINTDLG pdlg = { sizeof PRINTDLG };
    pdlg.Flags = PD_RETURNDEFAULT;
    PrintDlg(&pdlg);
    
    LPDEVNAMES lpDev = (LPDEVNAMES)GlobalLock(pdlg.hDevNames);
    std::wstring device = (LPCTSTR)lpDev + lpDev->wDeviceOffset;
    std::wstring port = (LPCTSTR)lpDev + lpDev->wOutputOffset;
    ::GlobalUnlock(pdlg.hDevNames);
    
    //clean up after PrintDlg, as pointed out by @RemyLebeau
    GlobalFree(pdlg.hDevMode);
    GlobalFree(pdlg.hDevNames);
    
    int nPapersCount;
    nPapersCount = ::DeviceCapabilities(device.c_str(), port.c_str(), DC_PAPERS, NULL, NULL);
    if (nPapersCount > 0)
    {
        WORD* sizeBuf = new WORD[nPapersCount];
        DeviceCapabilities(device.c_str(), port.c_str(), DC_PAPERS, (LPTSTR)sizeBuf, NULL);
        for (int i = 0; i < nPapersCount; i++)
            std::wcout << sizeBuf[i] << "\n";
        delete[] sizeBuf;
    }
    

    【讨论】:

    • 不要忘记在使用完 PRINTDLG 结构后释放 hDevModehDevNameshDC 句柄。为此使用GlobalFree()DeleteDC()。不过,您确定需要PD_RETURNDC 吗?您没有使用 hDC 做任何事情。
    • @RemyLebeau 没有分配,所以不需要GlobalFree。也没有DC。 PD_RETURNDC 是不必要的,我删除了它。
    • PRINTDLG 文档明确指出,如果 hDevModehDevNames 在输入时为 NULL,则分配它们。它没有说明PD_RETURNDEFAULT 是否会改变这种行为。它只是说它们被设置为系统默认打印机的句柄。他们被分配了吗?还是它们是静态的并归操作系统所有?该文档没有说一种或另一种方式。但大多数PD_RETURNDEFAULT 示例我可以在它们上找到调用GlobalFree()
    • @RemyLebeau 你是对的。我必须打电话给GlobalFree,否则会出现内存泄漏。文档不是那么清楚。
    【解决方案2】:

    使用 PrintDlg 有点笨拙,缺点是它只允许您查询默认打印机 (AFAIK)。更好的选择是使用 GetPrinter,请求的输出级别为 5:

    HANDLE h = NULL;
    OpenPrinter(printerName, &h, NULL);  // printerName is a LPWSTR
    if (!h) 
        return;
    DWORD cbBuf=0;
    GetPrinter(h, 5, NULL, 0, &cbBuf);
        // First call to GetPrinter determines an output buffer size
    BYTE *buf = new BYTE[cbBuf];
    if (!GetPrinter(h, 5, buf, cbBuf, &cbBuf))
        { ClosePrinter(h);  return; }
    PRINTER_INFO_5 *ppi = (PRINTER_INFO_5*) buf;
    LPWSTR port = ppi->pPortName;
    ClosePrinter(h);
    

    【讨论】:

      猜你喜欢
      • 2017-04-21
      • 1970-01-01
      • 1970-01-01
      • 2012-05-28
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多