这几个月的开发工作主要是关于游戏内GUI的,业务开发之余也时常会看看客户端工程里的GUI系统这一块的代码,这里系统的总结下。

一、GUI树形结构

 

  在GUI中所有的控件都遵循树形结构:



  在客户端初始化时,会创建出一个无形的,跟客户端窗口等大的root窗口:g_FBClient_Global.m_pRootWnd。在游戏中添加的窗口,一般都挂载在root窗口下。要在游戏中新增一个窗口,当在GUI编辑器中创建好了窗口资源后,代码中创建该窗口资源的的方式一般是在对应的类的构造函数中使用:CreateFromRes(strWndResourceName, g_FBClient_Global.m_pRootWnd)。第一个参数是在编辑器中对应窗口资源的名称;第二个为要挂载的父窗口,如前面所述,这里一般都是挂载在根窗口下。该方法成功执行后,该窗口及窗口下的所有子控件便都创建出来了并且都是默认显示的。(关于GUI编辑器的介绍及使用,这个是内部资料了,见/src/Tools/ArkGUIEditor/bin/用ArkGUI创建一个窗口的步骤.doc)

  GUI的绘制时,是在游戏主循环中调用m_pRootWnd->Render(),从根窗口自顶向下地依此树形结构递归地显示绘制。游戏退出时对资源的回收,也是如此进行的(所以在窗口中创建的控件,如果在创建时挂载在了该窗口下的话,都无需自己手动释放)。

二、关于CArkWnd类

  class CArkWnd;是所有窗口和控件的基类。其中绝大部分为虚方法,包括窗口生命周期函数如OnCreated()、OnDestroy()、OnUpdateDataBeforeDraw()等;响应消息的一些函数如OnMouseWheel()、OnChildmsg()以及设置窗口属性功能的函数如EnableWnd()、SetFontSize()、SetWndText()等。

  一个窗口的生命周期大致可以表示如下:



