Windows 如何从CPrintDialogEx(PrintDlgEx)获取正确的hDevMode值?
我正在显示CPrintDialogEx对话框以选择打印机并修改设置。我设置了hDevNames成员,以便选择默认打印机,但我将hDevMode设置为NULL。成功返回时,我从hDevMode中从返回的DEVMODE结构中提取一些值,例如纸张大小 我遇到了一个问题,因为hDevMode似乎是用我传入的默认打印机的值初始化的,而不是最终选择的打印机。如何从实际选择的打印机获取参数?Windows 如何从CPrintDialogEx(PrintDlgEx)获取正确的hDevMode值?,windows,winapi,mfc,Windows,Winapi,Mfc,我正在显示CPrintDialogEx对话框以选择打印机并修改设置。我设置了hDevNames成员,以便选择默认打印机,但我将hDevMode设置为NULL。成功返回时,我从hDevMode中从返回的DEVMODE结构中提取一些值,例如纸张大小 我遇到了一个问题,因为hDevMode似乎是用我传入的默认打印机的值初始化的,而不是最终选择的打印机。如何从实际选择的打印机获取参数? 根据要求,这里是代码的相关部分。为了节省空间,我删掉了一些。TOwnedHandle是我写的一个智能指针,用于固定内
根据要求,这里是代码的相关部分。为了节省空间,我删掉了一些。TOwnedHandle是我写的一个智能指针,用于固定内存句柄并自动锁定它
CPrintDialogEx dlg(PD_ALLPAGES | PD_NOCURRENTPAGE | PD_NOPAGENUMS | PD_NOSELECTION, this);
ASSERT(dlg.m_pdex.hDevMode == NULL);
ASSERT(dlg.m_pdex.hDevNames == NULL);
dlg.m_pdex.hDevNames = GlobalAlloc(GHND, sizeof(DEVNAMES) + iSizeName);
DEVNAMES * pDevNames = (DEVNAMES *) GlobalLock(dlg.m_pdex.hDevNames);
// ...
GlobalUnlock(dlg.m_pdex.hDevNames);
if ((dlg.DoModal() == S_OK) && (dlg.m_pdex.dwResultAction == PD_RESULT_PRINT))
{
TOwnedHandle<DEVMODE> pDevMode = dlg.m_pdex.hDevMode;
TRACE("Printer config = %dx%d %d\n", (int)pDevMode->dmPaperWidth, (int)pDevMode->dmPaperLength, (int)pDevMode->dmOrientation);
// ...
}
如果我找不到解决办法,我很想听到一个解决办法。费了好大劲,我想我已经明白了 当对话框最初出现时,hDevMode成员将被最初选择的打印机的默认值填充。如果在关闭对话框之前选择了其他打印机,则该DEVMODE结构将显示给新的打印机驱动程序;如果纸张大小对驱动程序没有意义,它可能会改变纸张大小,并且驱动程序不一致 这让我绊倒的原因是我在三台打印机之间切换:两台标签打印机 打印机具有非常不同的特性,激光打印机与美国信纸
- 激光打印机始终以正确的尺寸响应,但可能指示错误的纸张尺寸代码
- 第一台标签打印机将覆盖激光打印机提供的尺寸,但不会覆盖另一台标签打印机
- 第二台标签打印机将接受第一台标签打印机提供的大小,因为它能够使用该大小,即使它未加载和未配置。它通过返回11英寸的最大宽度和字母大小长度来修改激光打印机提供的大小
IPrintDialogCallback
,并通过重新加载新选定打印机的默认DEVMODE来响应SelectionChange
调用编辑:我尝试了这个,但它不起作用。CPrintDialogEx已经实现了一个IPrintDialogCallback接口,这使它变得简单。PrintDlgEx似乎有自己的内部句柄,用于跟踪当前DEVMODE结构,并且只使用PrintDlgEx结构中的句柄进行输入/输出。对话框启动时无法影响DEVMODE,当它返回时已经太晚了
第二种解决方案是完全忽略返回的结果,并使用打印机的默认纸张配置。对话框中打印机默认值的任何更改都将完全丢失,但对于我的应用程序来说,这是可以接受的
bool MyDialog::GetPaperSize(const TCHAR * pPrinterName, double & dPaperWidth, double & dPaperLength)
{
// you need to open the printer before you can get its properties
HANDLE hPrinter;
if (OpenPrinter((TCHAR *)pPrinterName, &hPrinter, NULL))
{
// determine how much space is needed for the DEVMODE structure by the printer driver
int iDevModeSize = DocumentProperties(m_hWnd, hPrinter, (TCHAR *)pPrinterName, NULL, NULL, 0);
ASSERT(iDevModeSize >= sizeof(DEVMODE);
// allocate a DEVMODE structure and initialize it to a clean state
std::vector<char> buffer(iDevModeSize, 0);
DEVMODE * pdm = (DEVMODE *) &buffer[0];
pdm->dmSpecVersion = DM_SPECVERSION;
DocumentProperties(m_hWnd, hPrinter, (TCHAR *)pPrinterName, pdm, NULL, DM_OUT_BUFFER);
ClosePrinter(hPrinter);
// convert paper size from tenths of a mm to inches
dPaperWidth = pdm->dmPaperWidth / 254.;
dPaperLength = pdm->dmPaperLength / 254.;
return true;
}
return false;
}
bool MyDialog::GetPaperSize(const TCHAR*ppInterName、double&dPaperWidth、double&dPaperLength)
{
//您需要先打开打印机,然后才能获取其属性
手柄式打印机;
if(OpenPrinter((TCHAR*)内部名称和hPrinter,NULL))
{
//确定打印机驱动程序为DEVMODE结构需要多少空间
int-iDevModeSize=DocumentProperties(m_-hWnd,hPrinter,(TCHAR*)内部名称,NULL,NULL,0);
断言(iDevModeSize>=sizeof(DEVMODE);
//分配DEVMODE结构并将其初始化为干净状态
std::向量缓冲区(iDevModeSize,0);
DEVMODE*pdm=(DEVMODE*)和缓冲区[0];
pdm->dmSpecVersion=DM_SPECVERSION;
文档属性(m_hWnd、hPrinter、(TCHAR*)pPrinterName、pdm、NULL、DM_OUT_BUFFER);
闭式打印机(hPrinter);
//将纸张大小从十分之一毫米转换为英寸
DPPaperWidth=pdm->dmPaperWidth/254。;
DPPaperLength=pdm->dmPaperLength/254。;
返回true;
}
返回false;
}
很难出错。张贴显示DoModal和GetDevMode的代码。很好的捕获…可能很难发现。
bool MyDialog::GetPaperSize(const TCHAR * pPrinterName, double & dPaperWidth, double & dPaperLength)
{
// you need to open the printer before you can get its properties
HANDLE hPrinter;
if (OpenPrinter((TCHAR *)pPrinterName, &hPrinter, NULL))
{
// determine how much space is needed for the DEVMODE structure by the printer driver
int iDevModeSize = DocumentProperties(m_hWnd, hPrinter, (TCHAR *)pPrinterName, NULL, NULL, 0);
ASSERT(iDevModeSize >= sizeof(DEVMODE);
// allocate a DEVMODE structure and initialize it to a clean state
std::vector<char> buffer(iDevModeSize, 0);
DEVMODE * pdm = (DEVMODE *) &buffer[0];
pdm->dmSpecVersion = DM_SPECVERSION;
DocumentProperties(m_hWnd, hPrinter, (TCHAR *)pPrinterName, pdm, NULL, DM_OUT_BUFFER);
ClosePrinter(hPrinter);
// convert paper size from tenths of a mm to inches
dPaperWidth = pdm->dmPaperWidth / 254.;
dPaperLength = pdm->dmPaperLength / 254.;
return true;
}
return false;
}