Tabs dynamisch erstellen wenn sie gebraucht wird.
-
Geht es Euch auch so, dass wenn man ein Problem löst sich das nächste größere vor einem aufbaut?
Ich habe eine Reihe von Tabs die auch sehr gut funktionieren. Soweit so gut. Nun habe ich aber folgende Situation:
Ich habe zunächst eine feste Anzahl von Tabs (2). Nun kann es aber sein, dass eine unbekannte Anzahl von Tabs (mit anderen Namen) dazu kommen sollen. Der Inhalt der Registerkarten ist i.d.R. immer der selbe. Soz. sollen Tabs dynamisch dazu kommen.
Kann man sowas überhaupt realisieren?
-
Schau dir mal meine Klasse DynTabCtrl an.
Devil
-
Erst mal danke, ich habe mir die DynTabCtrl angesehen. Da war jemand aber fleisig!
Zitat aus anderm Threat von Dir: "Mach dir ein paar dialog, welche in den eigenschaften Untergeordnet und randlos sind. "
D.h. ich muß eine ganze Reihe von Dialogen vorher basteln und mit den Steuerelementen versehen. Was mache ich aber wenn ich nicht weis wieviele Tabs ich haben werde? Oder kann man den selben Dialog mehrere male unter anderem Namen aufrufen?
Was mir auch noch nicht so ganz klar ist: "Den Header der Tab-Dialoge in die Datei des Hauptdialog einbinden(Da wo die TabCtrl ist)." Etwa so DlgSeite1.h nach bspw. MyTabCtrl includen.
-
Du kannst X Instanzen einer Dialogklasse erstellen.
-
Ich hoffe du weisst vorher wie der Inhalt deiner Tabs aussehen soll
Wie Unix-tom schon richtig sagte, Instanzen kannst du (fast) unendlich viele erstellen...Devil
-
Also irgendwas mache ich da wohl falsch?
Ich bekomme folgende Fehlermeldungen:
1. error C2061: Syntaxfehler: Bezeichner 'myDialog'
2. error C2660: 'DynTabCtrl::InsertItem': Funktion akzeptiert keine 1 Argumente
3. ...Ich bin so vorgegangen:
1. Neue Dialoganwendung erstellt
2. DynTabCtrl eingebunden
3. Ein TabCtrl Steuerelement ins Fenster gezogen
4. Membervariable erstellt (m_cMyTab) Variablentyp DynTabCtrl
5. 2 Dialoge ohne Rand und untergeordnet erstellt
6. 2 Dialogklassen mit Basisklasse CDialog erstellt
6. Die Header der Dialoge in meine testdlg.cpp included
7. In der testdlg.cpp: m_cMyTab.InsertItem(new myDialog(), "Glubsch", IDD_DIALOG1)Ergebnis:
-
er kennt den Dialog nicht, und du hast zuwenig parameter für InsertItem,
aber das sagt dir der Compiler ja schon...
-
Es ist einfach zu warm zu arbeiten! Da sitzt man vorm Bildschirm und übersieht völlig das man einen Buchstabendreher hat. myDialog() und myDilaog.cpp vertragen sich nicht wirklich. :p
Danke für die Hilfe!
-
CPP-Datei
// XTabCtrl.cpp : implementation file // #include "stdafx.h" #include "deineapp.h" #include "XTabCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CXTabCtrl CXTabCtrl::CXTabCtrl() { m_iSelectedTab = 0; m_ptTabs.x = 4; m_ptTabs.y = 28; m_crSelected = 0; m_crDisabled = 0; m_crNormal = 0; m_crMouseOver = 0; m_alarm = 0; m_bColorSelected = false; m_bColorDisabled = false; m_bColorNormal = false; m_bColorMouseOver = false; m_balarmSelected = true; m_iIndexMouseOver = -1; m_bMouseOver = false; } CXTabCtrl::~CXTabCtrl() { TRACE("CXTabCtrl Destruct\n"); DeleteAllTabs(); } BEGIN_MESSAGE_MAP(CXTabCtrl, CTabCtrl) //{{AFX_MSG_MAP(CXTabCtrl) ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelchange) ON_NOTIFY_REFLECT(TCN_SELCHANGING, OnSelchanging) ON_WM_MOUSEMOVE() ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTabCtrl message handlers void CXTabCtrl::SetTopLeftCorner(CPoint pt) { m_ptTabs.x = pt.x; m_ptTabs.y = pt.y; } void CXTabCtrl::SetMouseOverColor(COLORREF cr) { m_bColorMouseOver = true; m_crMouseOver = cr; } void CXTabCtrl::SetAlarmColor(COLORREF cr) { m_alarm = cr; } void CXTabCtrl::SetAlarm(bool alarm) { m_balarmSelected = alarm; } void CXTabCtrl::SetDisabledColor(COLORREF cr) { m_bColorDisabled = true; m_crDisabled = cr; } void CXTabCtrl::SetSelectedColor(COLORREF cr) { m_bColorSelected = true; m_crSelected = cr; } void CXTabCtrl::SetNormalColor(COLORREF cr) { m_bColorNormal = true; m_crNormal = cr; } void CXTabCtrl::AddTab(CDialog* pWnd, LPTSTR lpszCaption, int iImage,UINT ID) { if(!pWnd->Create(ID,this)) { delete pWnd; pWnd =NULL; return; } // m_tabs.push_back(pWnd); m_tabs1.Add(pWnd); TCITEM item; item.mask = TCIF_TEXT|TCIF_PARAM|TCIF_IMAGE; item.lParam = (LPARAM) pWnd; item.pszText = lpszCaption; item.iImage = iImage; int iIndex = m_arrayStatusTab.GetSize(); InsertItem(iIndex, &item); pWnd->SetWindowPos(NULL, m_ptTabs.x, m_ptTabs.y , 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER); pWnd->ShowWindow(iIndex ? SW_HIDE : SW_SHOW); //** the initial status is enabled m_arrayStatusTab.Add(TRUE); } void CXTabCtrl::AddTab(CWnd* pWnd, LPTSTR lpszCaption, int iImage) { ASSERT_VALID(pWnd); TCITEM item; item.mask = TCIF_TEXT|TCIF_PARAM|TCIF_IMAGE; item.lParam = (LPARAM) pWnd; item.pszText = lpszCaption; item.iImage = iImage; int iIndex = m_arrayStatusTab.GetSize(); InsertItem(iIndex, &item); pWnd->SetWindowPos(NULL, m_ptTabs.x, m_ptTabs.y , 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER); pWnd->ShowWindow(iIndex ? SW_HIDE : SW_SHOW); //** the initial status is enabled m_arrayStatusTab.Add(TRUE); } void CXTabCtrl::EnableTab(int iIndex, BOOL bEnable) { ASSERT(iIndex < m_arrayStatusTab.GetSize()); //** if it should change the status ---- if (m_arrayStatusTab[iIndex] != bEnable) { m_arrayStatusTab[iIndex] = bEnable; //** redraw the item ------- CRect rect; GetItemRect(iIndex, &rect); InvalidateRect(rect); } } void CXTabCtrl::DeleteAllTabs() { m_arrayStatusTab.RemoveAll(); // DeleteAllItems(); if(!m_tabs1.IsEmpty()) { for(int i =0; i < m_tabs1.GetCount(); i++)//vector freigeben { delete m_tabs1.GetAt(i); } m_tabs1.RemoveAll();//vector leeren } } void CXTabCtrl::DeleteTab(int iIndex) { if (iIndex >= m_arrayStatusTab.GetSize()) return; // ASSERT(iIndex < m_arrayStatusTab.GetSize()); if(iIndex == 0) { SelectTab(m_arrayStatusTab.GetSize()-1); } else { SelectTab(0); } m_arrayStatusTab.RemoveAt(iIndex); m_tabs1.GetAt(iIndex)->DestroyWindow(); delete m_tabs1.GetAt(iIndex); DeleteItem(iIndex); m_tabs1.RemoveAt(iIndex); } BOOL CXTabCtrl::IsTabEnabled(int iIndex) { ASSERT(iIndex < m_arrayStatusTab.GetSize()); return m_arrayStatusTab[iIndex]; } BOOL CXTabCtrl::SelectTab(int iIndex) { ASSERT(iIndex < m_arrayStatusTab.GetSize()); if (GetCurSel() == iIndex) return TRUE; //** check if the tab is enabled -------- if (m_arrayStatusTab[iIndex]) { TCITEM item; CWnd* pWnd; item.mask = TCIF_PARAM; GetItem(GetCurSel(), &item); pWnd = reinterpret_cast<CWnd*> (item.lParam); ASSERT_VALID(pWnd); pWnd->ShowWindow(SW_HIDE); SetCurSel(iIndex); GetItem(iIndex, &item); pWnd = reinterpret_cast<CWnd*> (item.lParam); ASSERT_VALID(pWnd); pWnd->ShowWindow(SW_SHOW); return TRUE; } return FALSE; } void CXTabCtrl::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here int iNewTab = GetCurSel(); if (!IsTabEnabled(iNewTab)) { SetCurSel(m_iSelectedTab); } else { TCITEM item; CWnd* pWnd; item.mask = TCIF_PARAM; //** hide the current tab --------- GetItem(m_iSelectedTab, &item); pWnd = reinterpret_cast<CWnd*> (item.lParam); ASSERT_VALID(pWnd); pWnd->ShowWindow(SW_HIDE); //** show the selected tab -------- GetItem(iNewTab, &item); pWnd = reinterpret_cast<CWnd*> (item.lParam); ASSERT_VALID(pWnd); pWnd->ShowWindow(SW_SHOW); } *pResult = 0; } void CXTabCtrl::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here m_iSelectedTab = GetCurSel(); *pResult = 0; } void CXTabCtrl::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class CTabCtrl::PreSubclassWindow(); ModifyStyle(0, TCS_OWNERDRAWFIXED); } void CXTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CRect rect = lpDrawItemStruct->rcItem; rect.top += ::GetSystemMetrics(SM_CYEDGE); int nTabIndex = lpDrawItemStruct->itemID; if (nTabIndex < 0) return; BOOL bSelected = (nTabIndex == GetCurSel()); COLORREF crSelected = m_bColorSelected ? m_crSelected : GetSysColor(COLOR_BTNTEXT); COLORREF crNormal = m_bColorNormal ? m_crNormal : GetSysColor(COLOR_BTNTEXT); COLORREF crDisabled = m_bColorDisabled ? m_crDisabled : GetSysColor(COLOR_GRAYTEXT); char label[64]; TC_ITEM item; item.mask = TCIF_TEXT|TCIF_PARAM|TCIF_IMAGE; item.pszText = label; item.cchTextMax = 63; if (!GetItem(nTabIndex, &item)) return; CWnd* pWnd; pWnd = reinterpret_cast<CWnd*> (item.lParam); ASSERT_VALID(pWnd); CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); if (!pDC) return; int nSavedDC = pDC->SaveDC(); CRect rectItem; POINT pt; GetItemRect(nTabIndex, &rectItem); GetCursorPos(&pt); ScreenToClient(&pt); if (rectItem.PtInRect(pt)) m_iIndexMouseOver = nTabIndex; if (m_balarmSelected) m_iIndexMouseOver = nTabIndex; pDC->SetBkMode(TRANSPARENT); pDC->FillSolidRect(rect, ::GetSysColor(COLOR_BTNFACE)); //** Draw the image CImageList* pImageList = GetImageList(); if (pImageList && item.iImage >= 0) { rect.left += pDC->GetTextExtent(_T(" ")).cx; IMAGEINFO info; pImageList->GetImageInfo(item.iImage, &info); CRect ImageRect(info.rcImage); int nYpos = rect.top; pImageList->Draw(pDC, item.iImage, CPoint(rect.left, nYpos), ILD_TRANSPARENT); rect.left += ImageRect.Width(); } if (!IsTabEnabled(nTabIndex)) { pDC->SetTextColor(crDisabled); rect.top -= ::GetSystemMetrics(SM_CYEDGE); pDC->DrawText(label, rect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); } else { //** selected item ----- if (bSelected) pDC->SetTextColor(crSelected); else //** other item --- { if (m_bColorMouseOver && nTabIndex == m_iIndexMouseOver) { pDC->SetTextColor(m_crMouseOver); } else { pDC->SetTextColor(crNormal); } } rect.top -= ::GetSystemMetrics(SM_CYEDGE); pDC->DrawText(label, rect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); } pDC->RestoreDC(nSavedDC); } void CXTabCtrl::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //** if we should change the color of the tab ctrl --- if (m_bColorMouseOver) { SetTimer(1,10,NULL); if (m_iIndexMouseOver != -1) { CRect rectItem; GetItemRect(m_iIndexMouseOver, rectItem); if (!rectItem.PtInRect(point)) { CRect rectOldItem; GetItemRect(m_iIndexMouseOver, rectOldItem); m_iIndexMouseOver = -1; InvalidateRect(rectOldItem); return; } } if (!m_bMouseOver) { TCHITTESTINFO hitTest; m_bMouseOver = true; hitTest.pt = point; int iItem = HitTest(&hitTest); if (iItem != -1 && m_arrayStatusTab[iItem]) { RECT rectItem; GetItemRect(iItem, &rectItem); InvalidateRect(&rectItem); } } } CTabCtrl::OnMouseMove(nFlags, point); } void CXTabCtrl::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default POINT pt; GetCursorPos(&pt); CRect rectItem, rectScreen; GetItemRect(m_iIndexMouseOver, rectItem); rectScreen = rectItem; ClientToScreen(rectScreen); // If mouse leaves, show normal if (!rectScreen.PtInRect(pt)) { KillTimer (1); m_bMouseOver = false; m_iIndexMouseOver = -1; InvalidateRect(rectItem); } CTabCtrl::OnTimer(nIDEvent); } CString CXTabCtrl::getlabelname(int tabitem) { CString sText; char label[64]; TC_ITEM item; item.mask = TCIF_TEXT; item.pszText = label; item.cchTextMax = 63; GetItem(tabitem, &item); sText = label; TRACE("Labelname = " + sText + "\n"); return CString(sText); }
Header
#if !defined(AFX_XTABCTRL_H__A11951B3_2F95_11D3_A896_00A0C9B6FB28__INCLUDED_) #define AFX_XTABCTRL_H__A11951B3_2F95_11D3_A896_00A0C9B6FB28__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // XTabCtrl.h : header file // ///////////////////////////////////////////////////////////////////////////// // CXTabCtrl window #include <afxtempl.h> #include <vector> using namespace std; class CXTabCtrl : public CTabCtrl { // Construction public: CXTabCtrl(); // Attributes public: // Operations public: void AddTab(CWnd* pWnd, LPTSTR lpszCaption, int iImage =0); void CXTabCtrl::AddTab(CDialog* pWnd, LPTSTR lpszCaption, int iImage,UINT ID); void EnableTab(int iIndex, BOOL bEnable = TRUE); BOOL SelectTab(int iIndex); void DeleteAllTabs(); void DeleteTab(int iIndex); void SetTopLeftCorner(CPoint pt); BOOL IsTabEnabled(int iIndex); void SetDisabledColor(COLORREF cr); void SetSelectedColor(COLORREF cr); void SetNormalColor(COLORREF cr); void SetMouseOverColor(COLORREF cr); vector<CDialog*> m_tabs; CArray<CDialog*, CDialog*> m_tabs1; void SetAlarmColor(COLORREF cr); void SetAlarm(bool alarm); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CXTabCtrl) protected: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual void PreSubclassWindow(); //}}AFX_VIRTUAL // Implementation public: virtual ~CXTabCtrl(); // Generated message map functions protected: CArray<BOOL, BOOL> m_arrayStatusTab; //** enabled Y\N int m_iSelectedTab; POINT m_ptTabs; COLORREF m_crSelected; COLORREF m_crDisabled; COLORREF m_crNormal; COLORREF m_crMouseOver; COLORREF m_alarm; int m_iIndexMouseOver; bool m_bMouseOver; bool m_bColorMouseOver; bool m_bColorNormal; bool m_bColorDisabled; bool m_bColorSelected; bool m_balarmSelected; //{{AFX_MSG(CXTabCtrl) afx_msg void OnSelchange(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnTimer(UINT nIDEvent); //}}AFX_MSG DECLARE_MESSAGE_MAP() public: CString getlabelname(int tabitem); }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_XTABCTRL_H__A11951B3_2F95_11D3_A896_00A0C9B6FB28__INCLUDED_)
Verwendung
CXTabCtrl m_chattab; m_chattab.AddTab(new chattab(),"Name des Tabs",1,IDD_CHATDLG);