Delphi 使用DrawThemeBackground绘图时,如何从右向左(RTL)方向绘制图元零件?

Delphi 使用DrawThemeBackground绘图时,如何从右向左(RTL)方向绘制图元零件?,delphi,winapi,right-to-left,windows-themes,uxtheme,Delphi,Winapi,Right To Left,Windows Themes,Uxtheme,我试图从右向左绘制Explorer::Treeview类的ttglyphmclosed元素(比如BiDiMode将是bdleftoright)。我有一个问题,我不知道如何使我的屏幕外位图是透明的。位图的背景始终为白色 我正在使用以下代码镜像图像: procedure TForm5.FormPaint(Sender: TObject); var bm: TBitmap; ARect: TRect; Details: TThemedElementDetails; begin

我试图从右向左绘制
Explorer::Treeview
类的
ttglyphmclosed
元素(比如
BiDiMode
将是
bdleftoright
)。我有一个问题,我不知道如何使我的屏幕外位图是透明的。位图的背景始终为白色

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

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(从右到左)渲染?

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


我已经有一段时间没有做过这件事了,所以我记不清了。

使用
SetLayout
,正如特拉玛在他现在删除的答案中所示,在你画画之前切换画布的布局

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)。由于无法知道零件中图像的位置,因此无法更好地对齐它