首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么DeviceCapabilities()会为DC_BINS返回4294967295?

为什么DeviceCapabilities()会为DC_BINS返回4294967295?
EN

Stack Overflow用户
提问于 2021-11-18 00:52:19
回答 1查看 100关注 0票数 0

我正在从WIN32调用PrintDlgEx()中获取选定的打印机托盘。这似乎在大多数情况下都是成功的,但是最近我在我的机器上增加了一台新的打印机( DYMO LabelWriter 450),它导致我的简单软件失败了。

经过调查,对DeviceCapabilities()DC_BINS调用返回4294967295,而我测试过的所有其他打印机都返回个位数的bin计数。

我的第一个倾向是当bin计数大于给定的阈值时省略bin名称(例如.20?)但我不喜欢这个解决方案。

是否知道打印机将为此返回最大UNSIGNED INT值的原因?这只是写得不好的驱动程序,还是有其他含义?或者我完全误解了预期的价值。

如果我必须写一个任意的上限,我会,但我想更好地理解为什么这种情况存在。显然,这台打印机没有数十亿种不同的打印机托盘。

这是MRE:

代码语言:javascript
复制
    HINSTANCE hinst = GetModuleHandle(NULL);
    HRESULT hResult;
    PRINTDLGEX pdx = {0};
    LPPRINTPAGERANGE pPageRanges = NULL;
    HWND hWndOwner = GetForegroundWindow();

    if(!hWndOwner){
        hWndOwner = GetDesktopWindow();
    }

    // Allocate an array of PRINTPAGERANGE structures.
    pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
    if(!pPageRanges){
        return wprintf(L"{\"error\": \"%s\"}", GetLastError()); // "Your computer does not have enough memory to complete this operation:"
    }

    //  Initialize the PRINTDLGEX structure.
    pdx.lStructSize = sizeof(PRINTDLGEX);
    pdx.hwndOwner = hWndOwner;
    pdx.hDevMode = NULL;
    pdx.hDevNames = NULL;
    pdx.hDC = NULL;
    pdx.Flags = PD_RETURNDC | PD_COLLATE;
    pdx.Flags2 = 0;
    pdx.ExclusionFlags = 0;
    pdx.nPageRanges = 0;
    pdx.nMaxPageRanges = 10;
    pdx.lpPageRanges = pPageRanges;
    pdx.nMinPage = 1;
    pdx.nMaxPage = 1000;
    pdx.nCopies = 1;
    pdx.hInstance = 0;
    pdx.lpPrintTemplateName = NULL;
    pdx.lpCallback = NULL;
    pdx.nPropertyPages = 0;
    pdx.lphPropertyPages = NULL;
    pdx.nStartPage = START_PAGE_GENERAL;
    pdx.dwResultAction = 0;

    //  Invoke the Print property sheet.
    hResult = PrintDlgEx(&pdx);

    DEVMODE * myDevMode     = (DEVMODE *)GlobalLock(pdx.hDevMode);
    DWORD binCount = DeviceCapabilities((CHAR*)myDevMode->dmDeviceName, nullptr, DC_BINS, nullptr, nullptr);
    DWORD binNameCount = DeviceCapabilities((CHAR*)myDevMode->dmDeviceName, nullptr, DC_BINNAMES, nullptr, nullptr);
    wprintf(L"\"binCount\":\"%lu\",", binCount);
    wprintf(L"\"binNameCount\":\"%lu\",", binNameCount);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-18 02:04:54

DeviceCapabilities()返回一个签名的int,而不是一个未签名的DWORD

无符号值4294967295是十六进制0xFFFFFFFF,它是与有符号-1相同的数值。

根据DeviceCapabilities()文档:

返回值

如果函数成功,则返回值取决于fwCapability参数的设置。返回值为零通常表示,当函数成功完成时,会出现某种类型的故障,例如不支持的功能。有关更多细节,请参见对fwCapability值的描述。

如果函数返回-1,这可能意味着该功能不受支持,或者出现了通用函数故障。

您没有考虑DeviceCapabilities()失败的可能性(也没有考虑PrintDlgEx()失败的可能性)。

试试这个:

代码语言:javascript
复制
HWND hWndOwner = GetForegroundWindow();
if (!hWndOwner){
    hWndOwner = GetDesktopWindow();
}

// Allocate an array of PRINTPAGERANGE structures.
LPPRINTPAGERANGE pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
if (!pPageRanges){
    // NOTE: GetLastError() returns DWORD, not TCHAR*! So, if you
    // want to translate the error code in a human-readable string,
    // use FormatMessage() instead...
    return wprintf(L"{\"error\": %lu}", GetLastError());
}

//  Initialize the PRINTDLGEX structure.
PRINTDLGEX pdx = {0};
pdx.lStructSize = sizeof(PRINTDLGEX);
pdx.hwndOwner = hWndOwner;
pdx.Flags = PD_RETURNDC | PD_COLLATE;
pdx.nMaxPageRanges = 10;
pdx.lpPageRanges = pPageRanges;
pdx.nMinPage = 1;
pdx.nMaxPage = 1000;
pdx.nCopies = 1;
pdx.nStartPage = START_PAGE_GENERAL;

HRESULT hResult = PrintDlgEx(&pdx);
if (hResult != S_OK)
{
    GlobalFree(reinterpret_cast<HGLOBAL>(pPageRanges));
    return wprintf(L"{\"error\": %d}", hResult);
}

if (pdx.dwResultAction == PD_RESULT_CANCEL)
{
    GlobalFree(reinterpret_cast<HGLOBAL>(pPageRanges));
    return wprintf(L"{\"error\": \"cancelled\"}");
}

DEVMODE *myDevMode = (DEVMODE*) GlobalLock(pdx.hDevMode);

int binCount = DeviceCapabilities(reinterpret_cast<TCHAR*>(myDevMode->dmDeviceName), nullptr, DC_BINS, nullptr, nullptr);
wprintf(L"\"binCount\":%d,", binCount);

int binNameCount = DeviceCapabilities(reinterpret_cast<TCHAR*>(myDevMode->dmDeviceName), 
nullptr, DC_BINNAMES, nullptr, nullptr);
wprintf(L"\"binNameCount\":%d,", binNameCount);

if (binCount == -1)
{
    ...
}

if (binNameCount == -1)
{
    ...
}

...

GlobalUnlock(pdx.hDevMode);
GlobalFree(reinterpret_cast<HGLOBAL>(pPageRanges));

return ...;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70013313

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档