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