CreateDC fails but get error code 0 on win10

  • Thread starter Thread starter yusen_chen
  • Start date Start date
Y

yusen_chen

Guest
Hello,
I'm having trouble with CreateDC that fails but GetLastError() returns ERROR_SUCCESS, which were happend on win10.

All printer didn't not work, but other apps can use printers to print something.

What can I do to recover when this happens ?

code sample:

m_pTestDC->CreateDC return failed.

typedef struct _PrinterInfo
{
CString csPrinterName;
PRINTER_INFO_2 * pInfo_2;
DEVMODE* pDevMode;
int nDmOrientation;
short nDmDuplex; //支持双面打印的打印机选择双面打印方式
short nInitDmDuplex; //打印机初始的打印方式
BOOL bPCLOptimization; //是否支持PCL优化
PRINTER_INFO_4* pInfo_4;
}PRINTERINFO;

BYTE * g_pAllPrinterInfo = NULL; //[打印设备信息]
CPrintMem<DWORD,PRINTERINFO,CString,LPCWSTR> g_lpPrinterInfo;


CDC * CTestPrinterDlg::GetPrinterDC(CString csPrinterName)
{
if (m_pTestDC != NULL)
{
m_pTestDC->DeleteDC();
delete m_pTestDC;
m_pTestDC = NULL;
}
if (csPrinterName.IsEmpty())
{
AfxMessageBox(L"PrinterName empty!");
return NULL;
}
PRINTERINFO* pPrinterInfo=g_lpPrinterInfo.Lookup((CString)csPrinterName);
if (!pPrinterInfo)
{
AfxMessageBox(L"PRINTINFO empty!");
return NULL;
}
if (!pPrinterInfo->pDevMode)
SetPrinterDevMode(pPrinterInfo);
SetLastError(0);
m_pTestDC = new CDC;
if (m_pTestDC)
{
if (!m_pTestDC->CreateDC(NULL, pPrinterInfo->csPrinterName, NULL, pPrinterInfo->pDevMode))
{
CString wsError;
wsError.Format(L"Error: [%d], %s, %s", GetLastError(), pPrinterInfo->pInfo_2->pDriverName, pPrinterInfo->pInfo_2->pPrinterName);
AfxMessageBox(wsError);

if (!m_pTestDC->CreateDC(NULL, pPrinterInfo->csPrinterName,
NULL, pPrinterInfo->pDevMode))
{
return NULL;
}
}
}
return m_pTestDC;
}

void CTestPrinterDlg::SetPrinterDevMode(PRINTERINFO *pPrinterInfo)
{
if (pPrinterInfo->pDevMode)
{
AfxMessageBox(L"pDevMode Have Value!");
return;
}
if (pPrinterInfo->pInfo_2 == NULL)
{
AfxMessageBox(L"SetPrinterDevMode pInfo_2 empty!");
return;
}
DEVMODE* pDevMode = NULL;
DEVMODE* pDvmUser = NULL;
//[如果没有默认打印机或打印默认值为NULL]
if (this->GetPrinterSettingEx(pPrinterInfo->pInfo_2->pDriverName, pPrinterInfo->csPrinterName, pDvmUser))
{
pDevMode = pDvmUser; //[置为系统用户设置值]
}
else
{
pDevMode = pPrinterInfo->pInfo_2->pDevMode; //[置为系统全局设置值]
}
if (pDevMode)
{
int info_size = sizeof(*pDevMode) + pDevMode->dmDriverExtra;
int info_size2222 = pDevMode->dmSize + pDevMode->dmDriverExtra;
pPrinterInfo->pDevMode = (DEVMODE*)new BYTE[info_size2222];
ZeroMemory(pPrinterInfo->pDevMode, sizeof(BYTE) * info_size2222);
memcpy(pPrinterInfo->pDevMode, pDevMode, sizeof(BYTE) * info_size2222);

CString wsaaaa;
wsaaaa.Format(L"SET %d-%d", info_size, info_size2222);
}
else
{
pPrinterInfo->pDevMode=NULL;
// AfxMessageBox(L"DevMode empty!");
}
//[加入列表]
if (pDvmUser) delete pDvmUser;
}


