Windows-GDI-在不修改绘图功能的情况下将屏幕DC缩放为打印机DC [英] Windows - GDI - Scaling a screen DC to a printer DC without modifying the draw functions

查看:128
本文介绍了Windows-GDI-在不修改绘图功能的情况下将屏幕DC缩放为打印机DC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个向用户显示文档的Windows应用程序.内容使用GDI功能绘制,所有内容均按预期显示在屏幕上.

I'm writing a Windows application showing a document to the user. The content is painted using the GDI functions, and all appears as expected on the screen.

现在我要打印此文档.我得到了打印机设备的上下文,并且所做的绘图与在屏幕上所做的完全相同.当然,打印的内容在打印页面的顶部显得很小.这种行为的原因对我来说很清楚,并在此处进行了充分说明:

Now I want to print this document. I get a printer device context, and I do the exact same drawing as I do on the screen. Of course the printed content appears tiny on the top of the printed page. The reason of this behavior is clear for me, and is fully explained here:

https://www.codeproject.com/Articles/764057 /GDI绘图和打印

因此,我需要在打印机DC上添加缩放的视口,并且在GDI中有几种功能可以实现此目的.但是,我对如何配置这些功能有些疑惑.我尝试了在互联网上找到的各种示例,但没有一个对我有用.

So I need to add a scaled viewport on my printer DC, and there are several functions to achieve that in the GDI. However I'm a little puzzled about HOW to configure these functions. I tried various examples found on the internet, but none of them worked for me.

我的屏幕分辨率为1920x1080像素,我正在尝试在A4纵向页面上打印.我测试了各种配置,发现最适合打印页面的近似值如下:

My screen resolution is 1920x1080 pixels, and I'm trying to print on an A4 portrait page. I tested various configurations, and I found that the best approximation to fit on my printed page is the following:

::SetMapMode(hDC, MM_ISOTROPIC);
::SetWindowExtEx(hDC, 1, 1, NULL);
::SetViewportExtEx(hDC, 5, 5, NULL);
::SetViewportOrgEx(hDC, -10200, 0, NULL);

由于屏幕和打印配置当然可以在其他PC上更改,因此我需要知道如何计算上述值,但是我找不到适合我的情况的公式.尤其是我不知道为什么我需要使用SetViewportOrgEx()函数缩放画布原点,没有人在我阅读的文档中提到这一点.

As the screen and print configurations may, of course, change on other PC, I need to know how the above values may be calculated, but I cannot find a formula that works in my case. Especially I don't know why I need to scale my canvas origin using the SetViewportOrgEx() function, nobody mentioned that on the documents I read.

考虑到以下几点,计算打印DC视口的正确方法是什么?

So what is the correct manner to calculate my print DC viewport, considering that:

  • 屏幕和打印机绘图将使用完全相同的绘画功能,我将永远不会编写不同的功能来在屏幕和打印机上打印
  • 屏幕和打印机设备可以完全由用户配置,但是打印结果应始终适合屏幕和打印机上的文档

还有一个额外的问题,最好是使用图元文件来完成这种工作?

And as an additional question, it would be better to use a metafile to do this kind of job?

推荐答案

为了将屏幕坐标映射到纸张坐标,我们需要纸张的宽度和长度.此信息在GetDeviceCaps(hdc, PHYSICALWIDTH)GetDeviceCaps(hdc, PHYSICALHEIGHT)中可用,其中hdc是打印机的设备上下文.我们已经在某个地方有了屏幕坐标.

In order to map the screen coordinates to paper coordinates, we need the width and length of the paper. This information is available in GetDeviceCaps(hdc, PHYSICALWIDTH) and GetDeviceCaps(hdc, PHYSICALHEIGHT), where hdc is printer's device context. We already have the screen coordinates somewhere.

打印机无法在纸张的边缘上打印.我们可以从PHYSICALOFFSETXPHYSICALOFFSETY获取该信息.

The printer cannot print on the edges of the paper. We can get that information from PHYSICALOFFSETX and PHYSICALOFFSETY.

下面的示例使用一个通用函数paint来完成所有绘制. print不做任何绘画,而是调用paint.

The example below uses uses a common function paint which does all the painting. print doesn't do any painting, it calls paint instead.

这假定rc.leftrc.right在屏幕坐标中为(0,0).

This assumes that rc.left and rc.right is (0,0) in screen coordinates.

void paint(HDC hdc, RECT rc)
{
    HBRUSH brush = GetSysColorBrush(COLOR_WINDOWTEXT);
    InflateRect(&rc, -10, -10);
    FrameRect(hdc, &rc, brush);
    DrawText(hdc, L"hello world", -1, &rc, 0);
}

void print(HWND hWnd, RECT rc)
{
    PRINTDLG pd = { sizeof(pd) };
    pd.hwndOwner = hWnd;
    pd.Flags = PD_RETURNDC;
    if(!PrintDlg(&pd))
        return;

    HDC hdc = pd.hDC;
    DOCINFO doc = { sizeof(doc) };
    StartDoc(hdc, &doc);
    StartPage(hdc);
    SetMapMode(hdc, MM_ISOTROPIC);
    SetWindowExtEx(hdc, rc.right, rc.bottom, NULL);
    SetViewportExtEx(hdc, 
      GetDeviceCaps(hdc, PHYSICALWIDTH), GetDeviceCaps(hdc, PHYSICALHEIGHT), NULL);
    SetViewportOrgEx(hdc,
      -GetDeviceCaps(hdc, PHYSICALOFFSETX), -GetDeviceCaps(hdc, PHYSICALOFFSETY), NULL);

    paint(hdc, rc);

    EndPage(hdc);
    EndDoc(hdc);
    DeleteObject(hdc);
}

测试:

case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    RECT rc;
    GetClientRect(hwnd, &rc);
    paint(hdc, rc);
    EndPaint(hwnd, &ps);
    break;
}

case WM_LBUTTONDOWN:
{
    RECT rc;
    GetClientRect(hwnd, &rc);
    print(hwnd, rc);
    break;
}

这篇关于Windows-GDI-在不修改绘图功能的情况下将屏幕DC缩放为打印机DC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