【问题标题】:TTreeView custom draw item widthTTreeView 自定义绘制项宽度
【发布时间】:2014-10-15 16:11:52
【问题描述】:

我使用 OnCustomDrawItem 事件来绘制这样的 TTreeView:

这是我的代码:

procedure Tform1.trvArbreCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  vRect      : TRect;
  vBmp       : TBitmap;
  vBmpRect   : TRect;
  vTreeView  : TTreeView;
  vBarreInfo : TScrollInfo;
  vDeltaX    : Integer;
begin
  DefaultDraw := False;
  vTreeView   := TTreeView(Sender);

  vRect := Node.DisplayRect(False);

  vBmp := TBitmap.Create();

  FillChar(vBarreInfo, SizeOF(vBarreInfo), 0);

  vBarreInfo.cbSize := SizeOf(vBarreInfo);
  vBarreInfo.fMask  := SIF_RANGE or SIF_POS;

  if GetScrollInfo(trvArbre.Handle, SB_HORZ, vBarreInfo) then
  begin
    if vBarreInfo.nMax > vRect.Right  - vRect.Left then
    begin
      vBmp.Width  := vBarreInfo.nMax + 1;
      vBmp.Height := vRect.Bottom - vRect.Top;

      vDeltaX := vBarreInfo.nPos;
    end
    else
    begin
      vBmp.Width  := vRect.Right  - vRect.Left;
      vBmp.Height := vRect.Bottom - vRect.Top;

      vDeltaX := 0;
    end;
  end
  else
  begin
    vBmp.Width  := vRect.Right  - vRect.Left;
    vBmp.Height := vRect.Bottom - vRect.Top;

    vDeltaX := 0;
  end;

  vBmpRect := Rect(0, 0, vBmp.Width, vBmp.Height);

  if cdsSelected in State then
  begin
    vBmp.Canvas.Brush.Color := cMenuDownFond;
    vBmp.Canvas.Pen  .Color := cMenuDownBordure;
  end 
  else if cdsHot in State then
  begin
    vBmp.Canvas.Brush.Color := cMenuSurvolFond;
    vBmp.Canvas.Pen  .Color := cMenuSurvolBordure;
  end    
  else
  begin
    vBmp.Canvas.Brush.Color := clWhite;
    vBmp.Canvas.Pen  .Color := clwhite;
  end;

  vBmp.Canvas.Rectangle(vBmpRect);

  vBmpRect.Left := vBmpRect.Left + 3;

  vBmpRect.Left := vBmpRect.Left + (Node.Level * vTreeView.Indent);

  if Node.StateIndex >= 0 then
  begin
    vTreeView.StateImages.Draw(vBmp.Canvas, vBmpRect.Left, vBmpRect.Top, Node.StateIndex);
  end;

  vBmpRect.Left := vBmpRect.Left + 18;

  vTreeView.Images.Draw(vBmp.Canvas, vBmpRect.Left, vBmpRect.Top, Node.ImageIndex);

  vBmpRect.Left := vBmpRect.Left + 18 + 3;

  vBmp.Canvas.Font := vTreeView.Font;

  DrawText
  (
    vBmp.Canvas.Handle,
    PChar(Node.Text),
    Length(Node.Text),
    vBmpRect,
    DT_SINGLELINE or DT_LEFT or DT_VCENTER or DT_NOPREFIX or DT_END_ELLIPSIS
  );

  BitBlt
  (
    Sender.Canvas.Handle,
    vRect.Left,
    vRect.Top,
    vRect.Right  - vRect.Left,
    vRect.Bottom - vRect.Top,
    vBmp.Canvas.Handle,
    vDeltaX,
    0,
    SRCCOPY
  );

  FreeAndNil(vBmp);
end;

我的问题是节点“我的最后一个节点不太长”并不太长,不足以证明水平滚动条的存在。

当我将 DefaultDraw 设置为 true 时,我得到:

似乎节点的宽度是用我不使用的字体计算的。

我尝试更改画布的字体,使用 Windows API,使用 OnAdvancedCustomDrawItem,但没有结果。

谢谢。

【问题讨论】:

  • 我使用 Delphi 7。我将 ComCtrls.pas 复制到我的应用程序文件夹中。我更改了procedure TCustomTreeView.CNNotify(var Message: TWMNotify);。第 8979 行从 Result := Result or CDRF_SKIPDEFAULTResult := Result or CDRF_SKIPDEFAULT;,我评论了第 8980 行` else if FCanvasChanged then`,以便模拟DefaultDrawFCanvasChanged。它似乎有效,但是......嗯......我真的不确定。您如何看待这种变化?

标签: delphi


【解决方案1】:

我使用 Delphi 7。我将 ComCtrls.pas 复制到我的应用程序文件夹中。我更改了程序TCustomTreeView.CNNotify(var Message: TWMNotify);。第 8979 行从 Result := Result or CDRF_SKIPDEFAULTResult := Result or CDRF_SKIPDEFAULT; 并且我评论了第 8980 行 else if FCanvasChanged then 以模拟 DefaultDraw=TrueFCanvasChanged 即使我在事件中将 DefaultDraw 设置为 False 并且不要更改字体。经过大量测试,我没有看到任何警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 2019-04-07
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    相关资源
    最近更新 更多