void OnBnClickedButton1()
{
CString strPrinterName = L"";
this->m_combox.GetLBText(this->m_combox.GetCurSel(),strPrinterName);

//[查找打印机信息]
HANDLE hPrinter;
PRINTERINFO* pPrinterInfo = g_lpPrinterInfo.Lookup((CString)strPrinterName);
if (pPrinterInfo == NULL) return;
if (pPrinterInfo && pPrinterInfo->pInfo_2 == NULL)
{
GetPrinterInfo2Data(this->GetSafeHwnd(), (CString)strPrinterName, pPrinterInfo);
}

CDC* pPTDC = this->GetPrinterDC(strPrinterName);

//[根据打印机信息显示打印机driver属性对话框]
LPWSTR strPrnName = pPrinterInfo->csPrinterName.GetBuffer(pPrinterInfo->csPrinterName.GetLength());
int nOldOrientation = 0;
short nOldDmDuplex = 0;
int nOldCopies = 1;
if (pPrinterInfo->pDevMode)
{
//[从打印对框获得是否自动分页(Collate)]
pPrinterInfo->pDevMode->dmCollate = DMCOLLATE_FALSE;
// pPrinterInfo->pDevMode->dmPaperSize = m_pLyti->GetPaperSize();
//nOldDmDuplex = pPrinterInfo->pDevMode->dmDuplex;
//pPrinterInfo->pDevMode->dmDuplex = pPrinterInfo->nDmDuplex;

//nOldCopies = pPrinterInfo->pDevMode->dmCopies;
pPrinterInfo->pDevMode->dmCopies = (short)2;
}

if (OpenPrinter(strPrnName, &hPrinter, NULL))
{ //[获取打印机句柄]
//[获取DEVMODE所需Buffer大小]
long lnSize = DocumentProperties(this->m_hWnd, hPrinter, strPrnName, NULL, NULL, 0);
if (lnSize <= 0)
{
ClosePrinter(hPrinter);//[关闭打印机]
pPrinterInfo->csPrinterName.ReleaseBuffer(-1);
return;
}
DEVMODE * devModeOutput = (DEVMODE *) new BYTE[lnSize];
if (devModeOutput == NULL)
{
ClosePrinter(hPrinter);//[关闭打印机]
pPrinterInfo->csPrinterName.ReleaseBuffer(-1);
return;
}
ZeroMemory(devModeOutput, sizeof(BYTE) * lnSize);
devModeOutput->dmSize = (unsigned short)lnSize;

CString aaa;
aaa.Format(L"BUTTON=%d", lnSize);
AfxMessageBox(aaa);

//[显示打印机driver属性对话框]
//If the fMode parameter is zero, the return value is the size of the buffer
//required to contain the printer driver initialization data
//If the function displays the property sheet,
//the return value is either IDOK or IDCANCEL, depending on which button the user selects.
int nPaperSize = 0;
if (pPrinterInfo->pDevMode)
nPaperSize = pPrinterInfo->pDevMode->dmPaperSize;
//[弹出属性对话框]
lnSize = DocumentProperties(this->m_hWnd, hPrinter,
strPrnName,
devModeOutput,
pPrinterInfo->pDevMode,
DM_OUT_BUFFER | DM_IN_PROMPT | DM_IN_BUFFER);


//[如果size小于0,说明有错误(获取错误码,并输出错误信息)]
if (lnSize < 0) { _gPTAfxFormatMessage(); }

delete []devModeOutput;
ClosePrinter(hPrinter);//[关闭打印机]
}
pPrinterInfo->csPrinterName.ReleaseBuffer(-1);
}

