我正在从WIN32调用PrintDlgEx()中获取选定的打印机托盘。这似乎在大多数情况下都是成功的,但是最近我在我的机器上增加了一台新的打印机( DYMO LabelWriter 450),它导致我的简单软件失败了。
经过调查,对DeviceCapabilities()的DC_BINS调用返回4294967295,而我测试过的所有其他打印机都返回个位数的bin计数。
我的第一个倾向是当bin计数大于给定的阈值时省略bin名称(例如.20?)但我不喜欢这个解决方案。
是否知道打印机将为此返回最大UNSIGNED INT值的原因?这只是写得不好的驱动程序,还是有其他含义?或者我完全误解了预期的价值。
如果我必须写一个任意的上限,我会,但我想更好地理解为什么这种情况存在。显然,这台打印机没有数十亿种不同的打印机托盘。
这是MRE:
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);发布于 2021-11-18 02:04:54
DeviceCapabilities()返回一个签名的int,而不是一个未签名的DWORD。
无符号值4294967295是十六进制0xFFFFFFFF,它是与有符号-1相同的数值。
根据DeviceCapabilities()文档:
返回值
如果函数成功,则返回值取决于fwCapability参数的设置。返回值为零通常表示,当函数成功完成时,会出现某种类型的故障,例如不支持的功能。有关更多细节,请参见对fwCapability值的描述。
如果函数返回-1,这可能意味着该功能不受支持,或者出现了通用函数故障。
您没有考虑DeviceCapabilities()失败的可能性(也没有考虑PrintDlgEx()失败的可能性)。
试试这个:
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 ...;https://stackoverflow.com/questions/70013313
复制相似问题