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++ Python

    集合栈 牛客网 程序员面试金典 C++ Python 题目描述 请实现一种数据结构SetOfStacks,由多个栈组成,其中每个栈的大小为size,当前一个栈填满时,新建一个栈.该数据结构应支持与普通 ...

  2. Codeforces Global Round 16题解

    E. Buds Re-hanging 对于这个题该开始还是没想法的,但这显然是个思维题,还是要多多动手推样例,实践一下. 简化题意:给定一个有根树,规定某个点为树干,当且仅当这个点不是根,且这个点至少 ...

  3. vscode + vim 全键盘操作高效搭配方案

    基础知识 vscode-vim vscode-vim是一款vim模拟器,它将vim的大部分功能都集成在了vscode中,你可以将它理解为一个嵌套在vscode中的vim. 由于该vim是被模拟的的非真 ...

  4. cpu内核态与用户态

    1.操作系统需要两种CPU状态 内核态(Kernel Mode):运行操作系统程序,操作硬件 用户态(User Mode):运行用户程序 2.指令划分 特权指令:只能由操作系统使用.用户程序不能使用的 ...

  5. Linux 权限控制

    权限管理概述 为什么要进行权限管理? 因为在生产服务器上,如果要让普通用户登录,就要给他分配合理的权限,在服务器上需要为用户严格定义权限等级,否则如果所有人都是roσt权限,权限过高容易导致岀现误操作 ...

  6. go的常用数据类型-持续优化篇

    p.p1 { margin: 0; font: 12px "Helvetica Neue"; color: rgba(69, 69, 69, 1) } p.p2 { margin: ...

  7. tabulate

    ValueError: headers for a list of dicts is not a dict or a keyword from: https://bitbucket.org/astan ...

  8. [第二章]c++学习笔记3(构造函数)

    成员函数的一种 (1)名字与类名相同,可以有参数,不能有返回值(void也不行) (2)作用是对对象初始化,如给成员变量赋初值 (3)如果定义类时没写构造函数,则编译器生成一个默认的无参数的构造函数( ...

  9. 我個人喜歡的一些Ubuntu的相關配置

    1.vim vim安裝: sudo apt-get install vim-gtk vim美化:刚安装的VIM,可能界面并不是十分友好,我们可以更改vim的配置文件,按照我们的需求去修改它.在命令行下 ...

  10. [atARC114F]Permutation Division

    由于是排列,即任意两个数字都各不相同,因此字典序最大的$q_{i}$就是将每一段的第一个数从大到小排序 接下来,考虑第一个元素,也就是每一段开头的最大值,分类讨论: 1.当$p_{1}\le k$时, ...