UE4版本:4.24.3源码编译

Windows10 + VS2019开发环境

在先前分享的基础上,现在来梳理下App启动时默认窗口的创建流程,以及相关的类、对象之间的抽象层级:

  1. 纯C++工程配置
  2. Step By Step展示SImage控件的简单使用
  3. UE4源码,App启动基本流程
1、窗口创建流程

Q:App启动过程中,窗口是何时创建的?
Win32 API中创建窗口使用CreateWindowXX系列函数,VS中全局搜索一下CreateWindow,如下图是想要找的地方

全局搜索时不要勾选【Match whole world】

                图1:全局搜索CreateWindow系列函数的调用

图一中源码路径:Source/Runtime/ApplicationCore/Private/Windows/WindowsWindow.cpp是需要找的调用;

在项目工程属性中:Debugging->Command Arguments中,添加-game参数:

VS中运行后,以Game模式启动,而非启动编辑器界面;

可以排除Editor相关的函数调用,模拟最终游戏的启动和运行流程;

VS中断点调试,拿到的调用堆栈如下图:

                 图2:窗口创建时的调用堆栈

从图2中可以看到,CreateWindowEx函数的调用过程中涉及到了下面几个类:

  • FEngineLoop
  • FPreLoadScreenManager
  • UGameEngine
  • FSlateApplication
  • FWindowsApplication
  • FWindowsWindow

定位到UGameEngine::CreateGameWindows()函数定义处,该函数创建的对象类型其实是SWindow;

// SNew宏创建一个SWindow实例(SWindow是SWidget派生类,参看前面的SImage用法)

TSharedRef<SWindow> Window = SNew(SWindow)

该SWindow实例被添加到FSlateApplication类中,被保存在SlateWindows这个数组中:定位到FSlateApplication::AddWindow()函数处可以查看

FSlateApplication::Get().AddWindow( Window, bShowImmediately );

FSlateApplication::AddWindow(...)函数内部,除了保存SWindow实例外,还会调用FSlateApplication::MakeWindow(...)创建一个FGenericWindow对象;
稍微追一下代码,会发现:

  • 该FGenericWindow对象的实际类型是FWindowsWindow;
  • FSlateApplication::MakeWindow(...)函数中出现的那个PlatformApplication实例,其类型为FWindowsApplication

关于PlatformApplication这个实例,参考FSlateApplication::Create(...)函数;

回到UGameEngine::CreateGameWindow()函数定义处:

SWindow实例会调用ShowWindow()函数,函数内部会调用到FWindowsWindow实例的Show()方法:该方法内部针对先前CreateWindowEx(...)函数创建的Win32窗口句柄做显示动作;

这部分分析过程中,会涉及到下面这些新出现的类:

  • FGenericWindow
  • FGenericApplication
  • FGenericAcpplicationMisc
  • FWindowsPlatformApplicationMisc
  • FPlatformApplicationMisc 该类是一个typedef,指向具体平台的FXXXPlatformApplicationMisc类
  • FSlateApplicationBase

以上整个UGameEngine::CreateGameWindow(...)函数调用的过程,就是窗口创建的过程;

2、类、对象的分析

类FSlateApplication继承自FSlateApplicationBase类;单例形式,管理并驱动整个Slate SWidget的渲染和事件派发等重要任务;

SWindow类抽象并封装平台Window对象;

FGenericApplication、FGenericWindow类是多平台对应类的基类,具体平台的逻辑操作在派生类中执行,实现各平台Api的封装;

3、总结、扩展

这次主要是追一下UE4引擎源码中,在Windows平台下,最基础的窗口是如何创建的;

对于其中涉及到的一些类和彼此之间的抽象关系做一个粗粒度的感性认识;

对于游戏引擎,各图形单元的渲染使用DirectX、OpenGL、Metal等底层硬件加速Api,并不依赖平台自身开发框架提供的Native控件;

窗口创建后,一般都会需要一个Content上下文初始化的工作,这块涉及到具体游戏引擎的渲染模块,以后有机会在来分享;

起始的窗口大小:

在项目工程属性中:Debugging->Command Arguments中,添加ResX=1280 ResY=720参数

ResX=1280 ResY=720参数设定窗口的启动大小:相关的代码可以参考:

static void UGameEngine::ConditionallyOverrideSettings(...);

static void UGameEngine::DetermineGameWindowResolution(...);

另外:上面全局搜索CreateWindo函数调用时,搜索结果中有出现一个WindowsPlatformSplash.cpp文件;
当中也有调用到CreateWindowEx(...)函数
这里其实就是引擎、或者VS中直接带-game参数启动时那个黑色的类似一个Loading界面的窗口
对应的图片资源在引擎Engine\Content\Splash目录下,有兴趣可以翻一下WindowsPlatformSplash.cpp源码

