<!--著作權foruok,轉載請註明出處!!--> 定製控制項
DXUTGUI的控制項陳列庫預設使用內建的紋理資源,這個紋理資源可以在CDXUTDialog的Init函數中指定為我們自己的紋理資源(通常可以用一個圖片檔案來替代)。在這個系列的第一篇中,介紹了如何使用自己的紋理資源改變整個控制項陳列庫的風格。
研究CDXUTDialog的InitDefaultElements函數可以發現,DXUTGUI為每種控制項定義了若干元素,這些元素儲存在m_DefaultElements數組中。當增加一個新的控制項時,比較控制項類型,將該類型的元素集從DefaultElements取出,傳遞給該控制項,該控制項產生自己的元素執行個體並儲存起來。這一點事實支援第二篇中提供的修改某個控制項和某類控制面板的辦法。
我們發現紋理資源儲存在CDXUTDialogResourceManager的成員變數m_TextureCache中。m_TextureCache是一個動態數組,可以儲存任意的紋理資源,如一個按鈕的圖片紋理,一個列表框的背景材質等。只需要調用CDXUTDialg::SetTexture函數,指定一個ID和紋理檔案名稱即可。
紋理有了儲存的地方,接下來只需要讓控制項使用我們自己的紋理就可以進行定製了。而控制項的定製分為三類:單個控制項的定製、一類控制項的定製、產生新控制項類型。下面一一說明怎麼來實現。
一、單個控制項定製
單個控制項的定製比較簡單,以按鈕為例,需要三步:
(1)CDXUTDialog::AddButton產生按鈕pBtn
(2)CDXUTDialog::SetTexture,產生該按鈕的紋理,記錄紋理序號nTexture
(3)pBtn->GetElement擷取CDXUTElement指標pElem,pElem->SetTexture修改該控制項所用紋理為nTexture。
上面的定製受限於DXUTGUI,需要根據其所實現的控制項的渲染方法來產生自己的紋理資源,還要查看InitDefaultElements來決定怎麼調用CDXUTElement::SetTexture和CDXUTElement::SetFont。
二、單類控制項的定製
某一類控制項的定製需要更改該類控制項的預設元素,這個可以通過CDXUTDialog::SetDefaultElement來實現。需要兩步完成:
(1)CDXUTDialog::SetTexture,產生該類控制項的紋理,記錄紋理序號nTexture
(2)CDXUTDialog::GetDefaultElement或者預設元素對象的指標pElem,然後pElem->SetTexture修改。
第(2)步也還有另一種實現方法。聲明CDXUTElement對象,設定其成員,然後調用CDXUTDialog::SetDefaultElement,改寫初始化時產生的預設元素集。無論怎樣,都需要瞭解InitDefaultElements函數中做了什麼。
三、產生新控制項類型
產生新控制項並使用定製的紋理,需要以下幾步:
(1)實現控制項類
(2)載入資源
(3)為新類型控制項產生預設元素集
(4)產生控制項執行個體,添加到對話方塊
我們不改變DXUT自己的檔案,一切都在我們自己的檔案中實現。
(1)DXUTGUI提供的控制項不一定能滿足我們需要,有時候需要自己實現新的控制項,片按鈕。我們可以從CDXUTControl派生,也可以從某個特定的控制項類派生。下面我們以圖片按鈕的實現為例來說明,先看代碼。
class CDXUTImageButton : public CDXUTButton
...{
public:
CDXUTImageButton(CDXUTDialog *pDialog = NULL ):CDXUTButton(pDialog)
...{
m_Type = (DXUT_CONTROL_TYPE)(DXUT_CONTROL_SCROLLBAR + 1);
};
~CDXUTImageButton(void)...{};
virtual void Render( float fElapsedTime )
...{
int nOffsetX = 0;
int nOffsetY = 0;
DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;
int iIndex = 0;
if( m_bVisible == false )
...{
iState = DXUT_STATE_HIDDEN;
}
else if( m_bEnabled == false )
...{
iState = DXUT_STATE_DISABLED;
iIndex = 2;
}
else if( m_bPressed )
...{
iState = DXUT_STATE_PRESSED;
iIndex = 1;
}
else if( m_bMouseOver )
...{
iState = DXUT_STATE_MOUSEOVER;
iIndex = 3;
}
else if( m_bHasFocus )
...{
iState = DXUT_STATE_FOCUS;
iIndex = 3;
}
// Main button
CDXUTElement *pElement = m_Elements.GetAt( iIndex );
float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f;
// Blend current color
pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );
m_pDialog->DrawSprite( pElement, &m_rcBoundingBox, 0.8f );
};
我們需要為CDXUTImageButton指定一個控制項類型,取DXUT_CONTROL_SCROLLBAR + 1。同時改寫CDXUTButton的Render函數,依據按鈕狀態取不同的紋理元素進行繪製。我們所提供的圖片具有四個狀態(順序):正常態、下壓態、禁止態、懸停態,對應按鈕的四個狀態。
(2)有了圖片按鈕類,我們需要將按鈕的資源載入進來。可以用CDXUTDialog::SetTexture實現。
(3)四次調用CDXUTDialog::SetDefaultElement,為圖片按鈕設定四個元素。
(4)分配CDXUTImageButton對象,調用CDXUTDialog::AddControl,然後設定該按鈕的ID、TEXT、位置、大小等元素。
(2)、(3)、(4)步的範例程式碼:
//init custom button, normal way
int iTexture = g_SampleUI.SetTexture(IDC_BUTTON_CUSTOM_1, L"play.tga");
CDXUTElement elem;
elem.iTexture = IDC_BUTTON_CUSTOM_1;
elem.iFont = 0;
RECT rc = ...{0};
for(int i=0; i<4; i++)
...{
SetRect(&rc, i*64, 0, (i+1)*64, 28);
elem.SetTexture(IDC_BUTTON_CUSTOM_1, &rc, D3DCOLOR_ARGB(128, 255, 255, 255));
g_SampleUI.SetDefaultElement(DXUT_CONTROL_SCROLLBAR+1, i, &elem);
}
CDXUTImageButton *imgbtn = new CDXUTImageButton(&g_SampleUI);
g_SampleUI.AddControl(imgbtn);
imgbtn->SetID(IDC_BUTTON_CUSTOM_1);
imgbtn->SetText(L"CustomStyle");
imgbtn->SetSize(64, 27);
imgbtn->SetLocation(5, 5);
如果改動DXUTGUI的源碼,則可以在枚舉類型DXUT_CONTROL_TYPE中添加DXUT_CONTROL_IMAGEBUTTON項,同時將上面的for迴圈設定預設元素集部分加入到InitDefaultElements函數中,給CDXUTDialog添加AddImageButton函數。那麼產生按鈕的代碼看起來會相對簡潔一些,它可能是這個樣子:
g_SampleUI.AddImageButton(IDC_BUTTON_CUSTOM_1, L"CustomStyle", 5, 5, 64, 27);
好了,DXUTGUI控制項定製到此為止。
<!--著作權foruok,轉載請註明出處!!-->