Exibir uma exibição XNA diretamente em uma janela do WPF
resumo
Descreve como renderizar diretamente em uma janela do WPF com XNA.
Ambiente operacional
Pré-requisitos
Versões do XNA suportadas |
|
Plataformas suportadas |
|
Versão do sombreador de vértice necessária para Windows | 1.1 |
Versão do sombreador de pixel necessária para Windows | 1.1 |
Ambiente operacional
plataforma |
substância
Em Usando XNA em aplicativos WPF, usei o controle WindowsFormsHost para exibir o modo de exibição, mas agora quero usar apenas a janela do WPF para exibir o polígono. "Usando XNA em aplicativos WPF" é um pouco de representação, então explicarei as diferenças.
Aliases de namespace
// 名前空間エイリアス
using Xna = Microsoft.Xna.Framework;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;
Como as estruturas Color e Matrix são cobertas pelos namespaces XNA Framework e WPF, você deve especificar o nome da estrutura do namespace para usá-la. No entanto, parece ser longo todas as vezes, então estou criando um alias de namespace. Por exemplo, "Microsoft.Xna.Framework.Rectangle" agora pode ser especificado como "Xna.Rectangle".
temporizador
Desde o .NET Framework 3.0, uma classe de temporizador chamada "System.Windows.Threading.DispatcherTimer" está disponível e essa classe de temporizador é usada para renderizar cada quadro. O WPF usa um DispatcherTimer para permitir o processamento no mesmo thread que a interface do usuário.
<summary>
タイマー
</summary>
private DispatcherTimer timer = null;
, declarando um DispatcherTimer.
<summary>
タイマーイベント
</summary>
<param name="sender"></param>
<param name="e"></param>
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
this.Draw();
}
Define um método que o DispatcherTimer chama em intervalos regulares.
// タイマー
this.timer = new DispatcherTimer();
this.timer.Tick += new EventHandler(dispatcherTimer_Tick);
this.timer.Interval = new TimeSpan(0, 0, 0, 0, 16);
this.timer.Start();
Este é o processo de definir o cronômetro. Depois de criar uma instância de DispatcherTimer e definir o método a ser chamado e o intervalo de tempo, o método DispatcherTimer.Start inicia o temporizador.
Obtendo um identificador de janela
Para criar um dispositivo Direct3D, você precisa de um identificador de janela. No entanto, o WPF não tem o conceito de um identificador de janela, portanto, não há como obtê-lo diretamente da classe Window.
No entanto, como há momentos em que um identificador de janela é necessário, como nesse caso, o identificador de janela pode ser obtido por meio da classe "System.Windows.Interop.WindowInteropHelper" como uma interoperabilidade para o código Win32. (esta é a classe Window)
// ウィンドウハンドルを取得する
IntPtr handle = new WindowInteropHelper(this).Handle;
Use esse identificador ao criar um dispositivo Direct3D. No entanto, se você tentar obter o identificador de janela no método OnInitialized, ele retornará 0, provavelmente porque a janela ainda não foi criada. Neste exemplo, o dispositivo é criado no método OnSourceInitialized.
Renderizar para área especificada
Você pode especificar a área de destino como o segundo argumento de GraphicsDevice.Present. Na amostra, tento desenhá-lo na posição (50, 50) como um deslocamento. O tamanho é o mesmo que o tamanho do backbuffer (300, 300). O primeiro argumento é a área da qual extrair e, se null for especificado, o buffer original será usado.
// 描画先を指定する
Xna.Rectangle rect = new Xna.Rectangle(
50, 50,
(int)this.viewSize.Width, (int)this.viewSize.Height);
this.device.Present(null, rect, this.windowHandle);
Destruindo um dispositivo
Você está destruindo seu dispositivo quando fecha a janela. Originalmente, eu queria lidar com isso com o método Dispose, mas como a classe Window do WPF não herda IDisposable por padrão, eu a escrevi aqui.
<summary>
ウインドウが閉じたとき
</summary>
<param name="e"></param>
protected override void OnClosed(EventArgs e)
{
if (this.device != null)
{
this.device.Dispose();
this.device = null;
}
base.OnClosed(e);
}
execução
Se você executar o programa de exemplo, poderá executá-lo com uma imagem de tela como a do início do artigo.
À primeira vista, ele renderiza bem, mas quando redimensiono a janela arrastando-a com o mouse, a visualização pisca ou desaparece durante o redimensionamento. Parece estar em conflito com a renderização do WPF, e tentei muitas coisas, mas não consegui resolver.
Se você estiver usando o XNA, parece mais seguro usar o controle WindowsFormsHost.
O programa requer o .NET Framework 3.0, o tempo de execução DirectX mais recente e o Microsoft XNA Framework Redistributable 2.0. Além disso, como requisito de hardware, é necessária "uma placa gráfica compatível com Pixel Shader 1.1 ou superior".
Além disso, o projeto foi criado no "Visual Studio 2008 Professional Edition". Prepare um ambiente para o Visual Studio 2008.