Etapa 1: criar e iniciar um modo de exibição

Etapa 1: criar e iniciar um modo de exibição

[ Este artigo destina-se aos desenvolvedores do Windows 8.x e do Windows Phone 8.x que escrevem aplicativos do Windows Runtime. Se você estiver desenvolvendo para o Windows 10, consulte documentação mais recente ]

Nesta etapa, você criará e iniciará o CoreApplicationView que define as configurações básicas de uma janela de exibição. Além disso, você obterá o objeto CoreWindow que controla os eventos de entrada nesse modo de exibição.

Você pode pensar em um modo de exibição como um conjunto de configurações de interface de usuário de um aplicativo. Incluindo a área de exibição e os comportamentos de entrada, além do thread usado para processamento. Para criar um modo de exibição, crie uma instância de um alocador que retorne um modo de exibição de seu aplicativo iniciado com as configurações necessárias (inclusive a cadeia de permuta do DirectX).

Eis o processo:

  • Definir a fábrica do provedor de exibição e o objeto do provedor de exibição.
  • Implementar os quatro métodos públicos para criar uma nova janela para seu aplicativo: Initialize, SetWindow, Load e Run.
  • Implementar o método público que descarta a janela: Uninitialize.
  • Definir a fábrica do aplicativo para invocar a fábrica do provedor de exibição e gerar um provedor de exibição para seu aplicativo.
  • Solicitar que o singleton do aplicativo execute a fábrica com CoreApplication.Run.
Observação  O código usado nesta orientação foi tirado do modelo Aplicativo DirectX no Microsoft Visual Studio 2013 e pode ser encontrado nos arquivos App.h, App.cpp, DeviceResources.h e DeviceResources.cpp.
 

Instruções

Em primeiro lugar, crie um alocador para o modo de exibição, que cria instâncias do objeto IFrameworkView responsável pela definição do modo de exibição.

O alocador do provedor do modo de exibição é Direct3DApplicationSource e implementa IFrameworkViewSource. A interface IFrameworkViewSource tem apenas um método definido, CreateView. Esse método é chamado pelo singleton do aplicativo quando transferimos uma referência a Direct3DApplicationSource para CoreApplication.Run.

A implementação desse alocador é simples: retornamos uma referência para uma nova instância de um objeto de seu aplicativo que implementa IFrameworkView. O alocador é declarado no arquivo de cabeçalho como a seguir:


ref class Direct3DApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
{
public:
	virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
};



Observação  Um recurso sintático que pode ter chamado sua atenção é o operador "^", também chamado de operador acento circunflexo. O novo operador permite a exclusão automática de objetos em tempo de execução por meio da contagem de referência. Assim, você não precisa implementar o processo por conta própria. O operador ref indica uma classe de referência. As classes de referência devem ser usadas apenas para tipos que interoperam com o DirectX.
 

É claro que você também precisa definir o objeto principal do aplicativo e a implementação do IFrameworkView. Esse código para a definição do seu objeto de aplicativo é criado para o seu aplicativo como parte do modelo Aplicativo DirectX fornecido com o Visual Studio 2013.


ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
	{
	public:
		App();

		// IFrameworkView methods
		virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
		virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
		virtual void Load(Platform::String^ entryPoint);
		virtual void Run();
		virtual void Uninitialize();

	protected:
		// App lifecycle event handlers
		void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
		void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
		void OnResuming(Platform::Object^ sender, Platform::Object^ args);

		// Window event handlers
		void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
		void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
		void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);

		// Display properties event handlers
		void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
		void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
		void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);

	private:
		std::shared_ptr<DeviceResources> m_deviceResources;
		std::unique_ptr<MyDirectXAppMain> m_main;
		bool m_windowClosed;
		bool m_windowVisible;
	};



Você também pode criar sua própria implementação de provedor de modo de exibição. Se você optar por criar o seu próprio, tenha o seguinte em mente:

  • Seu objetivo é fornecer uma "visão" para a instância CoreWindow para que seu aplicativo possa usar para desenhar o estado para a exibição de uma forma que represente o seu aplicativo. Por so só, CoreWindow não tem como desenhar na tela. Em vez disso, é uma coleção encadeada de eventos e comportamentos de sistema que representam a interação do usuário. Cabe a você desenhar os resultados desses eventos e comportamentos, e o provedor do modo de exibição é o método pelo qual você faz isso.
  • Você tem acesso direto ao DirectX, assim como faria em um aplicativo da área de trabalho. Para realizar seu objetivo de fornecer um modo de exibição para o CoreWindow, você precisa encontrar uma maneira de conectar os eventos e comportamentos do CoreWindow importantes com o DirectX, e, finalmente, desenhar esses resultados na cadeia de permuta para apresentação.
  • O modelo de conexão da CoreWindow ao DirectX é sua implementação da interface IFrameworkView, que você transmite para o aplicativo de aplicativo quando ele é iniciado. Especificamente, quando você inicializa o renderizador (quando o objeto de aplicativo chama sua implementação da IFrameworkView::SetWindow), você transmite uma referência à CoreWindow do aplicativo para o renderizador e transmite essa referência para o IDXGIFactory2::CreateSwapChainForCoreWindow depois de configurar o contexto do dispositivo.

