Extended ComboBox mit Strings füllen



  • Halle zusammen!

    Würde mich aktuell noch als C++-Anfänger bezeichnen - habe es als Leistungskurs in der Schule, seit zwei Jahren. Haben vor kurzen mit MFC angefangen und nun einen Wecker pogrammiert. Hier bei wollte ich nun eine Extended ComboBox als Dropdown Listenfeld hinzufügen, um eine Songauswahl zu erstellen, nur scheitere ich bereits am einfügen der Strings in die ComboBox. Ich nutze übrigens Visual Studio 2010 Ultimate. Wollte das ganze in der Methode OnInitDialog() machen und habe dazu eine Variable von Typ CComboBoxEx (m_Wahl) angelegt. Anschließend wollte ich folgende Methode benutzen:

    UpdateData(true);
    m_Wahl.AddString(L"Sonnentanz");
    UpdateData(false);
    

    Spuckt zwar keine Fehlermeldung aus, lässt das Programm allerdings abstürzen.

    Das Ganze soll vorerst ohne Funktion sein, will da nur 3 - 5 verschiedene Strings drin stehen haben, die mal per Klick in der ComboBox auswählen kann. Was möglich ist ist, dass man eine Variable vom Typ CString hinzufügt und dieser einen Wert gibt, allerdings wird dann nur diese eine einzige Sache in das Feld geschrieben und nicht in die "ComboBox-Liste angehangen".

    Hoffentlich kann mir jemand helfen. 😕



  • Hast Du vor dem Aufruf von AddString() die Basisklassenmethode OnInitDialog() bereits aufgerufen?

    Ist aber nur geraten das ganze ...

    BOOL MyDialog::OnInitDialog() 
    {
      BOOL result = __super::OnInitDialog()
      UpdateData(true);
      m_Wahl.AddString(L"Sonnentanz");
      UpdateData(false);
      return result;
    }
    


  • Der Aufruf befindet sich in der Methode OnInitDialog().
    Ganz unten. Wenn ich das richtig verstanden habe, wird OnInitDialog() einmalig beim Start des Programms aufgerufen, sollte also der erste Aufruf sein.

    BOOL CMy04_AufgWeckerDlg::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    
    	// Hinzufügen des Menübefehls "Info..." zum Systemmenü.
    
    	// IDM_ABOUTBOX muss sich im Bereich der Systembefehle befinden.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		BOOL bNameValid;
    		CString strAboutMenu;
    		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    		ASSERT(bNameValid);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Symbol für dieses Dialogfeld festlegen. Wird automatisch erledigt
    	//  wenn das Hauptfenster der Anwendung kein Dialogfeld ist
    	SetIcon(m_hIcon, TRUE);			// Großes Symbol verwenden
    	SetIcon(m_hIcon, FALSE);		// Kleines Symbol verwenden
    
    	// TODO: Hier zusätzliche Initialisierung einfügen
    	GetDlgItem(IDC_Aus)->EnableWindow(0);
    	GetDlgItem(IDC_Ein)->EnableWindow(1);
    	GetDlgItem(IDC_Stop)->EnableWindow(0);
    	GetDlgItem(IDC_CheckIt)->EnableWindow(0);
    	GetDlgItem(IDC_Wecker)->EnableWindow(0);
    
    	UpdateData(true);
    
    	m_Wahl.AddString(L"Sonnentanz");
    
    	UpdateData(false);
    
    	return TRUE;  // TRUE zurückgeben, wenn der Fokus nicht auf ein Steuerelement gesetzt wird
    }
    


  • Hast du m_Wahl mit der ID der Combobox verknüpft?
    In DoDataExchange:

    DDX_Control(pDX, IDC_DEINE_COMBOBOX, m_Wahl);
    


  • Ja, macht Visual Studio automatisch, wenn man den Wizard zum erstellen von Variablen benutzt. (Wieder ganz unten)

    void CMy04_AufgWeckerDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialogEx::DoDataExchange(pDX);
    	DDX_Text(pDX, IDC_Uhrzeit, m_Zeit);
    	DDX_Control(pDX, IDC_stunden, m_Stunden);
    	DDX_Control(pDX, IDC_minuten, m_Minuten);
    	DDX_Control(pDX, IDC_PROGRESS3, m_Sekunden);
    	DDX_Text(pDX, IDC_Wecker, m_Weckzeit);
    	DDX_Check(pDX, IDC_CheckIt, m_check);
    	DDX_Control(pDX, IDC_Wahl, m_Wahl);
    }
    

    Hier der Programmabsturz:
    http://bilderupload.de/bild.php/117980,unbenanntGKD7G.png



  • Also ich verwende bei der ComboboxEx immer InsertItem. Schon deswegen, weil ich mit AddString keine Bilder hinzufügen kann. Versuch mal statt deinem AddString folgenden Code:

    COMBOBOXEXITEM boxItem;
    
    boxItem.cchTextMax = csText.GetLength();
    boxItem.pszText = csText.GetBuffer(0);
    boxItem.iItem = 0;
    boxItem.mask = CBEIF_TEXT;
    m_Wahl.InsertItem(&boxItem);
    

  • Mod

    Lass das programm im Debuggerlaufen.
    Wo stürzt es ab? So sehe ich hier keinen Fehler.
    Wenn es abstürzt was ist Dein Code, der ausgeführt wird (schu in den Callstack).



  • Er geht als erstes in die Methode AddString() in der Datei afxcmn2.inl.

    351_AFXCMN_INLINE int CComboBoxEx::AddString(LPCTSTR lpszString)
    352	{ UNUSED_ALWAYS(lpszString); ASSERT(FALSE); return CB_ERR;}
    

    Anschließend springt er von da in folgende Methode:

    BOOL AFXAPI AfxAssertFailedLine(LPCSTR lpszFileName, int nLine)
    {
    #ifndef _AFX_NO_DEBUG_CRT
    	// we remove WM_QUIT because if it is in the queue then the message box
    	// won't display
    	MSG msg;
    	BOOL bQuit = PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE);
    	BOOL bResult = _CrtDbgReport(_CRT_ASSERT, lpszFileName, nLine, NULL, NULL);
    	if (bQuit)
    		PostQuitMessage((int)msg.wParam);
    	return bResult;
    #else
    	// Not supported.
    #error _AFX_NO_DEBUG_CRT is not supported.
    #endif // _AFX_NO_DEBUG_CRT
    }
    

    Da springt im oberen Teil dieser Methode, in irgendeine andere, von dem ich absolut nichts verstehe und in irgendwelche Dateien springt, die er mir nicht anzeigen kann. Ich lade das Projekt einfach mal hoch, verpackt in einer .rar. Vielleicht mag es sich ja einer von euch mal genauer anschauen und findet meinen Fehler - oder was auch immer es ist. 🙂
    Download Link (Dropbox)
    Es kommt kein Lied, da ich die Zeile auskommentiert habe und das Lied aus dem Ordner gelöscht habe, da er sonst rund 30mb gehabt hätte. Könnte ihr aber gerne mit einem eigenen Lied ausprobieren. 😃 .mp3 bringt das Programm eigenartiger Weise zum abstürzen, nehmt also .wav - das funktioniert.

    Hoffe ihr findet so etwas heraus.



  • Hatte vorhin, aufgrund von Source2702s Antwort, auch noch folgende Methoden benutzt:

    m_Wahl.InsertString(1, L"Sonnentanz");
    

    und

    m_Wahl.InsertItem(0);
    

    Beides ohne Erfolg. Immer wieder der selbe Programmabsturz - ohne Fehlermeldung im Visual Studio. Hat schon jemand etwas mit meinem Projekt anfangen können?



  • Huhu?



  • CComboBoxEx unterstützt AddString nicht. Verwende CComboBox oder guck dir den letzten Post von Source2702 noch mal an.



  • Das ist falsch: "CComboBoxEx unterstützt AddString nicht"

    class CComboBoxEx : public CComboBox
    

    Und deshalb hat CComboBoxEx eine Methode AddString.
    Vs2010 bietet diese auch in der Vervollständigung an.



  • Nur zur Ergänzung von wem alles CComboBoxEx erbt:

    Base Class Members
    CObject Members
    CCmdTarget Members
    CWnd Members
    CComboBox Members
    Quelle MSDN



  • @noergel

    schaust du die definition von CComboboxEx an

    class CComboBoxEx : public CComboBox
    {
    	DECLARE_DYNAMIC(CComboBoxEx)
    
    // Constructors
    public:
    	CComboBoxEx();
    
    	// Generic creator
    	virtual BOOL Create(_In_ DWORD dwStyle, _In_ const RECT& rect, _In_ CWnd* pParentWnd, _In_ UINT nID);
    
    	// Generic creator allowing extended style bits
    	virtual BOOL CreateEx(_In_ DWORD dwExStyle, _In_ DWORD dwStyle, _In_ const RECT& rect,
    		_In_ CWnd* pParentWnd, _In_ UINT nID);
    
    // Operations
    	using CComboBox::DeleteItem;
    	int DeleteItem(_In_ int iIndex);
    	BOOL GetItem(_Out_ COMBOBOXEXITEM* pCBItem);
    	int InsertItem(_In_ const COMBOBOXEXITEM* pCBItem);
    	BOOL SetItem(_In_ const COMBOBOXEXITEM* pCBItem);
    
    // Attributes
    	BOOL HasEditChanged();
    	DWORD GetExtendedStyle() const;
    	DWORD SetExtendedStyle(_In_ DWORD dwExMask, _In_ DWORD dwExStyles);
    	CEdit* GetEditCtrl() const;
    	CComboBox* GetComboBoxCtrl() const;
    	CImageList* GetImageList() const;
    	CImageList* SetImageList(_In_ CImageList* pImageList);
    
    #if (_WIN32_WINNT >= 0x0501)
    	AFX_ANSI_DEPRECATED HRESULT SetWindowTheme(_In_z_ LPCWSTR pszSubAppName);
    #endif
    
    	// These functions are supported by the Windows ComboBox control,
    	// but not supported by the Windows ComboBoxEx control.
    
    	int Dir(_In_ UINT attr, _In_z_ LPCTSTR lpszWildCard);
    	int FindString(_In_ int nIndexStart, _In_z_ LPCTSTR lpszFind) const;
    	int AddString(_In_z_ LPCTSTR lpszString);
    	BOOL SetEditSel(_In_ int nStartChar, _In_ int nEndChar);
    	int InsertString(_In_ int nIndex, _In_z_ LPCTSTR lpszString);
    
    // Implementation
    public:
    	virtual ~CComboBoxEx();
    };
    

    und wie kann man da lesen

    // These functions are supported by the Windows ComboBox control,
    // but not supported by the Windows ComboBoxEx control.

    was soviel bedeutet wie das es nicht unterstützt wird???????

    soviel zum erben von klassen

    also ist dann nur die Möglichkeit mit InsertItem los zu machen, wobei wenn man das öfters braucht, kann man natürlich anpassen mit einer eigenen Funtion die dann auch nur den string als übergabe braucht

    @TE
    aber warum reicht dir nicht ein einfaches CComboBox?



  • Stimmt. Ich lag falsch.
    Habe den Remark nicht gelesen.
    http://msdn.microsoft.com/de-de/library/x9y44b47%28v=vs.80%29.aspx


  • Mod

    Wie wäre es mit Doku lesen?

    1. EIn ASSERT ist kein Absturz sondern eine Warnung das Du etwas nihct korrekt benutzt.
    2. CComboBoxEx unterstützt AddString nicht.
    Siehe auch Doku im MFC Source Code knapp über Deiner Assert Stelle.
    3. InsertItem muss eine gültige Struktur übergeben werden.
    Warum machst Du es nicht wie es Source702 Dir scon geschrieben hat?



  • Oh, ja. Hat funktioniert! Vielen Dank.
    Wie gesagt, würde mich noch als Anfänger beschreiben - verstehe auch nicht alles auf Anhieb..
    Ich möchte jetzt ja wie beschrieben um die 6 - in diesem Fall jetzt Items - einfügen, wie mache ich das am besten, ohne dass ich immer wieder den Code wiederholen muss? Die Länge des Strings kann ich ja einmal auf 20 packen und muss dann nur aufpassen, dass der String diese Länge nicht überschreitet.

    Eine weitere Frage: Wie kann ich die ComboBox von Anfang größer machen? So ist es doch schon etwas lästig...
    http://img195.imageshack.us/img195/8620/eyyo.png


  • Mod

    Du basut eine Schleife über einen Array von Strings oder oder oder



  • Ja, da bin ich auch drauf gekommen. Wie sieht es mit meinem Problem mit der Größer/dargestellten Länge der ComboBox aus?


  • Mod

    Hast Du as COntrol selbst erzeugt? Bei einer COmbobox muss man das COntrol in der Größe erzeugen, die die Dropdown Box haben soll.
    Wenn Du es über den Ressourceneditor gemacht hast. Klick auf den Dropdown Schalter und die die Box auf die Größe, die Du möchtest.


Anmelden zum Antworten