一个GUI结构学习总结:
一. GUI在游戏中的显示流程
1. 树形结构
在GUI结构中,所有控件遵循树形结构,游戏中的所有窗口都挂接到了root节点下。
每个窗口中,通过语句
CreateFromRes(LoginWnd_Main.c_str(),g_FBClient_Global.m_pRootWnd)
把各个窗口挂接到根窗口下。
2. 创建g_FBClient_Global.m_pRootWnd
在FBClient_Global.cpp中通过
m_pRootWnd->CreateRootWnd(m_pImeHandler,rectClient,&m_Device,&m_Manager,InfacePath.c_str());创建根窗口。
3. UI的绘制
4. 关于UI绘制的补充
UI的控件(button,editbox等)都是自己绘制,但又的窗口需要特殊需求,比如新手卡礼包,当玩家还没有输入新手礼包卡号的时候,要求“确定”按钮灰化(即玩家不可以点击此按钮),这个特殊的需求就需要在具体的新手卡礼包窗口(CNewPlayerCard.h和CNewPlayerCard.cpp)中实现。这个窗口中也有virtual voidOnUpdateDataBeforeDraw(),在里面添加具体实现就可以完成特殊的需求。
二. GUI消息响应结构
下面对于上面第一个树形结构进行说明,消息响应即鼠标键盘等消息的响应。
1. 用根窗口接收消息
g_FBClient_Global.m_pRootWnd->RecieveMsg(message,wParam,lParam)
根窗口接受要处理的消息,其他窗口调用无效
2. 每个CArkWnd窗口中保存了一个tagWndData结构
此结构中有窗口管理器CArkGUIManage,在上面的函数中调用
pGUI->WndProc(message,wParam,lParam)
在这个函数中分别处理鼠标和键盘的消息
HRESULTCArkMouseMsgProc::ProcessMsg(uint32 message, WPARAM wParam, LPARAM lParam)
HRESULTCArkKeyMsgProc::ProcessMsg(uint32 message, WPARAM wParam, LPARAM lParam)
3. 在上述函数中查找最顶窗口,然后转到CArkWnd的
LRESULTCArkWnd::WndProc(uint32 message, WPARAM wParam, LPARAM lParam)
中发送操作消息给各个控件的OnLButtonDown进行处理
4. 在各个逻辑窗口中的OnChildmsg中处理
处理各个控件的逻辑,比如按下了登陆界面中的“进入游戏”,则响应EnterGame(),比如按下了商城界面的“购买”,则发送一个购买的消息给服务器进行扣钱。
下面是上述消息响应流程的图释:
三. GUI基本控件类型介绍
对应上面的这个结构图进行讲述,各个控件的自绘
1. 按钮(CArkButton.h和CArkButton.cpp)的显示
大家一定好奇当鼠标经过一颗按钮时按钮的状态如何改变,其实每个状态就是一张图,当鼠标移动到上面变成了另外一张图,点击后又换成了另外一张图。按钮自己接收了鼠标事件进行不同状态的响应。
voidCArkButton::DrawWndBackground()
{
DrawBackImage(m_pWndData->m_Enable,m_pWndData->m_Disable,
m_MouseOverImage,m_ClickDownImage,IsHeld());
}
正如上面第一条第3点提到的,此函数为在所有控件中为虚函数,不同的控件在鼠标经过,点击状态也各不相同。
复选框CArkCheckButton,进度条CArkProgress等控件,此函数都是虚函数,用于特殊的绘制
2. 编辑框闪烁线的显示
每当点击一下编辑框时,闪烁线就出现,所以在编辑框自己的OnLButtonDown中写下逻辑
3. 富文本框(CArkRichWnd)
富文本框最典型的应用是聊天框,在富文本框中的字可以变换颜色,还可以设置是否自动换行。在AddWndText(const char* str, bool nFlag, bool bDis, int32 nDis)中,每次增加文字,自动换行,滚动条随之变化。
通过CArkRichText和CArkRichTextFormat进行换行和颜色解析等功能的具体实现。
4. 内嵌IE控件
我们用的是微软的接口IWebBrowser2,把IE浏览器嵌入到窗口中。
5. 模态窗口
四. GUI特殊窗口(悬浮提示框,泡泡提示框,确定框,确定取消框,确定输入框等)
1. 悬浮提示框
属于CArkWnd的一个函数,所以所有控件可以支持悬浮提示。
富文本框之前不支持悬浮提示,是因为当富文本框不是“可剪切”属性时,不法响应鼠标移动的消息,后来添加的支持。
2. 泡泡提示框
单独实现,非控件。CInfoWndMgr。
在表中配置的泡泡提示不能提示数字等服务器传过来的值,只能配置特定的话(- -!),很坑,如果要灵活提示数字就直接申明个泡泡框窗口指针变量(CTorchbearerWnd*)。
3. 确定框,确定取消框,确定输入框
因为游戏中有很多确定框,这些框大小不一样,但是可以复用,如果每一个确定框都写一个窗口的话很傻,所以聪明的程序员就把它写成通用的了,这些框子可以根据字的多少来显示一个确定框。
在InterfaceCommon中,实现了很多可以复用确定框。补充一下InterfaceCommon中也实现了一些时间格式显示的函数。
五. GUI编辑器
1. MFC中的树形结构来管理各个逻辑窗口(登录窗口,选人窗口等)
2. 把创建的窗口属性存在脚本文件中,每次加载的时候读取脚本文件
3. GUI编辑器中绘制窗口的原理和游戏里一样。MFC中的主循环中调用根窗口的Render(),看下上面的树形图。因为MFC主窗口GUIEditorDlg是继承了CArkRootWnd,所以直接调用Render()。
4. 编辑器中的设备,画线,字体,贴图都是用了游戏中的实现。
设备:CFBGraphics_Device
画线:CFBGraphics_Line
字体:CFBGraphics_FontMgr
贴图:CFBGraphics_Sprite
在主循环中用上述的指针画出即可。