随笔 - 132  文章 - 51  trackbacks - 0
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用链接

留言簿(7)

随笔分类

随笔档案

文章分类

文章档案

cocos2d-x

OGRE

OPenGL

搜索

  •  

最新评论

阅读排行榜

评论排行榜

1.UI文件保存的设计缺陷
   我们生成.UI文件来保存我们生成的控件数据,下面是UI结构设计图



这样的设计有缺陷:
      以前UI控件最大数量定CONTROLS_COUNT_MAX= 64,因为m_ControlsType为固定数组,一旦控件数量超出64,我们就需要将以前的.UI文件转换为现在的UI文件进行版本兼容,而我们又不能具体确定好我们的控件上限是多少,每次版本兼容进行的转换相当麻烦...
 改进:设为容器,根据控件数量,动态读取保存到.UI文件中

struct S_UIData
{
    
struct S_UIHead
    
{
        S_UIHead()
        
{
            memset( m_szVer, 
0sizeof(m_szVer) );
            m_nControlsType.resize( CONTROLS_COUNT_MAX );
            memset( 
&m_nControlsType[0], 0sizeof(m_nControlsType) );
            strcpy( m_szVer, UI_VER);
            m_nControlsCount 
= 0;
            m_dwCreatedDate 
= 0;
        }

        
~S_UIHead()
        
{
            m_nControlsType.clear();
        }


        
char        m_szVer[10];
        DWORD        m_dwCreatedDate;
        S_FrameData    m_stFrameData;
        
int            m_nControlsCount;
        
//int            m_nControlsType[CONTROLS_COUNT_MAX];
        vector<int>    m_nControlsType;
    }
;

    S_UIData();
    
~S_UIData();
    
void Release();
    DWORD LoadOldFile( 
const char* pszFileName );
    DWORD LoadFile( 
const char* pszFileName );
    DWORD SaveFile( 
const char* pszFileName );
    
static S_BaseData* NewData( int nType );

    S_UIHead    m_stHead;
    
//S_BaseData    *m_pstControlData[CONTROLS_COUNT_MAX];
    vector< S_BaseData* > m_pstControlData;
}
;


这个样子,以后我们即使控件不够用了,只需要更改一下上限CONTROLS_COUNT_MAX就OK,但是.UI文件我们却不需要做版本转换,因为.UI中的数据都是根据控件数量来读取保存的 eg.10个控件,读取10个类型和控件数据。

DWORD S_UIData::LoadFile( const char* pszFileName )
{
    guard(S_UIData::LoadFile);
    assert( pszFileName );
    assert( pszFileName[
0!= 0 );

    FILE 
*fp = fopen(pszFileName, "rb" );
    
if ( fp )
    
{
        
forint n=0; n<CONTROLS_COUNT_MAX; n++ )
        
{
            
if ( m_pstControlData[n] )
            
{
                delete m_pstControlData[n];
                m_pstControlData[n] 
= NULL;
            }

        }


        fread( 
&m_stHead.m_szVer, sizeof(m_stHead.m_szVer), 1, fp );
        fread( 
&m_stHead.m_dwCreatedDate, sizeof( DWORD ) , 1, fp );
        fread( 
&m_stHead.m_stFrameData, sizeof( S_FrameData ) , 1, fp );
        fread( 
&m_stHead.m_nControlsCount, sizeofint ) , 1, fp );
        fread( 
&m_stHead.m_nControlsType[0],sizeof(int)*m_stHead.m_nControlsCount,1,fp);
        
//fread( &m_stHead, sizeof(m_stHead), 1, fp );

        
if ( strcmp( m_stHead.m_szVer, UI_VER ) != 0 )
        
{
            fclose(fp);
            MessageBox( NULL, 
"读取的*.UI文件版本不一样!""失败", MB_OK );
            
return 0;
        }


        assert( m_stHead.m_nControlsCount 
< CONTROLS_COUNT_MAX );

        
forint n=0; n<m_stHead.m_nControlsCount; n++ )
        