UE4之Slate:App默认窗口的创建流程的更多相关文章

  1. UE4之Slate: App启动与最外层Runtime结构

    UE4版本:4.24.3源码编译: Windows10 + VS开发环境 Slate为一套自定义UI框架,其绘制直接依赖的是OpenGL.DirectX这样的硬件加速AIP;可以理解为一个单独的2D图 ...

  2. Cinder-2 窗口的创建过程

    通过TinderBox生成的代码很简单,整个代码如下: #include "cinder/app/AppNative.h" #include "cinder/gl/gl. ...

  3. 一个先进的App框架:使用Ionic创建一个简单的APP

    原文  http://www.w3cplus.com/mobile/building-simple-app-using-ionic-advanced-html5-mobile-app-framewor ...

  4. day99:MoFang:Flask-JSONRPC提供RPC接口&在APP进行窗口页面操作(窗口-帧-帧组)

    目录 1.服务端基于Flask-JSONRPC提供RPC接口 1.Flask-JSONRPC简介 2.安装Flask-JSONRPC模块 3.快速实现一个测试的RPC接口 4.移动端访问测试接口 2. ...

  5. UE4之Slate: SImage

    概述 距离上次记录<UE4之Slate:纯C++工程配置>后已经好长时间了: 这个随笔来记录并分享一下SImage控件的使用,以在屏幕上显示一张图片: 目标 通过SImage控件的展示,学 ...

  6. uCGUI窗口的创建过程分析

    一.相关结构体和变量 窗口管理结构体 /* 窗口管理结构体 共30个字节 */ struct WM_Obj { GUI_RECT Rect; //窗口尺寸(x0,y0,x1,y1) 8个字节 GUI_ ...

  7. win32 api Windows窗口的创建

    windows窗口的创建有以下几个步骤: 1.创建注册窗口类 2.创建窗口句柄 3.显示更新窗口 4.消息循环 1.创建注册窗口类 所谓创建窗口类就是定义一个WNDCLASS类对象,并将该对象进行初始 ...

  8. vc++窗口的创建过程(MFC消息机制的经典文章)

    一.什么是窗口类  在Windows中运行的程序,大多数都有一个或几个可以看得见的窗口,而在这些窗口被创建起来之前,操作系统怎么知道该怎样创建该窗口,以及用户操作该窗口的各种消息交给谁处理呢?所以VC ...

  9. Windows窗口的创建

    Windows窗口创建的基本代码: #include <Windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); i ...

随机推荐

  1. 计算机网络之应用层概述(C/S模型与p2p模型)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105582318 学习课程:<2019王道考研计算机网络> 学习目的 ...

  2. (转载)linux chmod命令用法

    chmod----改变一个或多个文件的存取模式(mode) chmod [options] mode files   只能文件属主或特权用户才能使用该功能来改变文件存取模式.mode可以是数字形式(八 ...

  3. filter tools

    // 过滤商品分类 Vue.filter("cateFilter", (data) => {   let tmp = ["一级分类", "二级分 ...

  4. Docker安装配置Tomcat

    1.使用docker pull tomcat下载镜像(不加tag则是下载最新版本) 2.运行容器(-d 后台运行:-p 指定端口映射),接的是镜像ID 3.进入容器执行命令,接的是容器ID 4.宿主机 ...

  5. 使用Visual Studio 2019将ASP.NET Core发布为linux-arm64程序

    前言 前段时间入手了一台树莓派4B,一直闲置未使用,最近工作需要,要在上面跑下.NET Core程序,由于树莓派4B使用的是ARM架构,并且支持64位操作系统,为了充分发挥树莓派性能,我的这台树莓派安 ...

  6. 这一篇 K8S(Kubernetes)集群部署 我觉得还可以!!!

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 国内安装K8S的四种途径 Kubernetes 的安装其实并不复杂,因为Kubernetes 属 ...

  7. MySQL新建用户并赋予权限:解决命令行与Navicat展示数据库不一致问题

    1.创建新用户 'xiaoxiao'密码'123456' mysql> CREATE USER 'xiaoxiao'@'localhost' IDENTIFIED BY '123456'; 2. ...

  8. let that = this用法解析

    这种情况就是在一个代码片段里this有可能代表不同的对象,而编码者希望this代表最初的对象

  9. logstash写入kakfa数据丢失的问题

    metricbeat采集系统指标,发送到logstash,再写入kafka,发现kafka中的数据不完整,只有某一个指标, 查找原因发现是logstash配置编码问题,如下: input { beat ...

  10. 大白话讲解Mybatis的plugin(Interceptor)的使用

    mybatis提供了一个入口,可以让你在语句执行过程中的某一点进行拦截调用.官方称之为插件plugin,但是在使用的时候需要实现Interceptor接口,默认情况下,MyBatis 允许使用插件来拦 ...