关于hge gui的资料似乎很少,刚好我又想用到hge的滚动条,于是就来就随便扯一下hge的滚动条。
让我们先来分析一下它的实现代码吧。
/*
**以下为声明
** hgeGUISlider
*/
BARRELATIVE
//这些是滚动条的三种模式,顾名思义咯。
//bar,类似安装程序的进度槽,直接让你拉
//barrelative和bar差不多,但是只能从中间开始拉到左边或右边尽头
//以上两个bar都是用拉伸纹理实现的,所以效果很多时候不好....
//slider就是滚动条游标啦
#define HGESLIDER_BAR 0
#define HGESLIDER_BARRELATIVE 1
#define HGESLIDER_SLIDER 2
class hgeGUISlider : public hgeGUIObject
{
public:
hgeGUISlider(int id, float x, float y, float w, float h, HTEXTURE tex, float tx, float ty, float sw, float sh, bool vertical=false);
virtual ~hgeGUISlider();
void SetMode(float _fMin, float _fMax, int _mode) { fMin=_fMin; fMax=_fMax; mode=_mode; }
void SetValue(float _fVal);
float GetValue() const { return fVal; }//获取滚动条的数值
virtual void Render();
virtual bool MouseMove(float x, float y);
virtual bool MouseLButton(bool bDown);
private://此处源代码被声明为private,如果想要用于被继承,应该改成protected
bool bPressed;
bool bVertical;
int mode;
float fMin, fMax, fVal;
float sl_w, sl_h;
hgeSprite *sprSlider;
};
/*
**以下为实现
** hgeGUISlider
*/
hgeGUISlider::hgeGUISlider(int _id, float x, float y, float w, float h, HTEXTURE tex, float tx, float ty, float sw, float sh, bool vertical)
{
//初始化一些父类的数据
id=_id;
bStatic=false;
bVisible=true;
bEnabled=true;
bPressed=false;
bVertical=vertical;//该滚动条是否垂直,不是则以水平方式表示
rect.Set(x, y, x+w, y+h);//该rect既为控件在窗口内的响应范围。
mode=HGESLIDER_BAR;
fMin=0; fMax=100; fVal=50//定义滚动条最低时,最高时,初始化时的数值;
sl_w=sw; sl_h=sh;//只在slider模式中有用,表示滚动条游标的宽和高
sprSlider=new hgeSprite(tex, tx, ty, sw, sh);//如果是在slider模式,这就是代表游标的精灵,如果在另两个bar模式,就是代表进度的精灵
}
hgeGUISlider::~hgeGUISlider()
{
if(sprSlider) delete sprSlider;
}
void hgeGUISlider::SetValue(float _fVal)//设置滚动条的数值
{
if(_fVal<fMin) fVal=fMin;
else if(_fVal>fMax) fVal=fMax;
else fVal=_fVal;
}
void hgeGUISlider::Render()
{
//没什么好说,就是根据进度条(fval)的值和控件响应区域(rect)来画出不同的sprSlider
float xx, yy;
float x1,y1,x2,y2;
xx=rect.x1+(rect.x2-rect.x1)*(fVal-fMin)/(fMax-fMin);
yy=rect.y1+(rect.y2-rect.y1)*(fVal-fMin)/(fMax-fMin);
if(bVertical)
switch(mode)
{
case HGESLIDER_BAR: x1=rect.x1; y1=rect.y1; x2=rect.x2; y2=yy; break;
case HGESLIDER_BARRELATIVE: x1=rect.x1; y1=(rect.y1+rect.y2)/2; x2=rect.x2; y2=yy; break;
case HGESLIDER_SLIDER: x1=(rect.x1+rect.x2-sl_w)/2; y1=yy-sl_h/2; x2=(rect.x1+rect.x2+sl_w)/2; y2=yy+sl_h/2; break;
}
else
switch(mode)
{
case HGESLIDER_BAR: x1=rect.x1; y1=rect.y1; x2=xx; y2=rect.y2; break;
case HGESLIDER_BARRELATIVE: x1=(rect.x1+rect.x2)/2; y1=rect.y1; x2=xx; y2=rect.y2; break;
case HGESLIDER_SLIDER: x1=xx-sl_w/2; y1=(rect.y1+rect.y2-sl_h)/2; x2=xx+sl_w/2; y2=(rect.y1+rect.y2+sl_h)/2; break;
}
sprSlider->RenderStretch(x1, y1, x2, y2);
}
bool hgeGUISlider::MouseLButton(bool bDown)
{
//如果控件响应区域内有被摁住,做下标记
bPressed=bDown;
return false;
}
bool hgeGUISlider::MouseMove(float x, float y)
{
//这个就是实现游标/进度条移动的代码了,只有鼠标摁下时移动才会执行。
if(bPressed)
{
if(bVertical)
{
if(y>rect.y2-rect.y1) y=rect.y2-rect.y1;
if(y<0) y=0;
fVal=fMin+(fMax-fMin)*y/(rect.y2-rect.y1);
}
else
{
if(x>rect.x2-rect.x1) x=rect.x2-rect.x1;
if(x<0) x=0;
fVal=fMin+(fMax-fMin)*x/(rect.x2-rect.x1);
}
return true;
}
return false;
} 怎么样,代码很简单吧?但是因为太简单了,所以很多场合并不适用,比如silder模式。我还想要鼠标覆盖游标后,游标图片改变啊,我还想游标的后面有个进度条来提示我游标的移动范围啊!
如果你想重用这份代码,那么你可以通过继承hgeGUISlider来实现。可是这货竟然用private保护了几个关键的数据,那么只好霸王硬上弓,把private改成protected了,至少这只是修改一下头文件,不用重新编译hge的代码,下面给出这么做的一个实例,你可以通过鼠标,键盘的方向键来移动游标。
PS:这次使用到的贴图资源我也顺便给出吧:)
/*
** base on hge_tut01 - Minimal HGE application
*/
#include "..\..\include\hge.h"
#include "..\..\include\hgefont.h"
#include "..\..\include\hgeguictrls.h"
HGE *hge = 0;
/////////////////////////////////////////////////////////////////////////
class MySlider:public hgeGUISlider
{
public:
MySlider( int id, float x, float y):
hgeGUISlider(id,x,y,0,0,0,0,0,0,0)
{
m_tex_usl = hge->Texture_Load( "Dummy.png");
m_tex_ovr = hge->Texture_Load( "Dummy_over.png");
m_tex_clk = hge->Texture_Load( "Dummy_click.png");
m_tex_bak = hge->Texture_Load( "Back.png");
int w = hge->Texture_GetWidth(m_tex_bak);
int h = hge->Texture_GetHeight(m_tex_bak);
rect.Set(x, y, x+w, y+h);
sl_w = hge->Texture_GetWidth(m_tex_usl);
sl_h = hge->Texture_GetHeight(m_tex_usl);
sprSlider->SetTexture(m_tex_usl);
sprSlider->SetTextureRect(0, 0, sl_w, sl_h);
m_sprBack = new hgeSprite(m_tex_bak, 0, 0,
hge->Texture_GetWidth(m_tex_bak),
hge->Texture_GetHeight(m_tex_bak));
hgeGUISlider::SetMode(0, 100.0f, HGESLIDER_SLIDER);
hgeGUISlider::SetValue(50.0f);
}
~MySlider()
{
hge->Texture_Free(m_tex_usl);
hge->Texture_Free(m_tex_ovr);
hge->Texture_Free(m_tex_clk);
hge->Texture_Free(m_tex_bak);
delete m_sprBack;
}
virtual void Render()
{
m_sprBack->Render(rect.x1, rect.y1);
hgeGUISlider::Render();
}
virtual void MouseOver(bool bOver)
{
bOver?
sprSlider->SetTexture(m_tex_ovr):
sprSlider->SetTexture(m_tex_usl);
}
virtual bool MouseLButton(bool bDown)
{
if(bDown)
sprSlider->SetTexture(m_tex_clk);
return hgeGUISlider::MouseLButton(bDown);
}
private:
HTEXTURE m_tex_usl;
HTEXTURE m_tex_ovr;
HTEXTURE m_tex_clk;
HTEXTURE m_tex_bak;
hgeSprite* m_sprBack;
};
/////////////////////////////////////////////////////////////////////////
hgeGUISlider *slider = 0;
hgeGUI* gui = 0;
hgeFont* fnt = 0;
int slider_id = 100;
float slider_value = 0;
bool FrameFunc()
{
float dt = hge->Timer_GetDelta();
if (hge->Input_KeyDown(HGEK_ESCAPE))
return true ;
if (hge->Input_GetKeyState(HGEK_LEFT))
{
slider_value -= 10.0f*dt;
((hgeGUISlider*)gui->GetCtrl(slider_id))->SetValue(slider_value);
}
else if (hge->Input_GetKeyState(HGEK_LEFT))
{
slider_value += 10.0f*dt;
((hgeGUISlider*)gui->GetCtrl(slider_id))->SetValue(slider_value);
}
if (hge->Input_GetKeyState(HGEK_ESCAPE)) return true ;
if(gui)
{
int id = gui->Update(hge->Timer_GetDelta());
if(id == slider_id)
slider_value = ((hgeGUISlider*)gui->GetCtrl(id))->GetValue();
}
return false;
}
bool RenderFunc()
{
hge->Gfx_Clear(0);
hge->Gfx_BeginScene();
if(gui)
gui->Render();
if(fnt)
fnt->printf(22, 130, HGETEXT_LEFT, "the value of the slider is: %.4f.", slider_value);
hge->Gfx_EndScene();
return false ;
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
hge = hgeCreate(HGE_VERSION);
hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
hge->System_SetState(HGE_RENDERFUNC, RenderFunc);
hge->System_SetState(HGE_TITLE, "HGE GUI SLIDER DEMO");
hge->System_SetState(HGE_WINDOWED, true);
hge->System_SetState(HGE_SCREENWIDTH, 400);
hge->System_SetState(HGE_SCREENHEIGHT, 300);
hge->System_SetState(HGE_HIDEMOUSE, false);
if(hge->System_Initiate())
{
gui = new hgeGUI();
slider = new MySlider(slider_id, 20, 50);
slider_value = slider->GetValue();
fnt = new hgeFont("font1.fnt" );
fnt->SetColor(0xFFFFFFFF);
gui->AddCtrl(slider);
hge->System_Start();
gui->DelCtrl(slider_id);
delete gui;
delete fnt;
}
else
MessageBox(NULL, hge->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
hge->System_Shutdown();
hge->Release();
return 0;
}
运行效果:
当然了,这个滚动条还是很挫的,你还想写更好的滚动条吗?比如说希望实现word那样,会随着内容的增加而缩放滚动条游标的大小?
那么那么,你应该自己从hgeGUIobject继承,重新写一个自己专用slider了,毕竟haaf写的那一套gui控件大都不好用,教学意义更大于实用意义呢,有了上面的参考,相信也不难吧。
如果你想知道更多关于hgeGUIobject的细节,你可以看这位前辈的介绍:
http://blog.csdn.net/tkokof1/article/details/5851682