How to let TVirtualStringTree to display an icon in disabled state?

How to let TVirtualStringTree to display an icon in disabled state?

I need to display files in a directory to a TVirtualStringTree.

So, I use SHGetFileInfo to get files‘ icons.

But seems I can only get "normal" icons (Left side on following screen shot).

If so, can TVirtualStringTree draw icons as "disabled"?

Just like you disabled the a node. Please see a screen shot:

UPDATED

There is a similar thread in Soft Gems forum.

I can get the rect of the icon then draw the icon myself.

I‘m using TcxImageList and it can draw the "disabled" icon easily.

I firstly assigned a non-exist image index in GetImageIndex event

so I have a room to draw the icon. Then using following code to draw.

procedure TfrmMain.tvSharesAfterItemPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect);
var
  rImage: TRect;
  OffsetLeft: Integer;
begin
    rImage  := ItemRect; 

    with TVirtualStringTree(Sender) do begin
      if (toShowRoot in TreeOptions.PaintOptions) then
        OffsetLeft := Indent * (GetNodeLevel(Node) + 1)
      else
        OffsetLeft := Indent * GetNodeLevel(Node); 

      Inc(rImage.Left, Margin + OffsetLeft);
      Inc(rImage.Top, (NodeHeight[Node] - Images.Height) div 2);
      rImage.Right  := rImage.Left + Images.Width;
      rImage.Bottom := rImage.Top + Images.Height;
    end; 

    // draw the "normal" or "disabled" icon here
    imageList.Draw(TargetCanvas, rImage.left, rImage.Top, ...);
  end;
end;

No, TVirtualStringTree does not have an explicit DisabledIcon property or any thing similiar.

However, you can achieve your desired result by an appropriate handler for the GetImageIndex event.

In the event handler for this event, determine if the node is disabled or not,

and use this test as a discriminator for computing the image index.

In your imagelist, you will need to have normal versions of glyphs and disabled versions.

VirtualTree will not magically create the disabled versions for you,

however it is a trivial matter to clone a glyph and grey wash it.

Let me know if you need demo code, either for the GetImageIndex event handler, or for grey washing.

There‘s no direct way to draw disabled image state.

I would prefer to create the event for custom drawing of the images

(now I‘ve suggested this as a new featurefor virtual tree view, due to this lack).

Here is the example with interposed class for virtual string tree.

For custom drawing of grayscale images, it uses the code from this post.

Surely, it‘s not a solution for permanent use, you would have to keep the PaintImage method code

synchronized with the actual code since the method is completely overriden.

Parameter count of the OnCustomDrawImage event points to that parameters deserve to wrap to some structure,

but it‘s just a showcase how would it look like.

This new event is fired twice;

first time for image draw (the DrawOverlay is False) and

second time for overlay (the DrawOverlay parameter is True):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DateUtils, StdCtrls, VirtualTrees, ImgList, CommCtrl;

type
  TCustomDrawImageEvent = procedure(Sender: TBaseVirtualTree; Node: PVirtualNode;
    ImageList: TCustomImageList; ImageIndex: Integer; TargetCanvas: TCanvas;
    X, Y: Integer; Style: Cardinal; DrawEnabled: Boolean; DrawOverlay: Boolean;
    var CustomDraw: Boolean) of object;
  TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
  private
    FOnCustomDrawImage: TCustomDrawImageEvent;
  protected
    function DoCustomDrawImage(Node: PVirtualNode; ImageList: TCustomImageList;
      ImageIndex: Integer; TargetCanvas: TCanvas; X, Y: Integer; Style: Cardinal;
      DrawEnabled: Boolean; DrawOverlay: Boolean): Boolean; virtual;
    procedure PaintImage(var PaintInfo: TVTPaintInfo; ImageInfoIndex: TVTImageInfoIndex;
      DoOverlay: Boolean); override;
  published
    property OnCustomDrawImage: TCustomDrawImageEvent read FOnCustomDrawImage write FOnCustomDrawImage;
  end;

type
  TForm1 = class(TForm)
    VirtualStringTree1: TVirtualStringTree;
    ImageList1: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure VirtualStringTree1GetImageIndex(Sender: TBaseVirtualTree;
      Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
      var Ghosted: Boolean; var ImageIndex: Integer);
  private
    procedure VirtualTreeCustomDrawImage(Sender: TBaseVirtualTree; Node: PVirtualNode;
      ImageList: TCustomImageList; ImageIndex: Integer; TargetCanvas: TCanvas;
      X, Y: Integer; Style: Cardinal; DrawEnabled: Boolean; DrawOverlay: Boolean;
      var CustomDraw: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TVirtualStringTree }

type
  TCustomImageListCast = class(TCustomImageList);

function TVirtualStringTree.DoCustomDrawImage(Node: PVirtualNode;
  ImageList: TCustomImageList; ImageIndex: Integer; TargetCanvas: TCanvas; X,
  Y: Integer; Style: Cardinal; DrawEnabled: Boolean; DrawOverlay: Boolean): Boolean;
