gpt4 book ai didi

c++ - 预期和实际打印结果不符

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:48:15 25 4
gpt4 key购买 nike

介绍和相关信息:

我试图通过尝试自己进行打印/打印预览来绕过我的应用程序中的另一个问题。

我正在尝试创建一个如下图所示的表格:

enter image description here

我正在使用 C++WinAPI , 在 WindowsXP SP3 上。我在 MS Visual Studio 2008 中工作。

我没有打印机,所以我通过打印到 来测试结果。 MS OneNote XPS file .

问题:

文本从数据库中获取,长度可变。由于它可能不适合原始单元格,因此我需要扩展单元格并适本地适合文本,如上图所示。

副作用:

我的测试代码的结果给出了关于字体大小的不一致结果。

在 OneNote 中,打印结果看起来不错:

enter image description here

但是,在 XPS 中它看起来不同:

enter image description here

我为解决此任务所做的努力:

我已经检查了 MSDN 文档以开始使用。到目前为止,我能够成功地在打印表面上绘制文本和线条。

我用过 DrawTextEx 执行断字(通过使用标志 DT_WORDBREAK)。

为了获得打印区域的大小,我使用了 GetDeviceCaps ,并获取打印机设备上下文我使用了 print property sheet .

问题:

重要说明:

如果认为以下问题过于宽泛,请发表评论,我将编辑我的帖子。我仍然相信我的错误很小,可以在一个帖子中解释。

