美文网首页Noesis Gui
C++教程5:应用框架

C++教程5:应用框架

作者: YottaYuan | 来源:发表于2020-03-15 04:43 被阅读0次

应用框架

教程数据

尽管noesisGUI可以完全集成到您的应用程序中,但是如集成教程中所示,还提供了一个Application Framework。该框架是一个开放源代码库,提供了用于创建多平台应用程序的抽象。该框架是有关如何使用Noesis的一个很好的示例,它提供了许多有用的帮助程序。我们所有的开放示例都使用该应用程序框架。

提供的扩展(例如ApplicationWindow)与WPF兼容,因此与Microsoft Blend兼容。使用应用程序框架,您可以设计将在Windows窗口,macOS窗口,iPhone屏幕或Xbox TV中兼容运行的应用程序。该框架支持NoesisGUI可用的所有平台。

spacer.png

以下是应用程序框架公开的功能列表:

  • 应用窗口的多平台抽象。
  • 输入事件的多平台处理:键盘,鼠标,触摸和游戏手柄。
  • 支持播放声音。
  • 用于加载资源的资源提供者实现。
  • 每种支持的图形API的渲染实现。
  • 交互包。

注意
Application Framework提供了我们的示例和教程所需的功能。永远不要将其用作“生产就绪”库。客户应将代码作为起点,必须针对每种特定情况进行适配和调整。

头文件和命名空间

应用程序框架的头文件包含在NsAppNsRender模块中。该API在NoesisApp命名空间中公开。

#include <NsApp/EntryPoint.h>
#include <NsApp/Application.h>
#include <NsApp/ApplicationLauncher.h>
#include <NsApp/Window.h>
#include <NsApp/EmbeddedXamlProvider.h>
#include <NsApp/EmbeddedFontProvider.h>

using namespace Noesis;
using namespace NoesisApp;

注意
请注意,框架头文件不在标准NoesisGUI的内部,也不包含“ Noesis_pch.h”预编译头文件。

入口点

由于main()并非在所有平台上都可用,因此该框架提供了一个可移植的入口点NsMain。通常,您将在此处创建一个Launcher,对其进行配置并对其进行Run()

int NsMain(int argc, char **argv)
{
    AppLauncher launcher;
    launcher.SetArguments(argc, argv);
    launcher.SetApplicationFile("App.xaml");
    return launcher.Run();
}

启动器(Launcher)

启动器是你创建的第一个实例。它负责应用程序初始化和主消息循环。它还提供了一些重要的可重写功能:

  • RegisterComponents:用于在组件工厂中注册类。需要在XAML实例化的每个扩展类都需要在此处注册,如扩展NoesisGUI教程中所述。对于框架,您至少需要注册ApplicationWindow类。
  • GetXamlProviderGetFontProviderGetTextureProvider:用于自定义如何加载资源。您可以按照“ 自定义资源加载”教程中的说明安装XAML,字体和纹理的自定义处理程序。
class AppLauncher final: public ApplicationLauncher
{
private:
    void RegisterComponents() const override
    {
        NsRegisterComponent<RssReader::App>();
        NsRegisterComponent<RssReader::MainWindow>();
    }

    Ptr<XamlProvider> GetXamlProvider() const override
    {
        EmbeddedXaml xamls[] =
        {
            { "App.xaml", App_xaml, sizeof(App_xaml) },
            { "MainWindow.xaml", MainWindow_xaml, sizeof(MainWindow_xaml) }
        };

        return *new EmbeddedXamlProvider(xamls, NS_COUNTOF(xamls));
    }

    Ptr<FontProvider> GetFontProvider() const override
    {
        EmbeddedFont fonts[] =
        {
            { "", Roboto_Regular_ttf, sizeof(Roboto_Regular_ttf) },
            { "", Roboto_Bold_ttf, sizeof(Roboto_Bold_ttf) }
        };

        return *new EmbeddedFontProvider(fonts, NS_COUNTOF(fonts));
    }
};

注意
在框架中找到的Embedded *系列资源提供程序使您可以将资源嵌入可执行文件中。每次编辑项目中包含的资源时,都会使用“ bin2h”将其自动转换为头文件,bin2h是随每个示例一起分发的工具。例如,每次您触摸“ Roboto-Regular.ttf”时,将自动重新生成“ Roboto-Regular.ttf.bin.h”。其余资源相同。

应用

应用Application类直接对应于WPF应用程序类。每个应用程序都提供从Application基类继承的自己的实现。

namespace RssReader
{
    class App final: public Application
    {
        NS_IMPLEMENT_INLINE_REFLECTION(App, Application)
        {
            NsMeta<TypeId>("RssReader.App");
        }
    };
}

应用程序的主要目的是提供全局资源字典并设置主窗口StartupUri

应用程式

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             x:Class="RssReader.App">

  <Application.Resources>
    <SolidColorBrush x:Key="Background0" Color="#FF2F3F4F" />
    <SolidColorBrush x:Key="Background1" Color="SlateGray" />
    <SolidColorBrush x:Key="Foreground0" Color="White" />
    <SolidColorBrush x:Key="Foreground1" Color="SkyBlue" />
    <SolidColorBrush x:Key="Foreground2" Color="Black" />
    <SolidColorBrush x:Key="Border" Color="LightSlateGray" />
    <FontFamily x:Key="DefaultFont">./#Roboto</FontFamily>
  </Application.Resources>

</Application>

窗口Window

窗口Window类模仿WPF窗口类。它是一个在操作系统窗口内显示其内容的容器。诸如TitleResizeModeWindowStyleWidthHeight的公共属性控制本机窗口的外观

