作者:kagula
日期:2009-3-27
环境:[1]Microsoft DirectX SDK (November 2008)
[2]WindowsSDK_6.0.6001.18000.367
[3] Visual Studio 2005 with C
读者对象:
[1]能够看懂DirectX SDK包中 Custom UI 这个例子程序,并能根据这个例子熟练使用DXUT中提供的控件。
[2]熟悉C++语言
关键字:
DirectX DXUT Button
内容简介:
在同一个资源管理器中,如何包含多种自定义风格按钮控件。
我们知道所有的Dialog由资源管理器(CDXUTDialogResourceManager类的实例)管理,所有的Dialog需要从资料管理器里注册(或Init),所有的控件要在Dialog里添加(例如AddButton方法)
这里我们通过重载CDXUTDialog,建立CDXUTDialog。因为我们需要通过它来载入纹理资源。纹理可以是JPG格式,也可以是DDS格式。
为了正确Render我们的按钮控件。我们对CDXUTButton也进行了重载,建立了CDXUTButton2。
下面以一个例子来说明如何使用CDXUTDialog2和CDXUTButton2。
第一步:参考本文的附件,在你的工程中建立DXUTGUI2.H和DXUTGUI2.CPP文件。
第二步:引入下面的头文件
#include "DXUT.h"
#include "DXUTgui2.h"
第三步:
建立CDXUTDialog实例,取名为m_SampleUI是因为它的作用同Custom UI这个例子中的相同变量。
CDXUTDialog2 m_SampleUI; // dialog for sample specific controls
第四步:
利用资源管理器初始化m_SampleUI中要使用到的纹理资源
std::vector<LPCWSTR> vectorFN;
//压入,按钮纹理,这里为平方像素大小,DXUT会为你自动拉伸,
//这个值,你可以配合CDXUTGUI2.cpp中的源代码,进行修改。
vectorFN.push_back(L"button.jpg");
//压入,按钮纹理。下面的dds格式纹理,带AlphaChannel
//可以帮助你Render圆角按钮。
vectorFN.push_back(L"button2.dds");
m_SampleUI.Init( &m_DialogResourceManager ,vectorFN); //初始化
m_SampleUI.SetCallback( ::OnGUIEvent ); //设置GUI事件回调函数
// Font
m_SampleUI.SetFont( 1, L"Comic Sans MS", 24, FW_NORMAL );
m_SampleUI.SetFont( 2, L"Courier New", 16, FW_NORMAL );
第五步:添加按钮
// Buttons; Remark:这里的x,y,width,height暂时可以随便指定一个
int nI=100;
// 这里,省去部份代码
m_SampleUI.AddButton( IDC_PTTJSXZ, L"B1", 30, nI, 80, 35, L'4' );
nI+=50;
m_SampleUI.AddButton2( IDC_GJLSSY, L"B2", 30, nI, 80, 35, L'5' ,false,NULL,1);
m_SampleUI.AddButton2( IDC_GXLQSY, L"B3", 30, nI, 80, 35, L'6' ,false,NULL,2);
其中B1按钮,这是DXUT缺省的按钮控件Render样子。
B2按钮,是采用button.jpg纹理的按钮控件。注意它的最后一个参数为1。表示它将使用第一个压入栈的纹理文件。
B3按钮,是采用button2.dds纹理的按钮控件,dds文件带Alpha Channel可以生成任意形状的按钮控件。注意它的最后一个参数为2。表示它将使用第二个压入栈的纹理文件。
第六步:使用按钮
这里开始,使用方式同Custom UI这个例子的m_SampleUI对象变量,这里不再重复。
如何生成Jpg图像文件格式的纹理,个人认为属于常识问题,这里不展开,下面介绍如何生成dds格式的纹理。
你需要使用DirectX Texture Tool 安装完成DirectX SDK后,你可以从系统的[开始]菜单里面找到。
你需要准备二张图片,第一张图片是要显示的纹理,第二张图片,是黑白两色的图像可以有过渡,黑色代表透明色,白色代表第一张图片可以显示的区域。
具体如下:
第一步:打开DirectX Texture Tool工具软件,新建纹理(New Texture), 在我们这个例子中,设定了32平方,纹理格式为Unsigned 32-bit: A8R8G8B8
第二步:在菜单里,选中[Open Onto This Surface],打开你已经准备好的第一张图片。
第三步:在菜单里,选中(Open Onto Alpha Channel Of This Surface),打开你已经准备好的第二张图片。你可以看到由于Alpha Channel的缘故,第一张图片中的部份区域变的不可见。如果你有兴趣,可以试着用一下菜单里的[Change Background Color]选项。
第四步:保存即可。
DXUTGUI2.H
#pragma once
#ifndef DXUT_GUI2_H
#define DXUT_GUI2_H
#include "DXUTgui.h"
#include <vector>
// Minimum scroll bar thumb size
#define SCROLLBAR_MINTHUMBSIZE 8
// Delay and repeat period when clicking on the scroll bar arrows
#define SCROLLBAR_ARROWCLICK_DELAY 0.33
#define SCROLLBAR_ARROWCLICK_REPEAT 0.05
#define DXUT_NEAR_BUTTON_DEPTH 0.6f
#define DXUT_FAR_BUTTON_DEPTH 0.8f
#define DXUT_MAX_GUI_SPRITES 500
/*
这个集合的目的是,增强原DXUT上Button控件的可视化效果方面的功能。
*/
//-----------------------------------------------------------------------------
// Button control
//-----------------------------------------------------------------------------
class CDXUTButton2 : public CDXUTButton
{
public:
CDXUTButton2(CDXUTDialog* pDialog):CDXUTButton( pDialog )
{
m_nStyle = 0;
}
virtual void Render( float fElapsedTime );
public:
int m_nStyle; //Get(0+m_nStyle<<1),Get(1+m_nStyle<<1);
};
//-----------------------------------------------------------------------------
// All controls must be assigned to a dialog, which handles
// input and rendering for the controls.
//-----------------------------------------------------------------------------
class CDXUTDialog2: public CDXUTDialog
{
public:
/*
功能:在这里分配,控件将要用到的D设备相关资源
*/
void Init( CDXUTDialogResourceManager* pManager, std::vector<LPCWSTR> pVector);
void Init( CDXUTDialogResourceManager* pManager )
{
CDXUTDialog::Init(pManager);
}
/*
功能:添加,自定义按钮
备注:最后一个参数,指明将要使用到的Element的编号,必须大于,而且该编号的Element已经在Init中
分配。
警告:如果pVector.size()>nStyle,可能会出现不可预测后果!
*/
HRESULT AddButton2( int ID, LPCWSTR strText, int x, int y, int width, int height, UINT nHotkey=0,
bool bIsDefault=false, CDXUTButton** ppCreated=NULL, int nStyle=0 );
};
#endif
DXUTGUI2.CPP
#include "dxut.h"
#include "dxutgui2.h"
void CDXUTButton2::Render( float fElapsedTime )
{
int nOffsetX = 0;
int nOffsetY = 0;
DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;
if( m_bVisible == false )
{
iState = DXUT_STATE_HIDDEN;
}
else if( m_bEnabled == false )
{
iState = DXUT_STATE_DISABLED;
}
else if( m_bPressed )
{
iState = DXUT_STATE_PRESSED;
nOffsetX = 1;
nOffsetY = 2;
}
else if( m_bMouseOver )
{
iState = DXUT_STATE_MOUSEOVER;
nOffsetX = -1;
nOffsetY = -2;
}
else if( m_bHasFocus )
{
iState = DXUT_STATE_FOCUS;
}
// Background fill layer
//TODO: remove magic numbers
CDXUTElement* pElement = m_Elements.GetAt( 0 + m_nStyle*2 );
float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f;
RECT rcWindow = m_rcBoundingBox;
OffsetRect( &rcWindow, nOffsetX, nOffsetY );
// Blend current color
pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );
pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate );
m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_FAR_BUTTON_DEPTH );
m_pDialog->DrawText( m_strText, pElement, &rcWindow );
// Main button
pElement = m_Elements.GetAt( 1 + m_nStyle*2 );
// Blend current color
pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );
pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate );
m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_NEAR_BUTTON_DEPTH );
m_pDialog->DrawText( m_strText, pElement, &rcWindow );
}
//--------------------------------------------------------------------------------------
void CDXUTDialog2::Init( CDXUTDialogResourceManager* pManager, std::vector<LPCWSTR> pVector)
{
CDXUTDialog::Init(pManager);
for(int i=0;i<pVector.size();i++)
{
OutputDebugString(L"CDXUTDialog2::Init() ... 为Button控件装载纹理,From[");
SetTexture( 1+i, pVector[i] );
OutputDebugString(pVector[i]);
OutputDebugString(L"]/n");
}
RECT rcTexture;
CDXUTElement Element;
for(int i=0;i<pVector.size();i++)
{
//-------------------------------------
// CDXUTButton - Button
//-------------------------------------
SetRect( &rcTexture, 0, 0, 32, 32 ); //位图中指定的区域,作为按钮纹理
Element.SetTexture( 1+i, &rcTexture ); //绕过第一个,因为第一个是default材质
Element.SetFont( 0 );
Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 ); //按钮控件缺省颜色(ARGB) 当A为时,为最大透明度
Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 150, 255, 255, 255 ); //按钮控件点中颜色(ARGB)
Element.FontColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 255, 0, 0, 0 ); //鼠标悬浮在按钮控件上时,字体颜色
Element.FontColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 255, 0, 0, 0 ); //缺省字体颜色
// Assign the Element
SetDefaultElement( DXUT_CONTROL_BUTTON, 2+i*2, &Element );
//-------------------------------------
// CDXUTButton - Fill layer
//-------------------------------------
SetRect( &rcTexture, 0, 0, 32, 32 );
Element.SetTexture(1+i, &rcTexture, D3DCOLOR_ARGB( 0, 255, 255, 255 ) ); //绕过第一个,因为第一个是default材质
Element.TextureColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 160, 255, 255, 255 );
Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 60, 0, 0, 0 );
Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 30, 255, 255, 255 );
// Assign the Element
SetDefaultElement( DXUT_CONTROL_BUTTON, 3+i*2, &Element );
}
}
HRESULT CDXUTDialog2::AddButton2( int ID, LPCWSTR strText, int x, int y, int width, int height, UINT nHotkey,
bool bIsDefault, CDXUTButton** ppCreated, int nStyle )
{
HRESULT hr = S_OK;
CDXUTButton2* pButton = new CDXUTButton2( this );
if( ppCreated != NULL )
*ppCreated = pButton;
if( pButton == NULL )
return E_OUTOFMEMORY;
hr = AddControl( pButton );
if( FAILED( hr ) )
return hr;
// Set the ID and list index
pButton->SetID( ID );
pButton->SetText( strText );
pButton->SetLocation( x, y );
pButton->SetSize( width, height );
pButton->SetHotkey( nHotkey );
pButton->m_bIsDefault = bIsDefault;
pButton->m_nStyle = nStyle;
return S_OK;
}