【问题标题】:How to draw the element part in right to left (RTL) direction when drawing with DrawThemeBackground?使用 DrawThemeBackground 绘图时如何在从右到左 (RTL) 方向绘制元素部分?
【发布时间】:2012-11-12 19:05:51
【问题描述】:

我正在尝试以从右到左的方向绘制Explorer::Treeview 类的ttGlyphClosed 元素(例如BiDiMode 将是bdLeftToRight 时)。我有一个问题,我不知道如何使我的屏幕外位图透明。位图的背景总是白色的。

我正在使用以下代码来镜像图像:

procedure TForm5.FormPaint(Sender: TObject);
var
  bm: TBitmap;
  ARect: TRect;
  Details: TThemedElementDetails;
begin    
  if ExplorerTreeviewhTheme = 0 then
    ExplorerTreeviewhTheme := OpenThemeData(0, 'Explorer::Treeview');

  ARect := Rect(20, 20, 40, 40);
  Details := ThemeServices.GetElementDetails(ttGlyphClosed);
  DrawThemeBackground(ExplorerTreeviewhTheme, Canvas.Handle,
    Details.Part, Details.State, ARect, nil); //Ok

  bm := TBitmap.Create;
  try
    bm.Width := 20;
    bm.Height := 20;

    ARect := Rect(00, 00, 20, 20);
    DrawThemeBackground(ExplorerTreeviewhTheme, bm.Canvas.Handle,
      Details.Part, Details.State, ARect, nil);

    // rendered result has white background
    Canvas.Draw(60, 10, bm);    
    // rendered result is mirrored but has also white background
    StretchBlt(Canvas.Handle, 100, 10, -20, 20, bm.Canvas.Handle, 0, 0, 20, 20, SRCCOPY);
  finally
    bm.Free;
  end;    
end;

问题是如何镜像DrawThemeBackground函数绘制的元素(用于RTL读取)或如何使用该函数进行RTL(从右到左)渲染?

【问题讨论】:

    标签: delphi winapi right-to-left windows-themes uxtheme


    【解决方案1】:

    使用SetLayout,正如 TLama 在他现在已删除的答案中显示的那样,在绘制之前切换画布的布局。

    function SetLayout(hdc: HDC; dwLayout: DWORD): DWORD; stdcall;
      external 'gdi32' name 'SetLayout';
    
    const
      LAYOUT_RTL = $00000001;
    
    procedure TForm1.FormPaint(Sender: TObject);
    var
      ExplorerTreeviewhTheme: HTHEME;
      Details: TThemedElementDetails;
      ARect: TRect;
      Size: TSize;
    begin
      ExplorerTreeviewhTheme := OpenThemeData(Handle, 'Explorer::Treeview');
      Details := ThemeServices.GetElementDetails(ttGlyphClosed);
      GetThemePartSize(ExplorerTreeviewhTheme, Canvas.Handle, Details.Part,
          Details.State, nil, TS_DRAW, Size);
    
      ARect := Rect(20, 30, 20 + Size.cx, 30 + Size.cy);
      
      // normal layout
      DrawThemeBackground(ExplorerTreeviewhTheme, Canvas.Handle,
                          Details.Part, Details.State, ARect, nil);
    
      // switched layout
      SetLayout(Canvas.Handle, LAYOUT_RTL);
      
      // calculate the rectangle for RTL as if it's in LTR
      OffsetRect(ARect, 0, Size.cy); // align to the bottom of the first image so that we can see
      ARect.Left := ClientWidth - ARect.Left - Size.cx;
      ARect.Right := ARect.Left + Size.cx;
    
      DrawThemeBackground(ExplorerTreeviewhTheme, Canvas.Handle,
                          Details.Part, Details.State, ARect, nil);
      
      // restore layout
      SetLayout(Canvas.Handle, 0);
      CloseThemeData(ExplorerTreeviewhTheme);
    end;
    

    输出:

    主题 api 正在绘制一个 6px 宽的三角形,零件尺寸为 16px(W7-aero)。由于您无法知道图像在零件中的位置,因此无法更好地对齐它。

    【讨论】:

      【解决方案2】:

      您在您的 stretchblt 调用中使用 srccopy,但我认为您可能需要寻找替代方案,包括可能使用掩码

      好久没做这个了,记不太清楚了

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-29
        • 2020-07-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多