1. Grundstruktur eines Fensters:
1.1 Headerdatei:
Hier werden die Funktionen und Variablen, die in der cpp Datei verwendet werden definiert. --> siehe Klassenkonzept
Code:
class CWndTest : public CWndBase //CWndTest --> Klassenname / public CWndBase --> erbt von CWndBase ( --> siehe Vererbung ) { private: //-->geschützte Variablen int m_nFontHeight ; public: //-->ungeschützte Variablen CWndTest (); //Konstruktor ~CWndTest (); //Destruktor virtual BOOL Initialize( CWndBase* pWndParent = NULL, DWORD nType = MB_OK ); //--> wird aufgerufen, wenn das Fenster sich öffnen soll virtual BOOL OnChildNotify( UINT message, UINT nID, LRESULT* pLResult ); //--> wird aufgerufen, wenn auf das Fenster geklickt wurde virtual void OnDraw( C2DRender* p2DRender ); //-->wird permanent aufgerufen, um das Fenster anzuzeigen virtual void OnInitialUpdate(); //-->wird aufgerufen, wenn das Fenster verändert wird virtual void OnLButtonUp( UINT nFlags, CPoint point ); //-->wird aufgerufen, wenn der linke Zeiger losgelassen wird virtual void OnLButtonDown( UINT nFlags, CPoint point ); //-->wird aufgerufen, wenn der linke Zeiger gedrückt wird //Es gibt natürlich noch viele weitere Funktionen für vershiedene Aufgaben };
Hier wird in die einzelnen Funktionen einer Klasse hineingeschrieben, was gemacht werden soll
Ein Funktionsname setzt sich zusammen aus: DatenTyp NameSpace::Funktionsname( Datentyp Parametername ... )
Code:
CWndTest ::CWndTest () { } CWndTest ::~CWndTest () { } void CWndTest ::OnDraw( C2DRender* p2DRender ) { } void CWndTest ::OnInitialUpdate() { } BOOL CWndTest ::Initialize( CWndBase* pWndParent, DWORD /*dwWndId*/ ) { return CWndNeuz::InitDialog( g_Neuz.GetSafeHwnd(), APP_COMM_ITEM, 0, CPoint( 0, 0 ), pWndParent ); } void CWndTest ::OnLButtonUp( UINT nFlags, CPoint point ) { } void CWndTest ::OnLButtonDown( UINT nFlags, CPoint point ) { } BOOL CWndTest ::OnChildNotify( UINT message, UINT nID, LRESULT* pLResult ) { return CWndNeuz::OnChildNotify( message, nID, pLResult ); }
Damit ist bereits ein Fenster programmiert, und wenn es irgendwo im Client erzeugt und initialisiert wird, wird es im Spiel erscheinen:
Code:
CWndTest* pTest = new CWndTest; pTest->Initialize(); //Zum löschen ( hier ist dann der Destruktor wichtig ) delete pTest; pTest = NULL;
2. In das oben erzeugte Fenster Tabs einfügen
Dazu müssen wir uns obiges Fenster als Container vorstellen, in welchen weitere Fenster eingebettet werden, die dann durchgeschaltet werden... Jeder Tab ist ein neues Fenster
2.1 Die Headerdatei
Code:
class CWndTestCtrl : public CWndBase { int m_nFontHeight ; CWndScrollBar m_wndScrollBar; CWndWorld* pWndWorld; int m_dwDraw[MAX_RECIPE]; int m_nMaxDraw; public: CRect m_rect; DWORD m_dwListCtrlStyle; void SetScrollBar(); CWndTestCtrl(); ~CWndTestCtrl(); void Create( DWORD m_dwListCtrlStyle, RECT& rect, CWndBase* pParentWnd, UINT nID ); //-->wird zum erstellen des Tabs aufgerufen virtual void OnMouseWndSurface( CPoint point ); virtual void OnInitialUpdate(); virtual void OnDraw(C2DRender* p2DRender); virtual void OnSize(UINT nType, int cx, int cy); virtual void PaintFrame(C2DRender* p2DRender); virtual void SetWndRect( CRect rectWnd, BOOL bOnSize ); virtual void OnLButtonDblClk( UINT nFlags, CPoint point ); //-->wird aufgerufen,wenn man Doppelklickt mit dem linken Zeiger };
2.2 Die Quellcodedatei
Code:
void CWndTestCtrl::Create( DWORD dwListCtrlStyle, RECT& rect, CWndBase* pParentWnd, UINT nID ) { m_dwListCtrlStyle = dwListCtrlStyle; CWndBase::Create( WBS_CHILD, rect, pParentWnd, nID ); } void CWndTestCtrl::SetScrollBar() { int nPage, nRange; nPage = GetClientRect().Height() / m_nFontHeight; #ifdef __RT_1025 nRange = g_WndMng.m_RTMessenger.size(); #else // __RT_1025 nRange = g_WndMng.m_Messenger.m_aFriend.size();//m_pItemContainer->m_dwIndexNum;// - nPage; #endif // __RT_1025 m_wndScrollBar.SetScrollRange( 0, nRange ); m_wndScrollBar.SetScrollPage( nPage ); } void CWndTestCtrl::OnSize( UINT nType, int cx, int cy ) { ItemProp* pItem = NULL; CRect rect = GetWindowRect(); rect.left = rect.right - 15; m_wndScrollBar.SetWndRect( rect ); int nPage, nRange; nPage = GetClientRect().Height() / m_nFontHeight; int nCount = GetRecipeCount(); nRange = nCount; m_wndScrollBar.SetScrollRange( 0, nRange ); m_wndScrollBar.SetScrollPage( nPage ); CWndBase::OnSize( nType, cx, cy); } void CWndTestCtrl::SetWndRect( CRect rectWnd, BOOL bOnSize ) { m_rectWindow = rectWnd; m_rectClient = m_rectWindow; m_rectClient.DeflateRect( 3, 3 ); if( bOnSize ) OnSize( 0, m_rectClient.Width(), m_rectClient.Height() ); } void CWndTestCtrl::PaintFrame( C2DRender* p2DRender ) { int nPage, nRange; ItemProp* pItem = NULL; if( 1 ) { nPage = GetClientRect().Height() / ( m_nFontHeight ); int nCount = GetRecipeCount(); nRange = nCount; } m_wndScrollBar.SetScrollRange( 0, nRange ); m_wndScrollBar.SetScrollPage( nPage ); } CWndTestCtrl::~CWndTestCtrl() { } void CWndTestCtrl::OnInitialUpdate() { CRect rect = GetWindowRect(); m_wndScrollBar.AddWndStyle( WBS_DOCKING ); m_wndScrollBar.Create( WBS_VERT, rect, this, 1000 ); m_nFontHeight = 30; pWndWorld = (CWndWorld*)g_WndMng.GetWndBase( APP_WORLD ); } void CWndTestCtrl::OnDraw( C2DRender* p2DRender ) { if( NULL == pWndWorld ) { pWndWorld = (CWndWorld*)g_WndMng.GetWndBase( APP_WORLD ); return; } if( NULL == g_pPlayer ) return; CPoint pt( 3, 3 ); CWndWorld* pWndWorld = (CWndWorld*)g_WndMng.GetWndBase( APP_WORLD ); int nMaxCount = 10; //Zahl der Elemente, die insgesamt vorhanden sind int nMax = nMaxCount; if( nMax - m_wndScrollBar.GetScrollPos() > m_wndScrollBar.GetScrollPage() ) nMax = m_wndScrollBar.GetScrollPage() + m_wndScrollBar.GetScrollPos(); if( nMax < m_wndScrollBar.GetScrollPos() ) nMax = 0; for( int i = 0; i < m_wndScrollBar.GetScrollPos() && i < nMaxCount; ++i ); int x = 0, nWidth = m_rectClient.Width();// - 1; CRect rect( x, pt.y, x + nWidth, pt.y + m_nFontHeight ); rect.SetRect( x + 3, pt.y + 6, x + 3 + 32, pt.y + 6 + 32 ); memset( m_dwDraw, 0, sizeof( int ) * (10) ); m_nMaxDraw = 0; int nScroll = 0; //an welcher Position bist du? DrawIrgendwas( p2DRender, &pt, x, nScroll ); //Die Funktion übernimmt eine Referenz ( DrawIrgendWas( C2DRender* p2DRender, CPoint* pPoint, int x, int &nScroll ) ) } CWndTestCtrl::CWndTestCtrl() { pWndWorld = NULL; memset( m_dwDraw, 0, sizeof( int ) * (MAX_RECIPE) ); m_nMaxDraw = 0; } void CWndTestCtrl::OnMouseWndSurface( CPoint point ) { } void CWndTestCtrl::OnLButtonDblClk( UINT nFlags, CPoint point ) { }
2.3 Das Tab einfügen
um jetzt das Tab zu erzeugen müsst ihr in der CWndTest ein bischen was verändern:
in der Headerdatei folgendes hinzufügen:
Code:
CWndTestCtrl m_WndTest;
und in der Quellcodedatei müsst ihr die OnInitialUpdate Funktion verändern:
Code:
void CWndTest::OnInitialUpdate() { CWndNeuz::OnInitialUpdate(); CWndTabCtrl* pWndTabCtrl = (CWndTabCtrl*)GetDlgItem( WIDC_TABCTRL1 ); CRect rect = GetClientRect(); rect.left = 5; rect.top = 0; m_WndTest.Create( WBS_CHILD | WBS_NODRAWFRAME, rect, pWndTabCtrl, APP_COMM_ITEM ); //Das Tab erstellen WTCITEM tabTabItem; tabTabItem.mask = WTCIF_TEXT | WTCIF_PARAM; tabTabItem.pszText = prj.GetText( TID_TOOLTIP_ITEMTIME ); //Text, der auf dem Tabreiter steht tabTabItem.pWndBase = &m_WndTest; pWndTabCtrl->InsertItem( 0, &tabTabItem ); //Das Tab einfügen CRect rectRoot = m_pWndRoot->GetLayoutRect(); CRect rectWindow = GetWindowRect(); CPoint point( rectRoot.right - rectWindow.Width(), 110 ); Move( point ); MoveParentCenter(); }
Der Rest wird von der CWndBase automatisch erledigt...
Wenn ihr Näheres wissen wollt, dann seht euch die CWndCommItem Klasse an... da steht alles wichtige drin^^
Hier wird eine Liste mit allen Funktionen kommen, die ich von Zeit zu Zeit hinzufügen werde:
Funktionen:
Konstruktor:
Destruktor:
OnDraw:
OnChildNotify:
OnInitialUpdate:
Initialize
OnDropIcon
OnLButtonDblClk/OnRButtonDblClk/OnMButtonDblClk
Code:
CWndTest::CWndTest() { //wird aufgerufen, wenn ich eine Variable des Typs CWndTest anlege //gut um Variablen zu initialisieren }
Destruktor:
Code:
CWndTest::~CWndTest() { //wird aufgerufen, wenn die Variable gelöscht werden soll //gut um Speicher wieder freizugeben, falls Variablen wie Pointer oder andere Klassen ohne Destruktor verwendet werden }
OnDraw:
Code:
void CWndTest::OnDraw( C2DRender* p2DRender ) { //Hier wird das Fenster gezeichnet //wichtig ist der Parameter p2DRender, über ihn können Icons u.ä. gerendert werden CString strPath = MakePath( DIR_ITEM, "Itm_TreasureBox01.dds"); CTexture* pTexture; pTexture = CWndBase::m_textureMng.AddTexture( g_Neuz.m_pd3dDevice, strPath, 0xffff00ff ); pTexture->Render( p2DRender, GetWndCtrl( WIDC_CB_OPEN03 )->rect.TopLeft(), 255 ); //Dieser Codeabschnitt rendert in ein Customfeld mit dem Identifier WIDC_CB_OPEN03 das Icon einer geöffneten Treasurebox TCHAR szTemp[32]; _stprintf( szTemp, "%d", 10 ); CSize size = p2DRender->m_pFont->GetTextExtent( szTemp ); p2DRender->TextOut( m_nCtrlId[i].right-11, GetWndCtrl( WIDC_CB_OPEN03 )->rect.bottom-11 , szTemp, 0xff1010ff ); //Dieser Codeabschnitt rendert eine Zahl an das Itembild }
OnChildNotify:
Code:
BOOL CWndTest::OnChildNotify( UINT message, UINT nID, LRESULT* pLResult ) { //Diese Funktion verarbeitet, wenn jmnd einen Button auf dem Fenster drückt //mit nID wird der Identifier des gedrückten Buttons übergeben if( nID == WIDC_BT_CANCEL ) //wenn Cancel gedrückt { Destroy(); //-->Fenster schliessen } return CWndNeuz::OnChildNotify( message, nID, pLResult ); }
OnInitialUpdate:
Code:
void CWndTest::OnInitialUpdate() { CWndNeuz::OnInitialUpdate(); //Diese Funktion wird aufgerufen, wenn sich das Fenster in irgendeiner Weise verändert //Hier können Werte zugewiesen werden }
Initialize
Code:
BOOL CWndTest::Initialize( CWndBase* pWndParent, DWORD nType ) { //Diese Funktion wird zum "erscheinen lassen" eines Fensters aufgerufen return CWndNeuz::InitDialog( g_Neuz.GetSafeHwnd(), APP_TREASURECHEST_RESULT, 0, CPoint( 0, 0 ), pWndParent ); }
OnDropIcon
Code:
BOOL CWndTest::OnDropIcon( LPSHORTCUT pShortcut, CPoint point ) { //Diese Funktion wird aufgerufen, wenn ein Icon auf ein Fenster gedroppt wird //Übergeben werden ein Shortcut zu dem Icon und der Punkt, auf den das Icon gedroppt wird //Um das Item, zu dem das Shortcut gehört zu kriegen muss man folgendes machen CItemElem* pItemElem; pItemElem = (CItemElem*)g_pPlayer->GetItemId( pShortcut->m_dwId ); if(g_pPlayer->IsUsing(pItemElem)) g_WndMng.PutString( "Item wird bereits verwendet" ); else { //Hier erfolgt dann die weitere Verarbeitung //man kann zB überprüfen, ob das Item gewissen Anforderungen entspricht if( pItemElem->GetProp()->dwItemKind1 == IK1_GOLD ) { //oder ob es überhaupt auf ein Feld gedroppt wurde: if( GetWndCtrl( WIDC_CB_OPEN03 )->rect.PtInRect( point ) ) { //Hier kann es dann in eine Klassenvariable gespeichert werden, um dann wo anders verwendet zu werden... zB in der OnDraw Funktion ( Item Rendern mit pItemElem->GetTexture()->Render( ... ) ) m_pItemElem = pItemElem; //Ein Item als verwendet markieren pItemElem->SetExtra( pItemElem->GetExtra() + 1 ); return TRUE; } } } return FALSE; }
OnLButtonDblClk/OnRButtonDblClk/OnMButtonDblClk
Code:
void CWndTest::OnLButtonDblClk( UINT nFlags, CPoint point ) { //Diese Funktion wird aufgerufen, wenn auf eine Fläche des Fenster zweimal geklickt wird //Wir gehen davon aus, dass der User sein Item aus dem Feld wieder entfernen möchte //als erstes testen, ob er überhaupt auf das richtige Feld klickt if(GetWndCtrl( WIDC_CB_OPEN03 )->rect.PtInRect( point )) { //überprüfen, ob darin ein Item ist if(m_pItemElem) { //Item als nicht verwendet markieren m_pItemElem->SetExtra(0); //Item aus der Klasse entfernen, damit es nicht mehr gerendert wird m_pItemElem = NULL; //einen eventuell vorhandenen OK Button deaktivieren CWndButton* pButton = (CWndButton*)GetDlgItem(WIDC_BT_OK); pButton->EnableWindow(FALSE); } } }
Was vielleicht noch kommt : Fortschrittsleiste programmieren