使用poUnbuffered选项时,TVirtualStringTree中的PaintTree逻辑似乎存在错误。在输出中只有树的第一个节点可见。我使用最小VST示例进行了测试,其行为相同。如果将poUnbuffered用作选项,则仅第一个节点可见,删除该选项,树将正确绘制。

如果我单步执行代码,则所有对象都被绘制在画布上,因此看起来像是裁剪问题,但我与VST的合作不足以识别问题所在。他们在画布的来源和剪裁方面发挥了很大作用。

要查看实际问题,只需将以下代码放在包含VST的任何形式上,根据需要更改名称以保护无辜者,然后单击即可。

procedure TMainForm.Button2Click(Sender: TObject);
var
  saveBitmap: TBitmap;
begin
  saveBitmap := TBitmap.Create;
  try
    saveBitmap.height := 400;
    saveBitmap.width := 400;

    vst.PaintTree(
      saveBitmap.Canvas,
      Rect(0, 0, 400, 400),
      Point(0, 0),
      [poBackground, poColumnColor, poGridLines, poUnbuffered], // Remove poUnbuffered to have the tree paint correctly
      pfDevice     // pixelformat
      );

    saveBitmap.SaveToFile('E:\temp\CanvasSave' + FormatDateTime('hhnnsszzz', Now) + '.bmp');
  finally
    saveBitmap.Free;
  end;
end;


有人遇到过吗?

一些更多的细节:

poUnbuffered和不带poUnbuffered的绘画代码之间几乎没有区别。我没有使用列,所以主要区别是:

  if not (poUnbuffered in PaintOptions) then
  begin
    // Create small bitmaps and initialize default values.
    // The bitmaps are used to paint one node at a time and to draw the result to the target (e.g. screen) in one step,
    // to prevent flickering.
    NodeBitmap := TBitmap.Create;
    // For alpha blending we need the 32 bit pixel format. For other targets there might be a need for a certain
    // pixel format (e.g. printing).
    if MMXAvailable and ((FDrawSelectionMode = smBlendedRectangle) or (tsUseThemes in FStates) or
      (toUseBlendedSelection in FOptions.PaintOptions)) then
      NodeBitmap.PixelFormat := pf32Bit
    else
      NodeBitmap.PixelFormat := PixelFormat;

    NodeBitmap.Width := PaintWidth;

    // Make sure the buffer bitmap and target bitmap use the same transformation mode.
    SetMapMode(NodeBitmap.Canvas.Handle, GetMapMode(TargetCanvas.Handle));
    PaintInfo.Canvas := NodeBitmap.Canvas;
  end
  else
  begin
    PaintInfo.Canvas := TargetCanvas;
    NodeBitmap := nil;
  end;




          if not (poUnbuffered in PaintOptions) then
          begin
            // Adjust height of temporary node bitmap.
            with NodeBitmap do
            begin
              if Height <> PaintInfo.Node.NodeHeight then
              begin
                // Avoid that the VCL copies the bitmap while changing its height.
                Height := 0;
                Height := PaintInfo.Node.NodeHeight;
                SetCanvasOrigin(Canvas, Window.Left, 0);
              end;
            end;
          end
          else
          begin
            SetCanvasOrigin(PaintInfo.Canvas, -TargetRect.Left + Window.Left, -TargetRect.Top);
            ClipCanvas(PaintInfo.Canvas, Rect(TargetRect.Left, TargetRect.Top, TargetRect.Right,
                                              Min(TargetRect.Bottom, MaximumBottom)))
          end;


在不使用poUnbuffered的情况下,BitBlt的后续版本将位图复制到画布上。

最佳答案

这是我从另一个与PaintTree代码有关的问题中解决的问题的变通方法,并且它是poUnbuffered的。我上面列出的第二个代码摘录中显然存在一个问题。显然SetCanvasOrigin更改了原点,而ClipCanvas没有考虑这些更改。该代码应更改如下:

      begin
        SetCanvasOrigin(PaintInfo.Canvas, -TargetRect.Left + Window.Left, -TargetRect.Top);
        // ClipCanvas(PaintInfo.Canvas, Rect(TargetRect.Left, TargetRect.Top, TargetRect.Right,
        //                                   Min(TargetRect.Bottom, MaximumBottom)))
        ClipCanvas(PaintInfo.Canvas, Rect(0, 0, TargetRect.Right - TargetRect.Left,
                                          Min(TargetRect.Bottom - TargetRect.Top, MaximumBottom - TargetRect.Top)));
      end;


我已经证实这可以解决我的情况。它可能并非在所有情况下都有效。在我的情况下,在这种情况下,我只使用poUnbuffered,所以对我来说风险是有限的。

关于delphi - 使用poUnbuffered时TVirtualStringTree中不正确的PaintTree行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22055775/

10-12 02:12