Win2D メモ - DrumMidiEditor/DrumMidiEditorApp GitHub Wiki

使用パッケージ

image

参考URL
https://baydachnyy.com/2015/08/04/win2d-how-to-use-graphics-without-knowledge-in-directx/

  • CanvasControl
     静的な描画に適している。

  • CanvasAnimatedControl
     WinUI3 では実装されていない。(2022/07時点)

  • CanvasSwapChainPanel
     DirectXのプログラムしているとよく出てくる SwapChain
     プレイヤーの描画はこれを使うようにしないとね

CanvasControl

描画

使う機能メモ

<UserControl 
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    Unloaded="UserControl_Unloaded">

    <Grid>
        <canvas:CanvasControl Draw="EditerCanvas_Draw" />
    </Grid>
</UserControl>

イベント処理:

private void UserControl_Unloaded( object sender, RoutedEventArgs args )
{
	// Win2D アンロード
	_EqualizerCanvas.RemoveFromVisualTree();
	_EqualizerCanvas = null;
}

private void _EqualizerCanvas_Draw( CanvasControl sender, CanvasDrawEventArgs args )
{
}

線描画:

args.DrawingSession.DrawLine
    (
        x1,
        y1,
        x2,
        y2,
        LineColor,
        LineSize
    );

四角

args.DrawingSession.FillRectangle
    (
        aDrawRect,
        BackColor
    );
args.DrawingSession.DrawRectangle
    (
        aDrawRect,
        aFormatRect.LineColor,
        aFormatRect.LineSize
    );

円:XY座標は円の中心点、縦横のサイズは半径で指定が必要

aGraphics.FillEllipse
  ( 
        (float)( rect.X + rect.Width  / 2 ),
        (float)( rect.Y + rect.Height / 2 ),
        rect._width  / 2,
        rect._height / 2,
        _FormatRect.BackColor
  );

テキスト:テキストの書式設定内でフォントや左寄などの設定が必要

args.DrawingSession.DrawText
    (
        aLabelText,
        aDrawRect,
        TextColor,
        TextFormat
    );

ひし形(多角形):CanvasControl sender の情報も必要

Vector2[] ps =
    {
        new( rect._x				, (float)( rect.Y + rect.Height / 2 )	),
        new( (float)( rect.X + rect.Width / 2 )	, rect._y				),
        new( (float)( rect.Right )		, (float)( rect.Y + rect.Height / 2 )	),
        new( (float)( rect.X + rect.Width / 2 ) , (float)( rect.Bottom )		)
    };

// ノートOFF描画
args.DrawingSession.DrawGeometry
	(
		CanvasGeometry.CreatePolygon( sender, ps ),
		LineColor,
		LineSize
	);

CanvasSwapChainPanel

CanvasControl から CanvasSwapChainPanel への変更は簡単
Drawイベントがないので、非同期の描画ループ処理など、描画プロセスの実装が必要

<UserControl xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml">
    <Grid>
        <canvas:CanvasSwapChainPanel x:Name = "_PlayerCanvas" />
    </Grid>
</UserControl>
// スワップチェイン作成
_PlayerCanvas.SwapChain = new CanvasSwapChain
    (
        new CanvasDevice(),
        DrawSet.ResolutionScreenWidth,
        DrawSet.ResolutionScreenHeight,
        96
    );

// 描画サイズ変更
//_PlayerCanvas.SwapChain.ResizeBuffers
//    (
//        DrawSet.ResolutionScreenWidth,
//        DrawSet.ResolutionScreenHeight,
//        96
//    );

// 描画開始前準備
using var drawSession = _PlayerCanvas.SwapChain
    .CreateDrawingSession( DrawSet.SheetColor.Color );

var args = new CanvasDrawEventArgs( drawSession );

// 描画処理
//_PlayerSurface?.OnDraw( _PlayerCanvas, args );

// 描画終了
_PlayerCanvas.SwapChain.Present();

Win2Dのサンプルより垂直同期
https://github.com/microsoft/Win2D-Samples/blob/reunion_master/CompositionExample/SwapChainRenderer.cs

swapChain.WaitForVerticalBlank();

その他

Convert CanvasBitmap to Bitmap

オフスクリーンに書き込んで、CanvasBitmap を作成後
Bitmapへバッファコピーする。

var device = CanvasDevice.GetSharedDevice();

var offscreen = new CanvasRenderTarget
    (
        device,
        ActualSize.X,
        ActualSize.Y,
        96
    );

using var g = offscreen.CreateDrawingSession();

// 描画処理
g.Clear( DrawSet.SheetColor.Color );

// CanvasBitmap作成
var frame = CanvasBitmap.CreateFromBytes
    ( 
        g,
        offscreen.GetPixelBytes( 0, 0, (int)offscreen.SizeInPixels.Width, (int)offscreen.SizeInPixels.Height ),
        (int)offscreen.SizeInPixels.Width,
        (int)offscreen.SizeInPixels.Height,
        DirectXPixelFormat.R8G8B8A8UIntNormalized,		// ココ
        96,
        CanvasAlphaMode.Premultiplied
    );

var buffer = frame.GetPixelBytes();

// Bitmap作成
var bmp = new Bitmap
    ( 
	(int)frameSize.Size.Width, 
	(int)frameSize.Size.Height, 
	PixelFormat.Format32bppArgb		// ココ
     );

// CanvasBitmap のデータを Bitmap へコピー
var bmpData = bmp.LockBits
(
    new( 0, 0, bmp.Width, bmp.Height ),
    ImageLockMode.WriteOnly,
    bmp.PixelFormat
);

Marshal.Copy( buffer, 0, bmpData.Scan0, buffer.Length );

bmp.UnlockBits( bmpData );

恐らく上記だけだと色がおかしくなるのではないかと思われる
根拠なしですが、RGBA → ARGB に上書きしているので
A=R, R=G, G=B, B=A の値が設定されている?

⚠️ **GitHub.com Fallback** ⚠️