一些常用的控件:

  1. 按钮类

      像按钮CArkButton、复选框CArkCheckoutButton等的显示,是在GUI编辑器中设置了一个按钮的各个状态的贴图包括点击、鼠标经过、禁用等状态。 按钮自己接收到鼠标事件进行不同状态的响应,在重写的虚函数DrawWndBackground()中实现:

    void CArkButton::DrawWndBackground()
    {
    DrawBackImage(m_pWndData->m_Enable,m_pWndData->m_Disable,
    m_MouseOverImage,m_ClickDownImage,IsHeld());// 传入各个状态的图片链表
    }
  2. 富文本框

      游戏内大部分显示文本的地方都是使用的富文本控件,最典型的像任务描述面板和聊天面板。在富文本框中的文字可以设置字体风格颜色及换行。

      通过CArkRichText和CArkRichTextFormat进行换行和颜色解析等功能的具体实现。(RichWnd格式化文字说明(内部网址):http://192.168.1.252:8080/pages/viewpage.action?pageId=9110273)

  3. 其他常用的控件还有诸如文本编辑框CArkEdit、泡泡提示框CTorchbearerWnd、确认框/确认取消框CRichMsgBox等等。

三、消息响应

  一个消息响应流程大致如下:

  由根窗口接收到消息:

  g_FBClient_Global.m_pRootWnd->ReceiveMsg(message, wParam, lParam);

  再由CArkWnd类中的窗口管理器CArkGUIManage,调用:pGUI->WndProc(message,wParam,lParam);

  在这个函数中分别处理鼠标消息和键盘消息:

  CArkMouseMsgProc::ProcessMsg(uint32 message, WPARAM wParam, LPARAM lParam)

  CArkKeyMsgProc::ProcessMsg(uint32 message, WPARAM wParam, LPARAM lParam)

  在上面的处理函数中,会找到最顶层的CArkWnd窗口,也就是我们在界面上实际操作的控件。然后调用这个CArkWnd的方法:

  CArkWnd::WndProc(uint32 message, WPARAM wParam, LPARAM lParam)

  在WndProc函数中,根据消息类型执行对应的处理函数;假设我们是点击了某个按钮,那么根据消息为点击事件,就执行虚方法OnLButtonDown()。那么实际就是由按钮类CarkButton的OnLButtonDown函数执行,在里面做一些特殊操作例如播放该按钮被点击时的特效。

  在平时GUI的开发中最主要接触的是这个OnChildMsg函数。在自己编写的窗口中,由这个函数的pChild和uMsgID参数得到子控件名称和消息类型,就能确定在界面上进行了什么操作,然后做后续的业务逻辑;比如在商城点击了“购买”按钮,那么当GenWndName(pChild)== ”BuyBtn”&& uMsgID==BUTTON_CLICK时就响应BuyItem()函数发消息给服务器。

  大致流程还可以看下面这张图:

客户端GUI结构学习总结的更多相关文章

  1. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  2. 机器学习&数据挖掘笔记_24(PGM练习八:结构学习)

    前言: 本次实验包含了2部分:贝叶斯模型参数的学习以及贝叶斯模型结构的学习,在前面的博文PGM练习七:CRF中参数的学习 中我们已经知道怎样学习马尔科夫模型(CRF)的参数,那个实验采用的是优化方法, ...

  3. Linux 目录结构学习与简析 Part2

    linux目录结构学习与简析 by:授客 QQ:1033553122 ---------------接Part 1-------------- #1.查看CPU信息 #cat /proc/cpuinf ...

  4. Linux 目录结构学习与简析 Part1

    linux目录结构学习与简析 by:授客 QQ:1033553122 说明: /             linux系统目录树的起点 =============== /bin      User Bi ...

  5. C++ GUI Qt4学习笔记01

    C++ GUI Qt4学习笔记01   qtc++signalmakefile文档平台 这一章介绍了如何把基本的C++只是与Qt所提供的功能组合起来创建一些简单的图形用户界面应用程序. 引入两个重要概 ...

  6. C++ GUI Qt4学习笔记03

    C++ GUI Qt4学习笔记03   qtc++spreadsheet文档工具resources 本章介绍创建Spreadsheet应用程序的主窗口 1.子类化QMainWindow 通过子类化QM ...

  7. C++ GUI Qt4学习笔记08

    C++ GUI Qt4学习笔记08   qtc++signal图形引擎文档 本章介绍Qt的二维图形引擎,Qt的二维图形引擎是基于QPainter类的.<span style="colo ...

  8. C++ GUI Qt4学习笔记09

    C++ GUI Qt4学习笔记09   qtc++ 本章介绍Qt中的拖放 拖放是一个应用程序内或者多个应用程序之间传递信息的一种直观的现代操作方式.除了剪贴板提供支持外,通常它还提供数据移动和复制的功 ...

  9. C++ GUI Qt4学习笔记05

    C++ GUI Qt4学习笔记05   qtc++正则表达式 QIntValidator           --  只让用户输入整数 QDoubleValidator     --  只让用户输入浮 ...

随机推荐

  1. 前端面试题1(HTML篇)

    HTML 语义化 HTML标签的语义化是指:通过使用包含语义的标签(如h1-h6)恰当地表示文档结构 css命名的语义化是指:为html标签添加有意义的class 为什么需要语义化: 去掉样式后页面呈 ...

  2. Git关联JIRA的issue

    指导文章 http://www.51testing.com/html/30/n-3724930.html http://{$host_url}/help/user/project/integratio ...

  3. 洛谷 P4827 [国家集训队] Crash 的文明世界

    题目描述 ​ 给你一棵 n 个点的树,对于树上的每个节点 i,求 \(\sum_{j=1}^ndis(i,j)^k\).其中 \(dis(i,j)\) 为两点在树上的距离. 输入格式 ​ 第一行两个整 ...

  4. 【leetcode】778. Swim in Rising Water

    题目如下: 解题思路:本题题干中提到了一个非常重要的前提:"You can swim infinite distance in zero time",同时也给了一个干扰条件,那就是 ...

  5. [CF846A]Curriculum Vitae题解

    枚举一个点,假设它一定符合条件,据此珂以\(O(n)\)算出要删去几个点 于是就\(O(n^2)\)解决了,貌似加一个前缀和可以在\(O(n)\)的时间复杂度内解决本问题,但对于这个数据范围来说\(O ...

  6. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

  7. 笨办法学Python(learn python the hard way)--练习程序1-10

    下面是当初看这本书时按照书中的代码做的练习,一行一行敲下来的,都已经试运行过,没有错误(基于python3),练习1-练习10 #ex1.py 1 #print("Hello world!& ...

  8. 问候 UEditor 的大爷

    记录该日志的时间是2015年2月1日. 先给出 UEditor 项目的首页,它是一款由百度开发的开源富文本编辑器,关于它的介绍,大家可以查看百度百科. UEditor - 首页http://uedit ...

  9. linux 统计代码行数

    列出目录下所有文件(仅有文件名):ls -laR 列出目录下所有文件名称find . * 统计当前目录下全部代码行数find . * | xargs wc -l 统计当前目录下java文件行数,去除空 ...

  10. Jenkins使用五:创建部署任务

    创建部署任务 选择运行节点 选择使用shell # 如果是持续进程,这里最好加一个kill进程的命令 判断如果/root/production目录存在,就删除if [ -d /root/product ...