Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 如何从CPrintDialogEx(PrintDlgEx)获取正确的hDevMode值?_Windows_Winapi_Mfc - Fatal编程技术网

Windows 如何从CPrintDialogEx(PrintDlgEx)获取正确的hDevMode值?

Windows 如何从CPrintDialogEx(PrintDlgEx)获取正确的hDevMode值?,windows,winapi,mfc,Windows,Winapi,Mfc,我正在显示CPrintDialogEx对话框以选择打印机并修改设置。我设置了hDevNames成员,以便选择默认打印机,但我将hDevMode设置为NULL。成功返回时,我从hDevMode中从返回的DEVMODE结构中提取一些值,例如纸张大小 我遇到了一个问题,因为hDevMode似乎是用我传入的默认打印机的值初始化的,而不是最终选择的打印机。如何从实际选择的打印机获取参数? 根据要求,这里是代码的相关部分。为了节省空间,我删掉了一些。TOwnedHandle是我写的一个智能指针,用于固定内

我正在显示CPrintDialogEx对话框以选择打印机并修改设置。我设置了hDevNames成员,以便选择默认打印机,但我将hDevMode设置为NULL。成功返回时,我从hDevMode中从返回的DEVMODE结构中提取一些值,例如纸张大小

我遇到了一个问题,因为hDevMode似乎是用我传入的默认打印机的值初始化的,而不是最终选择的打印机。如何从实际选择的打印机获取参数?
根据要求,这里是代码的相关部分。为了节省空间,我删掉了一些。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;
}