/Files/biyou007/GXUI_DEMO.rar
基于Directx9的GUI框架的设计与实现
第一章 概述
该GUI框架命名为GXUI,基于directx 9.0,比较类似于微软自己的DXUT, 其目标是基于directx 9.0构建一个完整界面库(包括框架、各类控件、动画效果、脚本创建支持),但不拘泥于directx,其底层绘制实现可以替换。GXUI属于天然的DirectUI。
将目标细分为以下几点:
1. 建立框架自己的消息循环机制,实现窗体容器管理。
2. 在第一步的基础上实现各类控件,包括button、edit、scroll、grid、chart等。
3. 实现动画效果及一些特殊效果。
4. 最终支持脚本创建。
目前为止,GXUI基本完成前3项目标,并在建立的过程中不断对整体框架进行回溯修改,也许最终GXUI达不到什么实用价值,毕竟已经有很多完善的、先进的、牛人所写的库存在,作者水平有限,不能与之相提并论。但我仍希望本系列文章能起到抛砖引玉的作用,毕竟还有很多新人对从头写到尾一个全新的界面库很感兴趣,但已有的很多库已经存于非常成熟的阶段,想深入具有较大难度,而本系列文章会尽量保证浅入深出,给予读者能接受的平滑度。事实上,有很多问题作者也未能解决,希望在此过程中能与读者一起学习,并提出有效的解决方案。
作者本人对win32真正的一些复杂的底层也并不了解,因此在构建GXUI的过程中,我秉承二点基本原则:
1. 框架内部的机制完全独立,尽量避免与win32交互,而所有必须得交互都仅限于外面的壳,该壳会调用框架。
2. 需要什么功能,再去实现该功能,因此不会一开始考虑的全全俱到。
第二章 UIUtil.h/UIUtil.cpp
该代码段提供了各种基础工具类,基础定义,directx初始化类等,具体如下:
class UIInitDX
{ ……
public:
bool InitD3D( HWND hWnd,
ULONG width, ULONG height,
bool windowed=true,
D3DDEVTYPE deviceType=D3DDEVTYPE_HAL );
bool ResetD3D( ULONG width, ULONG height );
};
该类提供directx9的初始化,InitD3D()接口的参数width和height表示缓存面大小,最好与窗口大小保持一致,否则会失真。ResetD3D()用于窗口大小改变时改变缓存面的大小。
以下仿函数均为基础功能类:
struct GetImagePointColor; // 未实现
struct GetWidth;
struct GetHeight;
struct GenRect; // NULLRECT
struct GenPoint; // NULLPOINT
struct GenSize;
struct ComparePoint;
struct CompareRect;
struct CrossRect;
void OffsetPoint;
struct IsPointInRect;
struct IsKeyDown;
下面的类为控件布局计算类:
/* 父窗口
-------------------------
| | |
| dy1 |
| | |
| -------- |
|-dx1- |子窗口 |-dx2- |
| | | |
| -------- |
| | |
| dy2 |
| | |
-------------------------
*/
struct UILayoutScale
{ ……
RECT _parentRect; // 父窗体的区域
RECT _rect; // 控件相对父窗体区域
enum zoomMode // 设置时x、y分别只能设一次
{
NO_ZOOM = 0,
MOVE_X = 1, // bit 1 dx2不变 dx1改变 控件x方向上大小不变
MOVE_Y = 2, // bit 2 dy2不变 dy1改变 控件y方向上大小不变
SIZE_X = 4, // bit 3 dx1和dx2都不变 控件x方向上大小改变
SIZE_Y = 8, // bit 4 dy1和dy2都不变 控件y方向上大小改变
SCALE_X = 16,// bit 5 dx1,dx2按比例变
SCALE_Y = 32,// bit 6 dy1,dy2按比例变
};
int _zoomModeflag; // 缩放模式
UILayoutScale( int flag=SIZE_X|SIZE_Y ); // 设置缩放模式
void CalcScale( RECT& parentRect, RECT& rect ); // 初始计算
RECT CalcNewPosRect( LONG cx, LONG cy ); // 计算新状态
};
第三章 UI2D.h/UI2D.cpp
该代码段基于directx9实现了各种2d图形的绘制接口,具体方法为采用RHW类型顶点绘制,带颜色信息,不涉及灯光、材质等。 实现基础2D图元为点、线、矩形、椭圆、图片、字体,如果这些接口用其它系统的图形接口来实现,GXUI框架将实现移植。
实现的2D这些接口具体如下:
struct UI2DPoint;
struct UI2DLine;
struct UI2DRect;
struct UI2DCircle;
struct UI2DEllipse;
struct UI2DImage; 有两种实现方式,一种直接通过文件路径载入图片,另一种方式从dll中通过ID载入图片。我们将GXUI框架所用的图片资源都封入一个GUIResource.dll,使用时从dll中载入各种图片资源。
/* 框架背景图绘制助手类:
---------------------------------
| 1 | 2 | 3|
|--------------------------------
| | | |
| 7| 9 | 8|
| | | |
|--------------------------------
| 4| 5 | 6| */
class DrawFrameHelp; 提供了框架背景图的绘制,绘制的方式主要为边框不变,中心部分大小改变,载入的方式和UI2DImage一样有两种。
class UI2DFont; 提供了字体支持。
class UI2DClipRect; 提供了绘制时的区域剪裁功能,并支持嵌套剪裁计算。
除了以上2D图形接口外,本代码包含另一个重要功能,即动画功能的实现,其设计包括一个动画基类以及动画管理类:
动画基类为纯虚基类,任何继承类均需要实现2个纯虚函数,DrawAnimateAuto()默认为空,因为如果是控件动画,其绘制在控件的自身绘制中就完成了,而不需要单独的动画绘制。
struct UIAnimateBase
{ ……
virtual bool IsRunAnimate() = 0; // 动画是否运行
virtual bool CalcAnimate() = 0;// 计算本帧动画 是否绘制
virtual void DrawAnimateAuto() {}// 动画绘制
};
动画管理类如下,其TimerHandle()在GXUI框架的消息循环中定时处理。
class UIAnimateManage
{ ……
bool TimerHandle(); // 计时器处理 返回值决定是否刷新
void AddAnimate( UIAnimateBase* pAnimateObj );
};
一个重要的动画实例就是插入符,其动画效果表现为当edit编辑框激活时插入符将在激活的位置自动闪烁,其实现如下。
class UICaret; 该类实现为单件类。并相应的提供了4个全局函数来进行操作。
void UIShowCaret( float z, int width, int height, D3DCOLOR rgb );
void UIHideCaret();
void UISetCaretPos( int x, int y );
void UIDrawCaret();
第四章 UI3D.h/UI3D.cpp
本代码段封装了部分3D相关功能、最重要的绘制功能、一些公共的动画特效,分别介绍如下。
一 部分3D相关功能
struct UICube; 提供了一个旋转的3d箱子,在绘制时会自动旋转,可用来测试GXUI框架中的UI元素实现时是否会产生无用的绘制。
struct UICamera; 设置摄像头。
二 框架绘制功能
extern UIContainer gUIContainerTop;
class UIRender : public UIAnimateManage
{ ……
// 自适应窗口大小变化
bool AutoAdjustSizeChange( ULONG width, ULONG height );
// 设置投影矩阵 设置可视柱体 映射到整个缓存面
bool SetPerspective( float aspect, float angle=D3DX_PI/2.f, float zn=1, float zf=1000 );
void Render();
};
其中Render()函数实现内容如下:
1 窗口最小化不进行render
2 清除缓存表面
3 绘制顶级容器内gUIContainerTop所有子窗体
4 绘制立方体 测试用
5 Swap the back and front buffers.
void UIRegisterAnimate( UIAnimateBase* pAnimateObj ); 该全局函数用于注册动画。
三 公共的动画特效
公共动画特效实现包括3种模式:
1 击鼓特效,选中的图片变淡放大至消失,类似击鼓时的鼓面振动。
2 hot特效,一个图片从淡变浓。
3 cool特效,和2相反。
template<class T>
class UIAnimateEffect : public UIAnimateBase
{ ……
enum
{ // 动画播放帧数
HIT_DRUM_FRAME = 10,
SET_HOT_FRAME = 9,
SET_COOL_FRAME = 9
};
public:
enum
{ // 预留前100的为自定义动画
HIT_DRUM = 100,
SET_HOT,
SET_COOL
};
void PlayAnimate( int mode, int maxFrame=0 );
};
第五章 WinShell.h/WinShell.cpp
本代码段实现了win32窗口的封装,具体如下:
class UIWinShell
{
protected:
virtual void AddUIElements() {}
public:
int RunMessageLoop();
void SetParam( HINSTANCE hInstance, UINT iconID, UINT iconSmID, std::string titleStr );
bool CreateWindowShell( int width=960, int height=640 );
};
其中虚函数AddUIElements()用于继承类添加UI元素,一个完整的GUI初始化调用过程如下:
UIWinShell gUIMainFrame;
gUIMainFrame.SetParam( hInstance, IDI_WSS, IDI_WSS, "tt" );
gUIMainFrame.CreateWindowShell();
UIInitDX::GetSingleton()->InitD3D( gUIMainFrame._hWnd, gUIMainFrame.GetWidth(), gUIMainFrame.GetHeight() );
gUIMainFrame.RunMessageLoop();
第六章 UIWinBase.h/UIWinBase.cpp