15

I'm working in a custom control which mix two windows controls (listview and treeview). In some point, I need to draw the image which uses windows 7 (with themes enabled) to identify the parent nodes, I'm using the DrawThemeBackground function with the TVP_GLYPH part and the GLPS_CLOSED state (I tried with all the parts and states related to the TREEVIEW class without luck), but the result image always is the old (+) or (-).

This image show the issue

enter image description here

I want to draw the Arrow image (inside of black circle) instead of the (+) sign (inside of orange circle).

This is the sample code which I use to draw the image.

uses
  UxTheme;

procedure TForm40.Button1Click(Sender: TObject);
var
  iPartId : integer;
  iStateId: integer;
  hTheme  : THandle;
begin
  hTheme  := OpenThemeData(Handle, VSCLASS_TREEVIEW);

  iPartId := TVP_GLYPH;
  iStateId:= GLPS_CLOSED;          
  //iPartId := TVP_TREEITEM;
  //iStateId:= TREIS_NORMAL;
  if hTheme <> 0 then
    try
      
      //if (IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId)) then
      //    DrawThemeParentBackground(Handle, PaintBox1.Canvas.Handle, nil);
      
      DrawThemeBackground(hTheme, PaintBox1.Canvas.Handle, iPartId, iStateId, Rect(0, 0, 31, 31), nil);
    finally
      CloseThemeData(hTheme);
    end;
end;

I check a couple of tools like the application made by Andreas Rejbrand and this too, but I can't find the image which I want.

My question is : how I can obtain the arrow image?

UPDATE

Thanks to the answer posted for Stigma I found additional resources to the values of the parts and states of the Explorer::Treeview class.

RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • What is VSCLASS_TREEVIEW defined as? Some quick googling seems to indicate you need to use "explorer::treeview" instead of just "treeview". – Luke May 07 '11 at 03:53
  • the `VSCLASS_TREEVIEW` is defined in the UxTheme unit, and is just a constant for the `TREEVIEW` value. – RRUZ May 07 '11 at 04:12

2 Answers2

11

First of all, in the case of an ordinary ListView or TreeView, one can simply call SetWindowTheme on its handle to apply the proper sort of styling. The example from its MSDN page is as follows:

SetWindowTheme(hwndList, L"Explorer", NULL);

Since we are talking about a custom control, I am not so sure that applies here however. But since SetWindowTheme causes the WM_THEMECHANGED message to be sent to the proper window, it implies that you will just need to use the proper OpenThemeData call for the specific sub theme.

I think Luke's comment is correct. You probably just need to pass 'Explorer::Treeview' rather than the plain style. So, barring years of not having touched Delphi/Pascal:

hTheme  := OpenThemeData(Handle, 'Explorer::Treeview');
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Stigma
  • 1,686
  • 13
  • 27
2

You must set SetWindowTheme(Handle, 'explorer', nil); before painting to ensure that OpenThemeData will use new explorer style theme. Of course, window handle must be the same for both functions.

Linas
  • 5,485
  • 1
  • 25
  • 35
  • 1
    For what it's worth, I always call SetWindowTheme in an overriden CreateWnd so that the setting persists across window handle recreation. – David Heffernan May 07 '11 at 10:25