如何:使用子画面

更新:2007 年 11 月

您可以使用子画面来向屏幕绘制图像和文本。此示例演示绘图和呈现。

此代码示例的窗体包含以下对象:

此代码示例从文件加载纹理以创建子画面。项目中需要有一个小位图,以便将其部署到设备或仿真程序。

窗体的构造函数会指定设备的 PresentationParameters 属性的设置,创建一个 Device 对象,然后调用设备的 Reset 方法。它还会构造一个 Font 对象。

下表描述了呈现子画面的示例方法。

说明:

托管 Direct3D 移动应用程序需要使用适用于 Pocket PC 和 Smartphone 的 Windows Mobile 5.0 版软件。有关 Windows Mobile 软件和 SDK 的信息,请参见 .NET Compact Framework 的外部资源

方法

操作

OnDeviceReset

  • 从位图文件加载纹理。

OnPaint

  1. 开启屏幕。

  2. 指定 SpriteFlags 标志。有关详细信息,请参见本主题后面的“可靠编程”一节。

  3. 向屏幕绘制子画面和文本。

  4. 结束屏幕。

示例

下面的代码示例提供了一个完整的窗体。它使用了提供的位图来绘制子画面。

Class Sprites
    Inherits Form
    ' The objects that will be used to show
    ' the uses of the Sprite class
    Private device As Device
    Private d3dFont As Microsoft.WindowsMobile.DirectX.Direct3D.Font
    Private sprite As Sprite
    Private texture As Texture


    Public Sub New() 
        Dim present As PresentParameters
        Dim gdiFont As System.Drawing.Font

        Me.Text = "Using Sprites"

        ' Give the application a way to be closed.
        ' This must be done before the device is created
        ' as it will cause the hwnd of the Form to change.
        Me.MinimizeBox = False

        present = New PresentParameters()
        present.Windowed = True
        present.SwapEffect = SwapEffect.Discard

        device = New Device(0, DeviceType.Default, Me, CreateFlags.None, present)
        AddHandler device.DeviceReset, AddressOf OnDeviceReset

        ' Construct a new Sprite.
        ' Sprites do not need to be recreated
        ' when a device is reset.
        sprite = New Sprite(device)

        gdiFont = New System.Drawing.Font(FontFamily.GenericSansSerif, 10F, FontStyle.Regular)

        ' Construct a new font. Fonts do not need
        ' to be recreated when a device is reset.
        d3dFont = New Microsoft.WindowsMobile.DirectX.Direct3D.Font(device, gdiFont)

        OnDeviceReset(Nothing, EventArgs.Empty)

    End Sub


    Private Sub OnDeviceReset(ByVal sender As Object, ByVal e As EventArgs) 
        ' Textures must be recreated whenever a device is reset
        ' no matter what pool they are created in.
        texture = TextureLoader.FromFile(device, "image.bmp")

    End Sub


    Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs) 
        ' Do nothing.
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        ' Begin the scene and clear the back buffer to black
        device.BeginScene()
        device.Clear(ClearFlags.Target, Color.Black, 1.0F, 0)

        ' When using sprites it is important to
        ' specify sprite flags passed to Sprite.Begin
        sprite.Begin(SpriteFlags.SortTexture Or SpriteFlags.AlphaBlend)

        ' Draw an image to the screen using Sprite.Draw
        Dim spriteY As Integer = 5

        sprite.Draw(texture, Vector3.Empty, New Vector3(0, spriteY, 0), Color.White.ToArgb())
        spriteY += texture.GetLevelDescription(0).Height + 5

        ' Draw a portion of an image to the screen
        ' using Sprite.Draw. This shall be drawn such
        ' that the image is modulated with the color green.
        sprite.Draw(texture, New Rectangle(4, 4, 24, 24), Vector3.Empty, New Vector3(0, spriteY, 0), Color.Green)

        spriteY += 30

        ' Draw text to the screen. Using a sprite to draw text
        ' to the  screen is essential for good performance.
        ' Otherwise the font object will perform a
        ' Sprite.Begin/Sprite.End internally for
        ' each call to Font.DrawText. This can cause severe
        ' performance problems.
        spriteY = 150

        d3dFont.DrawText(sprite, "This is text.", 5, spriteY, Color.Red)
        spriteY += d3dFont.Description.Height + 5

        d3dFont.DrawText(sprite, "This is another line of text.", 5, spriteY, Color.Green)
        spriteY += d3dFont.Description.Height + 5

        d3dFont.DrawText(sprite, "Only one call to Sprite.Begin.", 5, spriteY, Color.Blue)

        ' End drawing using this sprite. This will cause the
        ' sprites to be flushed to the graphics driver and will
        ' reset the transformation matrices, textures states,
        ' and renderstates if the SpriteFlags specified in Begin
        ' call for that to happen.
        sprite.End()

        ' Finish the scene and present it on the screen.
        device.EndScene()
        device.Present()

    End Sub


    Shared Sub Main() 
        Application.Run(New Sprites())

    End Sub