void GetPrinterInfo2Data(HWND hwnd, CString wsPrinterName, PRINTERINFO *pPrinterInfo)
{
HANDLE printerHandle = NULL; //打印机设备句柄
//检测打开打印机设备是否成功
LPWSTR strPrnName = wsPrinterName.GetBuffer(wsPrinterName.GetLength());

if (OpenPrinter(strPrnName, &printerHandle, NULL))
{
DWORD nByteNeeded = 0;
DWORD nReturned = 0;
DWORD nByteUsed = 0;

//通过调用GetPrinter()函数得到作业数量
PRINTER_INFO_2* pInfo_2 = NULL;
BOOL bRet = GetPrinter(printerHandle, 2, NULL, 0, &nByteNeeded);
if (!bRet && nByteNeeded > 0) //If cbBuf is smaller than this value, GetPrinter fails, and the value represents the required buffer size
{
pInfo_2 = (PRINTER_INFO_2*)malloc(nByteNeeded);
if (pInfo_2)
{
memset(pInfo_2, 0, sizeof(pInfo_2));
bRet = GetPrinter(printerHandle, 2, (LPBYTE)pInfo_2, nByteNeeded, &nByteUsed);
if (bRet)
{
pPrinterInfo->pInfo_2 = pInfo_2;
}
else
{
free(pInfo_2);
CString wsError;
wsError.Format(L"GetPrinter Error: [%d], %s", GetLastError(), wsPrinterName);
AfxMessageBox(wsError);
}
}
else
{
//malloc failed, null
CString wsError;
wsError.Format(L"GetPrinter malloc Error: [%d], %s", GetLastError(), wsPrinterName);
AfxMessageBox(wsError);
}
}
else
{
CString wsError;
wsError.Format(L"GetPrinterSize Error: [%d], %s", GetLastError(), wsPrinterName);
AfxMessageBox(wsError);
}
//关闭打印机设备
ClosePrinter(printerHandle);
}
else
{
CString wsError;
wsError.Format(L"OpenPrinter Error: [%d], %s", GetLastError(), wsPrinterName);
AfxMessageBox(wsError);
}
wsPrinterName.ReleaseBuffer();
}

BOOL EnumPrinterInfo()
{
///////////////////////////////////////
//
// [释放所有旧数据]
//
///////////////////////////////////////
ReleaseAllPrinterInfo();


///////////////////////////////////////
//
// [遍历所有的打印机]
//
///////////////////////////////////////
DWORD cbNeeded = 0, dwPrinters = 0;
// Allocate enough buffer
EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL,
4, NULL, 0, &cbNeeded, &dwPrinters);

if (g_pAllPrinterInfo)
{
delete []g_pAllPrinterInfo;
}
g_pAllPrinterInfo = new BYTE[cbNeeded];

//[Get all printer infomation]
BOOL bResult = EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL,
4, g_pAllPrinterInfo, cbNeeded, &cbNeeded, &dwPrinters);
if (!bResult)
{
AfxMessageBox(L"EnumPrinters GetAll Failed!");
return FALSE;
}
if (dwPrinters <= 0)
{
AfxMessageBox(L"EnumPrinters dwPrinters <= 0 Failed!");
return FALSE;
}

///////////////////////////////////////
//
// [解析每一个打印机的设置]
//
///////////////////////////////////////  
for (DWORD dw = 0; dw < dwPrinters; dw++)
{
//[新建一个PrinterInfo]
PRINTERINFO* pPrinterInfo = new PRINTERINFO;
//[所有打印机信息]
PRINTER_INFO_4* allPter = (PRINTER_INFO_4*)g_pAllPrinterInfo;
PRINTER_INFO_4* prt = &allPter[dw];
if (allPter && prt)
{
//====[得到PrinterName并作为索引值]======//
pPrinterInfo->csPrinterName = prt->pPrinterName;

pPrinterInfo->pInfo_2 = NULL;
pPrinterInfo->pDevMode = NULL;
pPrinterInfo->nDmOrientation = 0;
pPrinterInfo->nDmDuplex = 0;
pPrinterInfo->nInitDmDuplex = 0;
pPrinterInfo->bPCLOptimization = FALSE;
pPrinterInfo->pInfo_4 = &allPter[dw];

if (!pPrinterInfo->csPrinterName.IsEmpty())
g_lpPrinterInfo.Add(pPrinterInfo, (CString)pPrinterInfo->csPrinterName);
}
}
return bResult;
}

void ReleaseAllPrinterInfo()
{
DWORD dwCount = g_lpPrinterInfo.GetCount();
for (DWORD dw = 0; dw < dwCount; dw++)
{
PRINTERINFO * pPrinterInfo = g_lpPrinterInfo.GetAt(dw);
if (pPrinterInfo)
{
if (pPrinterInfo->pInfo_2)
{
delete []pPrinterInfo->pInfo_2;
}
if (pPrinterInfo->pDevMode)
{
delete []pPrinterInfo->pDevMode;
}
}
}
g_lpPrinterInfo.ReleaseAll();//[释放所有PRINTERINFO ]
}

Continue reading...
 
Back
Top