begin
  Result := False;
  if Assigned(FOnCustomDrawImage) then
    FOnCustomDrawImage(Self, Node, ImageList, ImageIndex, TargetCanvas, X, Y,
      Style, DrawEnabled, DrawOverlay, Result);
end;

procedure TVirtualStringTree.PaintImage(var PaintInfo: TVTPaintInfo;
  ImageInfoIndex: TVTImageInfoIndex; DoOverlay: Boolean);
var
  CutNode: Boolean;
  ExtraStyle: Cardinal;
  DrawEnabled: Boolean;
  PaintFocused: Boolean;
const
  Style: array[TImageType] of Cardinal = (0, ILD_MASK);
begin
  with PaintInfo do
  begin
    CutNode := (vsCutOrCopy in Node.States) and (tsCutPending in TreeStates);
    PaintFocused := Focused or (toGhostedIfUnfocused in TreeOptions.PaintOptions);
    if DoOverlay then
      GetImageIndex(PaintInfo, ikOverlay, iiOverlay, Images)
    else
      PaintInfo.ImageInfo[iiOverlay].Index := -1;
    DrawEnabled := not (vsDisabled in Node.States) and Enabled;
    with ImageInfo[ImageInfoIndex] do
    begin
      if (vsSelected in Node.States) and not (Ghosted or CutNode) then
      begin
        if PaintFocused or (toPopupMode in TreeOptions.PaintOptions) then
          Images.BlendColor := Colors.FocusedSelectionColor
        else
          Images.BlendColor := Colors.UnfocusedSelectionColor;
      end
      else
        Images.BlendColor := Color;
      if (ImageInfo[iiOverlay].Index > -1) and (ImageInfo[iiOverlay].Index < 15) then
        ExtraStyle := ILD_TRANSPARENT or ILD_OVERLAYMASK and
          IndexToOverlayMask(ImageInfo[iiOverlay].Index + 1)
      else
        ExtraStyle := ILD_TRANSPARENT;
      if (toUseBlendedImages in TreeOptions.PaintOptions) and PaintFocused
        and (Ghosted or ((vsSelected in Node.States) and
        not (toFullRowSelect in TreeOptions.SelectionOptions) and
        not (toGridExtensions in TreeOptions.MiscOptions)) or CutNode)
      then
        ExtraStyle := ExtraStyle or ILD_BLEND50;
      if (vsSelected in Node.States) and not Ghosted then
        Images.BlendColor := clDefault;

      // in this modified part of code, the new event OnCustomDrawImage
      // is fired once before the image is actually drawn and once when
      // the overlay is to be drawn; when you keep its CustomDraw param
      // in False value (what is, by default), the default drawing will
      // be done otherwise you need to take care of drawing by yourself

      // draw image default way when the CustomDraw parameter of the new
      // OnCustomDrawImage event remains False (what is, by default)
      if not DoCustomDrawImage(Node, Images, Index, Canvas, XPos, YPos,
        Style[Images.ImageType] or ExtraStyle, DrawEnabled, False)
      then
        TCustomImageListCast(Images).DoDraw(Index, Canvas, XPos, YPos,
          Style[Images.ImageType] or ExtraStyle, DrawEnabled);
      // draw overlay default way when the CustomDraw parameter of the new
      // OnCustomDrawImage event remains False (what is, by default)
      if PaintInfo.ImageInfo[iiOverlay].Index >= 15 then
      begin
        if not DoCustomDrawImage(Node, ImageInfo[iiOverlay].Images,
          ImageInfo[iiOverlay].Index, Canvas, XPos, YPos,
          Style[ImageInfo[iiOverlay].Images.ImageType] or ExtraStyle,
          DrawEnabled, True)
        then
          TCustomImageListCast(ImageInfo[iiOverlay].Images).DoDraw(
            ImageInfo[iiOverlay].Index, Canvas, XPos, YPos,
            Style[ImageInfo[iiOverlay].Images.ImageType] or ExtraStyle,
            DrawEnabled);
      end;
    end;
  end;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  VirtualStringTree1.OnCustomDrawImage := VirtualTreeCustomDrawImage;
end;

type
  TImageListDrawParams = record
    cbSize: DWORD;
    himl: HIMAGELIST;
    i: Integer;
    hdcDst: HDC;
    x: Integer;
    y: Integer;
    cx: Integer;
    cy: Integer;
    xBitmap: Integer;
    yBitmap: Integer;
    rgbBk: COLORREF;
    rgbFg: COLORREF;
    fStyle: UINT;
    dwRop: DWORD;
    fState: DWORD;
    Frame: DWORD;
    crEffect: COLORREF;
  end;

procedure DrawDisabledImage(DC: HDC; ImageList: TCustomImageList; Index, X,
  Y: Integer);
