【问题标题】:GDI+ does not follow the LAYOUT_RTL of the used HDCGDI+ 不遵循所用 HDC 的 LAYOUT_RTL
【发布时间】:2019-12-04 22:45:00
【问题描述】:

我们使用旧 GDI 绘制的所有项目都使用 Window 的底层布局方向。窗口是使用 WS_EX_RTLLAYOUT 创建的。在希伯来语系统上运行时,Windows 完美地将填充矩形从 LTR 系统的左侧移动到窗口的右侧。 一旦我们在同一个 HDC 上使用 GDI+,什么都不会发生。全部保持 LTR。当然,我们可以开始自己计算矩形应该出现在屏幕上的什么位置,但是,这工作了一半。然后我们绘制的区域不是无效的,因此绘制被剪裁了。

非常感谢有关此问题的任何建议。 贾斯珀·德·凯泽尔

【问题讨论】:

    标签: gdi+ gdi win32gui


    【解决方案1】:

    布局是窗口的属性,而不是图形层。检查布局并做正确的事情是程序的责任。

    您在 GDI 中看到的是,为了帮助程序,Windows 将 DC 的默认坐标映射反转为从右到左的窗口,因此坐标会发生变化。

    GDI+ 必须覆盖它或进行自己的坐标映射。这并不奇怪,因为 GDI+ 可以使用浮点坐标。

    【讨论】:

      【解决方案2】:

      我通过让 GDI+ 绘制到内存设备上下文中解决了这个问题,然后我将它粘贴到屏幕上。对于 blitting,我使用标准的 GDI 函数,这给了我从右到左的权利。

      作为一个例子,我在这里提交了用于创建渐变填充区域的代码。代码现在在 LTR 和 RTL 环境中运行,这意味着我们没有两个代码库来区分方向。

      
      long srvDrawGradientFilledRect(HDC hdc,LPRECT lpFillingRect,
                                     unsigned long startcolor, unsigned long endcolor, UINT uFlags)
      {
          BYTE red_end, red_start;
          BYTE green_end, green_start;
          BYTE blue_end, blue_start;
          RECT FillingRect = *lpFillingRect;
          int xSize;
          int ySize;
          int xPos;
          int yPos;
      
          xSize = (FillingRect.right - FillingRect.left);
          ySize = (FillingRect.bottom - FillingRect.top);
          xPos = FillingRect.left;
          yPos = FillingRect.top;
          // Create compatible device context.
          HDC hdcMem = CreateCompatibleDC(hdc);
          // Create compatible bitmap.
          HBITMAP hbmMem = CreateCompatibleBitmap(hdc, xSize, ySize);
          // Select bitmap into device context.  (Bitmap holds all changes drawn in its DC.)
          HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
          // endcolor in bytes
          blue_end = (BYTE)(endcolor >> 16);
          green_end = (BYTE)(endcolor >> 8);
          red_end = (BYTE)(0x000000FF & endcolor);
          // startcolor in bytes
          blue_start = (BYTE)(startcolor >> 16);
          green_start = (BYTE)(startcolor >> 8);
          red_start = (BYTE)(0x000000FF & startcolor);
      
          LinearGradientBrush linGrBrush(Point(0, 0),       // starting point of the gradient
                                         Point(0, ySize),    // ending point of the gradient
                                         Color(255, red_start, green_start, blue_start),       // White starting color
                                         Color(255, red_end, green_end, blue_end));   // End color
          Graphics graphics(hdcMem);
          graphics.SetCompositingMode(CompositingModeSourceCopy);
          graphics.FillRectangle(&linGrBrush,0,0,xSize,ySize);
          // a box is painted arround the gradient in the end color.
          if (uFlags & ODRW_GRADIENT_OUTLINE) {
              Pen pen(Color(255, red_end, green_end, blue_end), 1.0f);
              graphics.DrawRectangle(&pen, 0, 0, xSize - 1, ySize);
          }
          BitBlt(hdc, FillingRect.left, FillingRect.top, xSize, ySize, hdcMem, 0, 0, SRCCOPY);
          /* Cleanup*/
          SelectObject(hdcMem, hbmOld);
          DeleteObject(hbmMem);
          DeleteDC(hdcMem);
          return 1;
      }
      

      希望这有助于结合 GDI+ 解决 RTL 问题。

      如果有更好的方法来解决这个问题,请告诉我。

      碧玉

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-12
        • 2010-09-26
        • 2019-02-26
        • 2021-11-06
        • 2010-11-13
        • 2023-03-28
        • 2015-03-01
        • 2011-01-09
        相关资源
        最近更新 更多