火焰傀偶的挣扎旅程

纯爷们的一生就是不停地燃烧,keep on burning soul!!
随笔 - 6, 文章 - 5, 评论 - 4, 引用 - 0
数据加载中……

在hge中实现自己的滚动条


关于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/2break;
        }
    
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)/2break;
        }

    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(00, sl_w, sl_h);
           
        m_sprBack 
= new hgeSprite(m_tex_bak, 00,
                                  hge
->Texture_GetWidth(m_tex_bak),
                                  hge
->Texture_GetHeight(m_tex_bak));
       
        hgeGUISlider::SetMode(
0100.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(22130, 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, 2050);
        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





posted on 2012-12-14 17:22 WhiteDummy 阅读(2126) 评论(1)  编辑 收藏 引用 所属分类: HGE

评论

# re: 在hge中实现自己的滚动条  回复  更多评论   

the value is good
2012-12-15 01:16 | 月入1000万

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理