Formato curto: CoreWindow representa os eventos básicos de interface do usuário que você deseja, como as alterações de entrada e de tela. O DirectX é a maneira pela qual você desenha na tela. Sua implementação da IFrameworkView é a maneira de trazê-los juntos, criando um modo de exibição desses eventos de interface do usuário desenhado pelo DirectX. Cabe a você desenhar todos os pixels da maneira que quiser, em resposta a eventos disparados na CoreWindow.

Observação  Como uma opção: ComPtr, um tipo no Tempo de Execução do Windows, permite gerenciar a vida útil de tipos COM. Use esse tipo sempre que criar variáveis para objetos COM herdados projetados, como diversos objetos DirectX.
 

Esta implementação de um provedor de modo de exibição usa três métodos personalizados definidos na classe Direct3DBase e fornecidos como parte do modelo Aplicativo Direct3D do Visual Studio:

  • CreateDeviceResources
  • CreateWindowSizeDependentResources
  • Render

Esses métodos são específicos à implementação discutida aqui e mostram alguns passos importantes.

Para manter as coisas simples, seu renderizador deve herdar a classe Direct3DBase e chamar as implementações base desses métodos. A implementação dos métodos Direct3DBase será vista novamente na etapa 3: conectar a cadeia de permuta do DirectX.

Agora, veremos estes cinco métodos públicos, conforme declarados na sua classe de provedor de modo de exibição:

  • Initialize
  • SetWindow
  • Load
  • Run
  • Uninitialize

O objeto de aplicativo espera encontrar esses cinco métodos em qualquer instância do provedor de modo exibição que recebe. Em ordem, ele chama esses métodos para criar os recursos para o modo de exibição, configura a CoreWindow para usar o modo de exibição, carrega os recursos adicionais, executa o aplicativo e o descarta.

Agora, implemente os cinco métodos públicos na interface IFrameworkView.

Primeiro, no Initialize, você pode inicializar o renderizador de seu modo de exibição, que é o objeto que executa o desenho do DirectX. Você também atribuir o manipulador para o evento de ativação do modo de exibição, que obtém a CoreWindow do aplicativo quando o CoreApplicationView::Activated é acionado. Você também vincula os manipuladores para o aplicativo suspender e retomar os eventos.

Veja como é possível implementar Initialize.


// The first method called when the IFrameworkView is being created.
void App::Initialize(CoreApplicationView^ applicationView)
{
	// Register event handlers for app lifecycle. This example includes Activated, so that we
	// can make the CoreWindow active and start rendering on the window.
	applicationView->Activated +=
		ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);

	CoreApplication::Suspending +=
		ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);

	CoreApplication::Resuming +=
		ref new EventHandler<Platform::Object^>(this, &App::OnResuming);

	// At this point we have access to the device. 
	// We can create the device-dependent resources.
	m_deviceResources = std::make_shared<DeviceResources>();
}


Aqui, você conectou seus manipuladores aos eventos críticos de Gerenciamento do Tempo de Vida do Processo (PLM) para um aplicativo da Windows Store:

  • Ativação do aplicativo, quando é inicializado bruscamente
  • Suspensão do aplicativo, quando o usuário descarta o aplicativo
  • Retomada do aplicativo, quando o usuário retorna o aplicativo para o primeiro plano
Você criou também o processador que você usará para desenhar na tela.

No método SetWindow, você configura os comportamentos da janela e de exibição. Esse método é chamado sempre que a CoreWindow é alterada de alguma forma.


// Called when the CoreWindow object is created (or re-created).
void App::SetWindow(CoreWindow^ window)
{
	window->SizeChanged += 
		ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);

	window->VisibilityChanged +=
		ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);

	window->Closed += 
		ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);

	DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();

	currentDisplayInformation->DpiChanged +=
		ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged);

	currentDisplayInformation->OrientationChanged +=
		ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged);

	DisplayInformation::DisplayContentsInvalidated +=
		ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated);

	// Disable all pointer visual feedback for better performance when touching.
	auto pointerVisualizationSettings = PointerVisualizationSettings::GetForCurrentView();
	pointerVisualizationSettings->IsContactFeedbackEnabled = false; 
	pointerVisualizationSettings->IsBarrelButtonFeedbackEnabled = false;

	m_deviceResources->SetWindow(window);
}


A CoreWindow do seu aplicativo é atribuída ao renderizador chamando o método Initialize do seu objeto renderizador e o transmitindo nos resultados do CoreWindow::GetForCurrentThread. Isso é importante pois é o ponto onde você conecta explicitamente a CoreWindow à sua cadeia de permuta do Direct3D. Você pode usar o tipo Windows::Graphics::Display::DisplayInformation para armazenar e acessar informações sobre o estado atual da exibição e definir seus recursos apropriadamente.

O código de inicialização do DirectX no renderizador se parece com este, caso esteja curioso. Da mesma forma, seu próprio renderizador deve fazer uma referência à CoreWindow do aplicativo. E deve também ter etapas semelhantes para:

  • Criar os gráficos de recursos do dispositivo, incluindo a cadeia de permuta
  • Reconfigurar e recriar esses recursos em caso de alteração do tamanho da janela ou da orientação ou se o dispositivo gráfico for perdido (ou sofrer alguma alteração)