1. 你能解释一下如何调整单元格以便整个字符串都适合吗?

  • 为什么我的字体绘制不一致?

  • 一如既往,这里是创建 SSCCE 的说明:

    1) 在 Visual Studio 中,创建默认的 Win32 项目。

    2) 在 stdafx.h文件 注释掉 #define WIN32_LEAN_AND_MEAN所以打印属性表可以正常工作。

    3) 在 stdafx.h#include <windows.h>下方添加以下内容线 :
    #include <windowsx.h>
    #include <commctrl.h>

    #pragma comment( linker, "/manifestdependency:\"type='win32' \
    name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
    processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
    language='*'\"")

    4)在窗口程序上方添加以下函数:
    // hWnd is the window that owns the property sheet.
    HRESULT DisplayPrintPropertySheet(HWND hWnd)
    {
    HRESULT hResult;
    PRINTDLGEX pdx = {0};
    LPPRINTPAGERANGE pPageRanges = NULL;

    // Allocate an array of PRINTPAGERANGE structures.
    pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));

    if (!pPageRanges)
    return E_OUTOFMEMORY;

    // Initialize the PRINTDLGEX structure.
    pdx.lStructSize = sizeof(PRINTDLGEX);
    pdx.hwndOwner = hWnd;
    pdx.hDevMode = NULL;
    pdx.hDevNames = NULL;
    pdx.hDC = NULL;
    pdx.Flags = PD_RETURNDC;
    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);

    if ( ( hResult == S_OK )
    && ( pdx.dwResultAction == PD_RESULT_PRINT ) )
    {

    // User clicked the Print button,
    // so use the DC and other information returned in the
    // PRINTDLGEX structure to print the document.

    /***************** IMPORTANT INFO : ********************/
    /****** I have added additional test code here *********/
    /**** please refer to the edited part of this post *****/
    /***************** at the very bottom !! ***************/

    DOCINFO diDocInfo = {0};
    diDocInfo.cbSize = sizeof( DOCINFO );
    diDocInfo.lpszDocName = L"Testing printing...";

    //******************** initialize testing font *****************//

    HFONT font, oldFont;

    long lfHeight = -MulDiv( 14, GetDeviceCaps( pdx.hDC, LOGPIXELSY), 72 );

    font = CreateFont( lfHeight,
    0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, 0, 0, 0,
    0, 0, L"Microsoft Sans Serif" );

    oldFont = SelectFont( pdx.hDC, font );

    SetBkMode( pdx.hDC, TRANSPARENT );

    SetTextColor( pdx.hDC, RGB( 255, 0, 0 ) );

    //******************** end of initialization ******************//

    if( StartDoc( pdx.hDC, &diDocInfo ) > 0 )
    {
    if( StartPage( pdx.hDC ) > 0 )
    {
    // get paper dimensions
    int pageWidth, pageHeight;

    pageWidth = GetDeviceCaps( pdx.hDC, HORZRES );
    pageHeight = GetDeviceCaps( pdx.hDC, VERTRES );

    /************ draw a testing grid ***************/

    // draw vertical lines of the grid
    for( int i = 0; i < pageWidth; i += pageWidth / 4 )
    {
    MoveToEx( pdx.hDC, i, 0, NULL );
    LineTo( pdx.hDC, i, pageHeight );
    }

    // draw horizontal lines of the grid
    for( int j = 0; j < pageHeight; j += pageWidth / 10 )
    {
    MoveToEx( pdx.hDC, 0, j, NULL );
    LineTo( pdx.hDC, pageWidth, j );
    }

    /************************************************/

    // test rectangle for drawing the text
    RECT r;
    r.left = 0;
    r.top = 0;
    r.right = 550;
    r.bottom = 100;

    // fill rectangle with light gray brush
    // so we can see if text is properly drawn

    FillRect( pdx.hDC, &r,
    (HBRUSH)GetStockObject(LTGRAY_BRUSH) );

    // draw text in test rectangle
    if( 0 == DrawTextEx( pdx.hDC,
    L"This is test string!",
    wcslen( L"This is test string!" ),
    &r,
    DT_CENTER | DT_WORDBREAK | DT_NOCLIP, NULL ) )
    // for now pop a message box saying something went wrong
    MessageBox( hWnd, L"DrawText failed!", L"Error", MB_OK );

    if( EndPage( pdx.hDC ) < 0 )
    // for now pop a message box saying something went wrong
    MessageBox( hWnd, L"EndDoc failed!", L"Error", MB_OK );
    }

    EndDoc( pdx.hDC );

    SelectFont( pdx.hDC, oldFont );
    DeleteFont( font );
    }
    }

    if (pdx.hDevMode != NULL)
    GlobalFree(pdx.hDevMode);

    if (pdx.hDevNames != NULL)
    GlobalFree(pdx.hDevNames);

    if (pdx.lpPageRanges != NULL)
    GlobalFree(pPageRanges);

    if (pdx.hDC != NULL)
    DeleteDC(pdx.hDC);

    return hResult;
    }

    5) 在 WM_COMMAND处理程序,修改 case IDM_ABOUT像这样 :
    case IDM_ABOUT:   // test our printing here
    {
    if( FAILED( DisplayPrintPropertySheet( hWnd ) ) )
    MessageBox( hWnd,
    L"Can't display print property sheet!",
    L"Error", MB_OK );
    }
    //DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    break;

    2014 年 6 月 8 日编辑:

    后挡 if ( ( hResult == S_OK ) && ( pdx.dwResultAction == PD_RESULT_PRINT ) )在提交的 SSCCE 中,为了测试目的,我添加了以下内容:
    int xDpi = GetDeviceCaps( pdx.hDC, LOGPIXELSX ),
    yDpi = GetDeviceCaps( pdx.hDC, LOGPIXELSY );

    int mapMode = GetMapMode( pdx.hDC );

    wchar_t displayDPI[50];
    swprintf_s( displayDPI, 50, L" xDPI = %s , yDPI = %s", xDpi, yDpi );
    MessageBox( hWnd, displayDPI, L"", MB_OK );

    switch( mapMode )
    {
    case MM_ANISOTROPIC:
    MessageBox( hWnd, L"MM_ANISOTROPIC", L"", MB_OK );
    break;
    case MM_HIENGLISH:
    MessageBox( hWnd, L"MM_HIENGLISH", L"", MB_OK );
    break;
    case MM_HIMETRIC:
    MessageBox( hWnd, L"MM_HIMETRIC", L"", MB_OK );
    break;
    case MM_ISOTROPIC:
    MessageBox( hWnd, L"MM_ISOTROPIC", L"", MB_OK );
    break;
    case MM_LOENGLISH:
    MessageBox( hWnd, L"MM_LOENGLISH", L"", MB_OK );
    break;
    case MM_LOMETRIC:
    MessageBox( hWnd, L"MM_LOMETRIC", L"", MB_OK );
    break;
    case MM_TEXT:
    MessageBox( hWnd, L"MM_TEXT", L"", MB_OK );
    break;
    case MM_TWIPS:
    MessageBox( hWnd, L"MM_TWIPS", L"", MB_OK );
    break;
    default:
    MessageBeep(0);
    break;
    }

    在这两种情况下,映射模式是相同的( MM_TEXT )但对于 XPS 我得到了 xDPI = 600 , yDPI = 600MessageBox而 OneNote 有 xDPI = 300 , yDPI = 300 .

    由此得出结论,成员 * Carey Gregory* 所做的评论是正确的 -> 具有相同特征的虚拟打印机将重现相同的结果。这也解释了为什么 OneNote 在我测试时正确打印到 XPS 中,以及为什么我的应用程序失败。为了解决这个问题,我需要找到 DPI 感知解决方案......

    2014 年 6 月 9 日编辑:

    使用 GDI+创建字体和绘制文本我能够获得一致的结果(DPI 不再是问题)。尽管如此,如果有人知道如何仅使用 GDI 获得相同的结果我还是会感兴趣的。

    我唯一剩下的就是绘制一个合适的网格,以便文本可以正确地放入单元格中。

    2014 年 6 月 10 日编辑:

    仔细阅读后 this MSDN link我能够更改字体创建代码以实现(在我看来)稳定的结果(字体的实际高度最终变小了,但我想我可以使用更大的数字):
     font = CreateFont( 
    // DPI aware, thanks to the below equation ( or so it seems... )
    lfHeight / ( GetDeviceCaps( pdx.hDC, LOGPIXELSY ) / 96 ),
    0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, 0, 0, 0, // remained the same
    0, 0, L"Microsoft Sans Serif" ); // remained the same

    为了安全起见,我会尽量坚持使用 GDI+但会在 GDI 时用测试结果更新这篇文章并且提到的等式用于以防其他人偶然发现相同的问题。我只是希望它能节省那些人的时间......

    最佳答案

    问题很简单。您正在调整字体大小(以像素为单位)以匹配您正在绘制的设备的 DPI,但您没有调整矩形的大小。由于您的映射模式是 MM_TEXT两者都以像素为单位,并且您的边界框实际上是设备尺寸的一半,分辨率是其两倍。

    解决方案是像缩放字体大小一样缩放矩形。在本例中,由于您已确定这些坐标在 300 DPI 时是正确的,因此我们将相对于该常数进行缩放。

    RECT r;
    r.left = 0 * GetDeviceCaps(pdx.hDC, LOGPIXELSX) / 300;
    r.top = 0 * GetDeviceCaps(pdx.hDC, LOGPIXELSY) / 300;
    r.right = 550 * GetDeviceCaps(pdx.hDC, LOGPIXELSX) / 300;
    r.bottom = 100 * GetDeviceCaps(pdx.hDC, LOGPIXELSX) / 300;

    关于您对 6 月 10 日的编辑,它之所以有效,只是因为您将字体变小了,以便它既适合全尺寸边框也适合半尺寸边框。我建议您使用字体大小的原始定义,这与大多数其他 Windows 应用程序一致。

    关于c++ - 预期和实际打印结果不符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24098435/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com