关于GDI / GDI +协调的兼容性?

问题描述 投票:16回答:4

我有一个问题,同时与两个GDI和GDI +绘图互换。页面转换,特别是扩大规模似乎有点过了两者之间。其中GDI方面的性能的影响要大于SetViewportExtSetWindowExt等输出的比例?

该代码使用几乎完全GDI其绘图,但是在它的功能(半透明)需要少数情况下使用GDI +。它采用SetViewportExtSetWindowExtSetViewportOrg,使缩放和滚动。

当GDI +是需要我周围构建了一个HDC对象Gdiplus::Graphics并做图。我以为这使得图形上下文包装设备上下文和继电器其呈现给设备上下文。如果我提取GDI +图形上下文的变换矩阵,我看到它是单位矩阵,所以缩放做过的工作(在我猜的设备上下文)。

我设计了一个简单的测试,我绘制GDI和GDI +矩形的同一阵列,以确保所有的转变是在两种情况下是相同的。的代码片段如下:

CRect rect = ...;

// Draw the rectangle using GDI
CPen cpen(PS_DASH, 0, RGB(0,0,255));
pDC->SelectObject(&cpen);
pDC->Rectangle(rect);

{
    // Draw the rectangle using GDI+
    Gdiplus::Graphics graphics(pDC->m_hDC);

    Gdiplus::Pen pen(Gdiplus::Color(180,180,180));
    graphics.DrawRectangle(
        &pen,
        Gdiplus::Rect(rect.left, rect.top, rect.Width(), rect.Height()));
}

其结果是在这里:(蓝色虚线是通过绘制GDI和灰色是由GDI +绘制)

Result drawn by code

我可以清楚地看到,这两个坐标系是不同的。我预计一些舍入误差,但不能作为这里看到的缩放误差。此外,当我改变缩放因子,则GDI +跳跃根据变焦两个方向围绕±4像素。这也强调了屏幕截图作为GDI +矩形具有正对X轴和负上相比于GDI矩形Y轴偏移的偏移量。

  • 有谁知道这是怎么回事呢?
  • 我怎么会去调查/调试呢?这发生在窗口的肠子,所以我很遗憾无法调试。

作为参考,这是我的视/窗口组织/转的样子:

Window Ext: (134000, 80500)
Window Org: (0, 0)
Viewport Ext: (1452 872)
Viewport Org: (35 35)

Update:

我有固定的问题,但它不是漂亮。其基本做法是:

  1. 采取在屏幕空间中的两个坐标(原点和第二合适的点),并将其转化到使用GDI(DPtoLP功能)逻辑坐标。
  2. 重置GDI改造MM_TEXT
  3. 使用变换点以构建用于GDI +的变换矩阵,其代表相同的变换
  4. 最后使用这个矩阵来构建一个GDI +上下文中有正确的转换。

这是一个黑客位,但它的工作原理。我仍然不知道为什么会出现两者之间的差异,虽然。它至少表明一点,就可以有一个GDI +情境模拟GDI改造。

c++ windows gdi+ gdi
4个回答
5
投票

简短的回答:叫graphics.SetPageUnit(Gdiplus::UnitPixel)

我有同样的问题,因为https://stackoverflow.com/a/4894969/700027:打印时,对于GDI +的坐标(Gdiplus ::图形)不匹配,从GDI(HDC)的坐标。

graphics.GetPageUnit()返航UnitDisplayUnitDisplay的文档:

指定显示单元。例如,如果显示设备是一台监视器,那么单位是1个像素。

我错误地认为,对于一台打印机,UnitDisplay将使用打印机点。很多挣扎后,我终于发现,它实际上是用英寸的1/100,原因未知。如果我使用Gdiplus :: UnitPixel然后GDI +的坐标是一样的GDI坐标。


2
投票

我们有同样的问题。

(背景:GDI工作正常,只是一切,似乎是为我们的电子表格形式显示与需要被渲染文本的单元1000的要快得多但是我们需要GDI +显示JPG格式的。)

在屏幕上显示的东西时,GDI +缩放似乎是正确的。我们有一个使用的坐标变换,让应用中呈现使用打印机坐标,而是出现在屏幕上打印预览功能。一切,直到我们把它交给实际的打印机(或PDF作家)在缩放得到鼻塞工作的罚款。

一个男人,一周的工作(并获得由您与您的解决方案的提示)后,这是我们的理解:

有一个在GDI中的错误+,当你打电话:“图形(HDC)”(创建从GDI设备上下文Graphics对象)中,其中HDC是从例如打印机或打印机软件6000 X 4000像素的分辨率,然后GDI +忽略一个事实,即HDC正在与这个大分辨率,而不是将其应用于自己的约1000×800像素的分辨率。

因此,你的解决方法可能是正确的,最好的解决问题的方法。

我们的解决方案是类似的,但有一点不同,其理由是,我们实际上并不希望任何坐标转换:

        graphics.GetVisibleClipBounds(&rect);
        double deltaY = (double)GetPrinterH()/(double)rect.Height;
        double deltaX = (double)GetPrinterW()/(double)rect.Width;
        x1=x1/deltaX;
        x2=x2/deltaX;
        y1=y1/deltaY;
        y2=y2/deltaY;
        graphics.DrawImage(jpeg->image, x1,y1,x2-x1,y2-y1);

这些比例因子似乎非常接近“6”在许多打印机驱动程序。


0
投票

我发现问题解决方法打印时。请注意,图形对象在本例中不设置任何世界空间变换,使绘图页面空间直接完成。

在页面单位设置为英寸,然后将坐标英寸似乎解决绘图问题没有太多的额外工作。在不同的DPI显示器和打印机的DC测试(范围从72到4000。)

Gdiplus::Graphics graphics(..);
Gdiplus::RectF    rect(0.0f, 0.0f, 1.0f, 1.0f);
Gdiplus::REAL     dpiX = graphics.getDpiX();
Gdiplus::REAL     dpiY = graphics.getDpiY();

/* Logical coordinates to inches. In this example, the window extents are
   equal to the DC's DPI. You will have to convert to inches based on your
   specific configuration. */
rect.X      /= dpiX;
rect.Y      /= dpiY;
rect.Width  /= dpiX;
rect.Height /= dpiY;

graphics.SetPageUnit(Gdiplus::UnitInch);
graphics.FillRectangle(.., rect);

-1
投票

有一点要记住的是,大多数GDI通常在硬件上运行(即GDI函数映射到实现硅一些功能的显示驱动程序)GDI +应该得到硬件加速,但它仍然作为一个单独的软件渲染器。

尝试手动设置通过GDI +和GDI几个像素,看看他们是不同的。

也许你的显卡变换坐标的方式,从它发生在GDI方式偏离+

© www.soinside.com 2019 - 2024. All rights reserved.