MainWindow.xaml

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="NoesisGUI - RSS Reader" Width="487" Height="630" ResizeMode="NoResize"
   Background="{StaticResource Background0}"
   Foreground="{StaticResource Foreground0}"
   FontFamily="{StaticResource DefaultFont}"
   x:Class="RssReader.MainWindow">

  <Viewbox>
    <DockPanel Background="{StaticResource Background0}" LastChildFill="True"
               KeyboardNavigation.TabNavigation="Contained"
               KeyboardNavigation.DirectionalNavigation="Contained" Width="325" Height="420">
      <TextBlock DockPanel.Dock="Top" Text="RSS Reader" FontSize="32" FontWeight="Bold"
                 TextAlignment="Center" Margin="0,10,0,0"/>
      <Border DockPanel.Dock="Top" Background="{StaticResource Background1}"
              BorderBrush="{StaticResource Border}" BorderThickness="1" CornerRadius="2"
              Margin="10" Padding="15,5">
        <Grid>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
          </Grid.ColumnDefinitions>
          <TextBlock Grid.Column="0" Text="URL: " VerticalAlignment="Center"/>
          <TextBox x:Name="Address" Grid.Column="1" Text="http://www.metacritic.com/"/>
          <Button x:Name="GoTo" Grid.Column="2" Content="Go" Click="OnGoToClicked" Margin="2,0,0,0"/>
        </Grid>
      </Border>
      <Grid DockPanel.Dock="Bottom" Margin="10">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.Resources>
          <Style TargetType="Button">
            <Setter Property="BorderBrush" Value="{StaticResource Background1}"/>
          </Style>
        </Grid.Resources>
        <Button x:Name="Prev" Grid.Column="0" Content="Prev" Click="OnPrevClicked"/>
        <Button x:Name="Next" Grid.Column="1" Content="Next" Click="OnNextClicked"/>
      </Grid>
      <Border Background="{StaticResource Background1}" BorderBrush="{StaticResource Border}"
              BorderThickness="1" CornerRadius="2" Margin="10,0" Padding="5">
        <Grid x:Name="ContentPanel" Margin="10,0">
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
          </Grid.RowDefinitions>
          <TextBlock x:Name="EntryTitle" Grid.Row="0" FontSize="20" FontWeight="Bold"
                     Foreground="{StaticResource Foreground1}" TextAlignment="Center" Margin="0,5,0,5"/>
          <ScrollViewer Grid.Row="1"  Margin="0,10" Focusable="False"
                        HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
            <TextBlock x:Name="EntryDesc" TextWrapping="Wrap" Margin="10,0"
                       Foreground="{StaticResource Foreground2}" FontSize="14"/>
          </ScrollViewer>
        </Grid>
      </Border>
    </DockPanel>
  </Viewbox>

</Window>

通常将窗口基类扩展为实现代码隐藏code-behind功能。

namespace RssReader
{
    class MainWindow final: public Window
    {
    public:
        MainWindow(): _index(0)
        {
            InitializeComponent();

            _title = FindName<TextBlock>("EntryTitle");
            _title->SetText(gTitles[0]);

            _desc = FindName<TextBlock>("EntryDesc");
            _desc->SetText(gBodies[0]);
        }

    private:
        void InitializeComponent()
        {
            Noesis::GUI::LoadComponent(this, "MainWindow.xaml");
        }

        bool ConnectEvent(BaseComponent* source, const char* event, const char* handler) override
        {
            NS_CONNECT_EVENT(Button, Click, OnGoToClicked);
            NS_CONNECT_EVENT(Button, Click, OnPrevClicked);
            NS_CONNECT_EVENT(Button, Click, OnNextClicked);
            return false;
        }

        void OnGoToClicked(BaseComponent* /*sender*/, const RoutedEventArgs& /*e*/)
        {
        }

        void OnPrevClicked(BaseComponent* /*sender*/, const RoutedEventArgs& /*e*/)
        {
            _index = _index == 0 ? 2 : _index - 1;
            _title->SetText(gTitles[_index]);
            _desc->SetText(gBodies[_index]);
        }

        void OnNextClicked(BaseComponent* /*sender*/, const RoutedEventArgs& /*e*/)
        {
            _index = _index == 2 ? 0 : _index + 1;
            _title->SetText(gTitles[_index]);
            _desc->SetText(gBodies[_index]);
        }

    private:
        int _index;
        TextBlock* _title;
        TextBlock* _desc;

        NS_IMPLEMENT_INLINE_REFLECTION(MainWindow, Window)
        {
            NsMeta<TypeId>("RssReader.MainWindow");
        }
    };
}

命令行开关

使用应用程序框架创建的所有应用程序都支持以下命令行开关:

  • --render [D3D11 | GL | Metal | ...]:覆盖默认渲染器。
  • --vsync [0 | 1]:禁用垂直同步。
  • --samples N:启用多重采样抗锯齿(MSAA),默认情况下处于关闭状态。
  • --linear:用于切换到线性渲染,默认情况下,渲染发生在gamma空间中。
  • --log_binding:使用数据绑定时增加日志记录的详细程度。

快捷键

以下快捷方式使调试功能可以检查应用程序的性能:

  • CTRL + W:渲染三角形时切换线框模式。
  • CTRL + B:提交给GPU的每个批处理都具有唯一的纯色。
  • CTRL + O:使用混合图层显示像素覆盖。每种类型的三角形使用不同的颜色:绿色表示正常,红色表示不透明,蓝色表示剪贴蒙版。
  • CTRL + P:每个基本抗锯齿拉伸几何图形的轮廓并将其平滑。未启用GPU多重采样时很有用。
  • CTRL + F:显示性能统计信息面板。

相关文章

网友评论

    本文标题:C++教程5:应用框架

    本文链接:https://www.haomeiwen.com/subject/ysolshtx.html