{
            m_pstControlData[n] 
= NewData( m_stHead.m_nControlsType[n] );
            
switch( m_stHead.m_nControlsType[n] )
            
{
            
case Type_Button:
                fread( m_pstControlData[n], 
sizeof(S_ButtonData), 1, fp );
                
break;
            
case Type_CheckBox:
                fread( m_pstControlData[n], 
sizeof(S_CheckBoxData), 1, fp );
                
break;
            
case Type_Edit:
                fread( m_pstControlData[n], 
sizeof(S_EditData), 1, fp );
                
break;
            
case Type_Text:
                fread( m_pstControlData[n], 
sizeof(S_TextData), 1, fp );
                
break;
            
case Type_List:
                fread( m_pstControlData[n], 
sizeof(S_ListData), 1, fp );
                
break;
            
case Type_ListImg:
                fread( m_pstControlData[n], 
sizeof(S_ListImgData), 1, fp );
                
break;
            
case Type_ScrollBar:
                fread( m_pstControlData[n], 
sizeof(S_ScrollBarData), 1, fp );
                
break;
            
case Type_ScrollBarEx:
                fread( m_pstControlData[n], 
sizeof(S_ScrollBarExData), 1, fp );
                
break;
            
case Type_ComboBox:
                fread( m_pstControlData[n], 
sizeof(S_ComboBoxData), 1, fp );
                
break;
            
case Type_Picture:
                fread( m_pstControlData[n], 
sizeof(S_PictureData), 1, fp );
                
break;
            
case Type_Progress:
                fread( m_pstControlData[n], 
sizeof(S_ProgressData), 1, fp );
                
break;
            
case Type_Tab:
                fread( m_pstControlData[n], 
sizeof(S_TabData), 1, fp );
                
break;
            
case Type_ListEx:
                fread( m_pstControlData[n], 
sizeof(S_ListExData), 1, fp );
                
break;
            
default:
                assert( 
false );
                
break;
            }

        }


        fclose(fp);
        
return m_stHead.m_dwCreatedDate;
    }

    
return 0;
    unguard;
}


DWORD S_UIData::SaveFile( 
const char* pszFileName )
{
    
//time_t osBinaryTime;  // C run-time time (defined in <time.h>)
    
//time( &osBinaryTime );
    
//m_stHead.m_dwCreatedDate = (DWORD)osBinaryTime;
    assert( pszFileName );
    
//
    DWORD dwVer = 0;
    
forint n=0; n<m_stHead.m_nControlsCount; n++ )
    
{
        
int nIdLength = strlen(m_pstControlData[n]->m_szID);
        assert( nIdLength 
> 0 );
        
forint i=0; i<nIdLength; i++ )
        
{
            dwVer 
+= m_pstControlData[n]->m_szID[i];
        }

    }

    dwVer 
= dwVer*m_stHead.m_nControlsCount + 1;
    m_stHead.m_dwCreatedDate 
= dwVer;

    FILE 
*fp = fopen( pszFileName, "w+b" );
    
if ( fp )
    
{
        fwrite( &m_stHead.m_szVer, sizeof(m_stHead.m_szVer), 1, fp );
        fwrite( &m_stHead.m_dwCreatedDate, sizeof( m_stHead.m_dwCreatedDate ) , 1, fp );
        fwrite( &m_stHead.m_stFrameData, sizeof( m_stHead.m_stFrameData ) , 1, fp );
        fwrite( &m_stHead.m_nControlsCount, sizeof( m_stHead.m_nControlsCount ) , 1, fp );

        //fwrite( &m_stHead, 
        //    sizeof(m_stHead.m_szVer)+sizeof(m_stHead.m_dwCreatedDate)+sizeof(m_stHead.m_stFrameData)+sizeof(m_stHead.m_nControlsCount),
        //    1, fp );
      
         //按容器中的空间数量进行读取
        fwrite( &m_stHead.m_nControlsType[0],sizeof(int)*m_stHead.m_nControlsCount, 1, fp );
        

        for( int n=0; n<m_stHead.m_nControlsCount; n++ )
        {
            switch( m_stHead.m_nControlsType[n] )
            {
            case Type_Button:
                SAVE_CONTROL( S_ButtonData );
                break;
            case Type_CheckBox:
                SAVE_CONTROL( S_CheckBoxData );
                break;
            case Type_Edit:
                SAVE_CONTROL( S_EditData );
                break;
            case Type_Text:
                SAVE_CONTROL( S_TextData );
                break;
            case Type_List:
                SAVE_CONTROL( S_ListData );
                break;
            case Type_ListImg:
                SAVE_CONTROL( S_ListImgData );
                break;
            case Type_ScrollBar:
                SAVE_CONTROL( S_ScrollBarData );
                break;
            case Type_ScrollBarEx:
                SAVE_CONTROL( S_ScrollBarExData );
                break;
            case Type_ComboBox:
                SAVE_CONTROL( S_ComboBoxData );
                break;
            case Type_Picture:
                SAVE_CONTROL( S_PictureData );
                break;
            case Type_Progress:
                SAVE_CONTROL( S_ProgressData );
                break;
            case Type_Tab:
                SAVE_CONTROL( S_TabData );
                break;
            case Type_ListEx:
                SAVE_CONTROL( S_ListExData );
                break;
            default:
                assert(false);
                break;
            }
        }
        fclose(fp);
        return dwVer;
    }
    