var
  Options: TImageListDrawParams;
begin
  FillChar(Options, SizeOf(Options), 0);
  Options.cbSize := SizeOf(Options);
  Options.himl := ImageList.Handle;
  Options.i := Index;
  Options.hdcDst := DC;
  Options.x := X;
  Options.y := Y;
  Options.fState := ILS_SATURATE;
  ImageList_DrawIndirect(@Options);
end;

procedure TForm1.VirtualStringTree1GetImageIndex(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: Boolean; var ImageIndex: Integer);
begin
  ImageIndex := 0;
end;

procedure TForm1.VirtualTreeCustomDrawImage(Sender: TBaseVirtualTree;
  Node: PVirtualNode; ImageList: TCustomImageList; ImageIndex: Integer;
  TargetCanvas: TCanvas; X, Y: Integer; Style: Cardinal; DrawEnabled: Boolean;
  DrawOverlay: Boolean; var CustomDraw: Boolean);
begin
  CustomDraw := True;
  if not DrawOverlay then
    DrawDisabledImage(TargetCanvas.Handle, ImageList, ImageIndex, X, Y);
end;

end.

And the result (I have to say it would be fine to blend it yet):

时间: 2024-11-06 16:19:00

How to let TVirtualStringTree to display an icon in disabled state?的相关文章

quick-cocos2d-x学习笔记【3】——display.newSprite创建精灵

游戏嘛,没图片没画面能叫游戏吗,所以我们还是先看用quick的方式怎么创建精灵. quick的api中对精灵的创建讲解得还是很详细,所以创建起来很简单. display.newSprite(filename, x, y, params) filename:精灵文件名 x:x位置坐标 y:y位置坐标 params:表参数(不常用) 我们创建的时候为了方便,可以添加x,y参数,这样就不用在后面再设置位置了.此外,对于精灵的文件名,我们在使用cocos2dx的时候,都知道有直接从文件读取,也有的是从缓

display.newSprite创建精灵

游戏嘛,没图片没画面能叫游戏吗,所以我们还是先看用Quick的方式怎么创建精灵. Quick的api中对精灵的创建讲解得还是很详细,所以创建起来很简单. display.newSprite(filename, x, y, params) filename:精灵文件名 x:x位置坐标 y:y位置坐标 params:表参数(不常用) 我们创建的时候为了方便,可以添加x,y参数,这样就不用在后面再设置位置了.此外,对于精灵的文件名,我们在使用Cocos2d-x的时候,都知道有直接从文件读取,也有的是从

[转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法

一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBox.Show (IWin32Window, String) 在指定对象的前面显示具有指定文本的消息框. MessageBox.Show (String, String) 显示具有指定文本和标题的消息框.由 .NET Compact Framework 支持. MessageBox.Show (IWi

quick-cocos2d-x游戏开发【14】——StateMachine状态机

状态机在quick中是一个亮点,如果我们做一款RPG游戏,一个角色一般会拥有idle,attack,walk,run,death这些状态,如果游戏角色的状态采用分支条件判断的话,会造成非常庞大而难以维护,但一旦使用了状态机这种模式,就会显得简单方便. 对于quick中的状态机是如何实现的咱们先不去了解,首先看看如何去使用它. 总结起来,如果让一个类拥有状态机,主要有两步: 1.创建状态机对象 2.初始化状态机,主要包括事件和回调函数 1.创建状态机组件 self.fsm = {} cc.Game

openerp学习笔记 context 的应用

1.在Action中定义,context用于传递搜索条件和分组条件,在搜索视图中默认显示: 示例代码: <record model="ir.actions.act_window" id="open_company_allocation"> <field name="name">Leaves Summary</field> <field name="res_model">hr.ho

windows ntp安装及调试

Setting up NTP on Windows It's very helpful that Meinberg have provided an installer for the highly-respected and high-accurate NTP software for Windows users - my thanks to them.  This Web page provides a quick guide to installing NTP on Windows XP,

前端补充

布局和事件 1.布局 首先看下下面的图片: 上面的内容都是居中的,怎么实现这个效果呢,第一种方法是通过float的方式,第二种是通过“div居中的方式” 第一种方式不在复述了,直接看第二种方式: 1.首先根据上面的图片我们可以把整个页面分为,“上”.“下”两部分 2.然后在在上下两部分中设置div并让他居中 3.居中的div不需要给他设置高度可以让内容给他吧高度顶起来 代码如下: <!DOCTYPE html> <html lang="en"> <head

搜狐女人轮播视频切换

<!doctype html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus®"> <meta name="Author" content="作者:千帆"> <meta name=&q

MARS3.6 Programming

An Assembly Language I.D.E. To Engage Students Of All Levels * A Tutorial *2007 CCSC: Central Plains Conference Pete Sanderson, Otterbein College, [email protected] Ken Vollmar, Missouri State University, [email protected] ? ? MARS is a software simu