End Class
class Sprites : Form
{
    // The objects that will be used to show
    // the uses of the Sprite class
    private Device device;
    private Microsoft.WindowsMobile.DirectX.Direct3D.Font d3dFont;
    private Sprite sprite;
    private Texture texture;

    public Sprites()
    {
        PresentParameters present;
        System.Drawing.Font gdiFont;

        this.Text = "Using Sprites";

        // Give the application a way to be closed.
        // This must be done before the device is created
        // as it will cause the hwnd of the Form to change.
        this.MinimizeBox = false;

        present = new PresentParameters();
        present.Windowed = true;
        present.SwapEffect = SwapEffect.Discard;

        device = new Device(0, DeviceType.Default, this,
            CreateFlags.None, present);
        device.DeviceReset += new EventHandler(OnDeviceReset);

        // Construct a new Sprite.
        // Sprites do not need to be recreated
        // when a device is reset.
        sprite = new Sprite(device);

        gdiFont = new System.Drawing.Font
            (FontFamily.GenericSansSerif,
        10.0f, FontStyle.Regular);

        // Construct a new font. Fonts do not need
        // to be recreated when a device is reset.
        d3dFont= new Microsoft.WindowsMobile.DirectX.Direct3D.Font
            (device, gdiFont);

        OnDeviceReset(null, EventArgs.Empty);
    }

    private void OnDeviceReset(object sender, EventArgs e)
    {
        // Textures must be recreated whenever a device is reset
        // no matter what pool they are created in.
        texture = TextureLoader.FromFile(device, "image.bmp");
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // Do nothing.
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        // Begin the scene and clear the back buffer to black
        device.BeginScene();
        device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);

        // When using sprites it is important to
        // specify sprite flags passed to Sprite.Begin

        sprite.Begin(SpriteFlags.SortTexture | SpriteFlags.AlphaBlend);

        // Draw an image to the screen using Sprite.Draw

        int spriteY = 5;

        sprite.Draw(texture, Vector3.Empty, new Vector3(0,
            spriteY, 0),
            Color.White.ToArgb());
        spriteY += texture.GetLevelDescription(0).Height + 5;

        // Draw a portion of an image to the screen
        // using Sprite.Draw. This shall be drawn such
        // that the image is modulated with the color green.

        sprite.Draw(texture, new Rectangle(4, 4, 24, 24),
            Vector3.Empty,
            new Vector3(0, spriteY, 0), Color.Green);

        spriteY+= 30;

        // Draw text to the screen. Using a sprite to draw text
        // to the  screen is essential for good performance.
        // Otherwise the font object will perform a
        // Sprite.Begin/Sprite.End internally for
        // each call to Font.DrawText. This can cause severe
        // performance problems.

        spriteY = 150;

        d3dFont.DrawText(sprite, "This is text.",
            5, spriteY, Color.Red);
        spriteY += d3dFont.Description.Height + 5;

        d3dFont.DrawText(sprite, "This is another line of text.",
            5, spriteY, Color.Green);
        spriteY += d3dFont.Description.Height + 5;

        d3dFont.DrawText(sprite, "Only one call to Sprite.Begin.",
            5, spriteY, Color.Blue);

        // End drawing using this sprite. This will cause the
        // sprites to be flushed to the graphics driver and will
        // reset the transformation matrices, textures states,
        // and renderstates if the SpriteFlags specified in Begin
        // call for that to happen.
        sprite.End();

        // Finish the scene and present it on the screen.
        device.EndScene();
        device.Present();
    }

    static void Main()
    {
        Application.Run(new Sprites());
    }
}

编译代码

此示例需要引用下面的命名空间:

可靠编程

在窗体的构造函数中创建子画面和字体,以便在设备重置后无需重新创建它们。

为了提高性能,请使用子画面绘制文本。否则,每次调用 DrawText,字体对象都会在内部执行子画面的 BeginEnd 方法。

如果可能,在每帧使用一个子画面时,应将子画面嵌套在对子画面的 BeginEnd 方法的一个调用内。

请指定下列 SpriteFlags 值以优化呈现和提高性能:

  • SortTexture 在将图像绘制到屏幕之前先对图像进行排序,以便加快切换纹理的速度。

  • AlphaBlend 可正确呈现字体,尤其适用于具有透明或半透明区域的子画面。

  • SortDepthBackToFront 按照从前向后的顺序对子画面进行排序;如果您拥有几个要互相绘制到对方顶部的透明或半透明子画面,就可以使用此值。

  • DoNotSaveState 可提高那些不能使用指定呈现状态的应用程序的性能。

  • DoNotModifyRenderState 可通过使用当前呈现状态优化性能,且可用来获得特殊效果。

  • 使用 ObjectSpaceBillboard,可以绘制出具有各种不同的特殊效果的图像。

请参见

概念

.NET Compact Framework 帮助主题

其他资源

.NET Compact Framework 中的 Mobile Direct3D 编程