void DeviceResources::SetWindow(CoreWindow^ window)
{
	m_window = window;
	
	// SetDpi() will call CreateWindowSizeDependentResources()
	// if those resources have not been created yet.
	SetDpi(DisplayInformation::GetForCurrentView()->LogicalDpi);

	UpdateForWindowSizeChange();
}


void DeviceResources::UpdateForWindowSizeChange()
{
	DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();

	if (m_swapChainPanel == nullptr && (
            m_window->Bounds.Width  != m_outputSize.Width ||
            m_window->Bounds.Height != m_outputSize.Height
        ) || m_swapChainPanel != nullptr && (
            m_swapChainPanel->ActualWidth != m_outputSize.Width ||
            m_swapChainPanel->ActualHeight != m_outputSize.Height
        ) || m_orientation != currentDisplayInformation->CurrentOrientation)

	{
		CreateWindowSizeDependentResources();
	}
}

Você verá como implementar CreateWindowSizeDeviceResources na Etapa 3: conectar a cadeia de permuta do DirectX.

Agora, você inicializou o objeto renderizador com a CoreWindow para seu aplicativo, criou todos os recursos de elementos gráficos necessários para desenhar na tela e adicionou os manipuladores de eventos ao conjunto básico de eventos de entrada para essa janela. Agora, iremos para a próxima etapa.

No método Load, você pode carregar opcionalmente qualquer recurso externo ou secundário do aplicativo e realizar qualquer inicialização de estado ou cache do aplicativo. Aqui, nós criamos um ponteiro para o objeto de aplicativo principal e o atribuímos a uma variável global para acesso posterior.



// Initializes scene resources, or loads a previously saved app state.
void App::Load(Platform::String^ entryPoint)
{
		m_main = std::unique_ptr<MyDirectXAppMain>(new MyDirectXAppMain(m_deviceResources));
}


Run cria e inicia o loop de processamento principal para seu aplicativo e chama o despachante de eventos do singleton de aplicativo atual com uma chamada para o CoreDispatcher::ProcessEvents em todas as iterações. Quando você chama o CoreDispatcher::ProcessEvents, processa todas as mensagens de evento que chegaram desde a última chamada. Tenha em mente que você sempre deve usar CoreProcessEventsOption::ProcessAllIfPresent como o comportamento da fila de mensagens para seus aplicativos da Windows Store em DirectX com C++, pois o comportamento de distribuição de mensagens que ele indica não afeta o desempenho geral de elementos gráficos.

(Para saber mais sobre o comportamento de envio de eventos, veja Objeto e DirectX do aplicativo.)

Aqui, você também deve renderizar a saída inicial de Direct3D e apresentá-la ao modo de exibição da janela.



// This method is called after the window becomes active.
void App::Run()
{
	while (!m_windowClosed)
	{
		if (m_windowVisible)
		{
			CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);

			m_main->Update();

			if (m_main->Render())
			{
				m_deviceResources->Present();
			}
		}
		else
		{
			CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
		}
	}
}


Quando você inicia o aplicativo, o alocador de aplicativo chama esses quatro métodos na ordem e inicia o loop de processamento do seu aplicativo, que é executado sobre o segmento do aplicativo principal. Porém, ainda há um método para implementar, aquele chamado quando o objeto de provedor de modo de exibição é dispensado enquanto o aplicativo está em primeiro plano.

Uninitialize descarrega e limpa todos os recursos de exibição, cache e ativos criados ou carregados no método Load. Neste exemplo, você pode deixar essa opção em branco.


// Required for IFrameworkView.
// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
// class is torn down while the app is in the foreground.
void App::Uninitialize()
{
}

A implementação dos métodos DeviceResources específicos é abordada no tópico sobre como conectar a cadeia de permuta do DirectX.

Agora, você configurou o objeto do provedor de modo de exibição e especificou a implementação dos cinco métodos que definem o provedor. Com essa tarefa concluída, é hora de criar um modo de exibição por conta própria com o método principal do aplicativo.

Para isso, crie uma instância do alocador do provedor de modo de exibição ao iniciar o aplicativo com o método main, conforme visto aqui:



// Start the app.

[Platform::MTAThread]
int main(Platform::Array<Platform::String^>^)
{
	auto direct3DApplicationSource = ref new Direct3DApplicationSource();
	CoreApplication::Run(direct3DApplicationSource);
	return 0;
}}

Quando o aplicativo é iniciado, ele cria o alocador do provedor de modo de exibição, que o método CoreApplication.Run usa para criar um novo objeto de provedor de modo de exibição e chama as implementações de Initialize, SetWindow,Load e Run.

Próxima etapa

Configurar os manipuladores de eventos

Tópicos relacionados

Como configurar o seu aplicativo DirectX da Windows Store para mostrar uma visualização
Código completo de um aplicativo DirectX da Windows Store

 

 

Mostrar:
© 2016 Microsoft