2

poUnbuffered オプションを使用すると、TVirtualStringTree の PaintTree ロジックにバグがあるようです。ツリーの最初のノードのみが出力に表示されます。Minimal 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 を使用する場合と使用しない場合のペイント コードの違いはほとんどありません。私は列を使用していないため、主な違いは次のとおりです。

  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 が後でいくつかあります。

4

1 に答える 1

1

これは、PaintTree コードと poUnbuffered に関する別の問題から取り上げた問題の回避策です。上記の 2 番目のコードの抜粋には明らかに問題があります。どうやら 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 のみを使用しているため、リスクは限られています。

于 2014-02-27T01:22:43.683 に答える