return 0;
}


最后需要注意的就是 字节对齐 问题

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2.UI整体设计思路 

 设计思路:我们游戏中的UI常划分为常见UI模块,如Friend面板,Property面板,Pack面板,Pet面板等等.
 每个模块中的单个UI也处理消息,渲染...
 我们创建一个UIMgr来管理这些大的UI模块(即UIFrame),每个UIFrame来管理大模块中的单个小UI控件
 然后在应用程序中分别调用UIMgr来处理
 
 一句话:app管理UIMgr,UIMgr管理UIFrame, UIFrame管理单个UI控件(UI_Object)
 
 
 我们的应用程序拥有主要函数:
 virtual HRESULT FrameMove(); //更新
 virtual HRESULT Render();  //渲染
 virtual LRESULT MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
 
 分别调用 theUIMgr.FrameMove(), theUIMgr.Render(), theUIMgr().MsgProc(...)
 
 theUIMgr是一个UIFrame的容器  vector<UIFrame*> vecFrame;
 
 内部调用UIFrame的消息处理
 for( int i = 0; i < vecFrame.size(); i++ )
 vecFrame[i]->FrameMove();
 vecFrame[i]->Render();
 vecFrame[i]->OnMouseMove(...);
 vecFrame[i]->OnLButtonDown(...);
 
 vecFrame[i]->MsgProc(...);
 

 
UIFrame是单个UI控件的容器 vector<UI_Object*> m_vecChild;
 
 for( int i = 0; i < m_vecChild.size(); i++ )
 m_vecChild[i]->FrameMove();
 ....
 m_vecChild[i]->Render();
 ....
 m_vecChild[i]->OnMouseMove(...);
 

所有的UI消息都能够处理了,所有处理要依据先后关系,如一个面板消息被一个UI处理后,那么要返回true,
其他的UI将不会重复处理


问题是我们会将我们的UI做成一个UI 静态库,那么我们按钮按下触发的功能,无法提前设置好,
解决方法: 设置回调函数
eg:
 CHR_UI_Frame下的回调函数接口
 typedef bool (*funOnClick)( OUT CHR_UI_Object* pSender );
 typedef bool (*funOnRBtnDown)( OUT CHR_UI_Object* pSender );
 typedef bool (*funRun)(void);
 typedef bool (*funRender)(void);
 
 CHR_UI_Edit下的回调函数指针
 typedef void (*funOnEnter)( OUT CHR_UI_Object* pSender, OUT const char *szData );
 typedef void (*funOnTab)( OUT CHR_UI_Object* pSender, OUT const char* szData);
 
 CHR_UI_Button下的函数接口
 typedef bool (*funOnButtonClick)( OUT CHR_UI_Object* pSender );
 
 ...
 
 在WM_LBUTTONUP中调用触发
 if ( m_pFunOnButtonClick )  //函数指针
 {
  if ( m_pFunOnButtonClick( this ) == false )
  {
   if ( m_pFather && strcmp( m_pstData->m_szID, "ID_BUTTON_CLOSE" ) == 0 )
   {
    m_pFather->SetVisable( false );
   }
  }
 }
 
 m_pID_BUTTON_SelectRole.SetButtonClickFunc( ID_BUTTON_SELECTROLEOnButtonDown );
 
   

posted on 2010-09-03 14:14 风轻云淡 阅读(545) 评论(0)  编辑 收藏 引用 所属分类: UI

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