Ein Kombinationsfeld mit Werten füllen!



  • Hallo an Alle,

    würde gerne wissen, wie ich eine ComboBox mit Werten in meiner Anwendung füllen kann, also nicht über den Ressourcenassistenten, sondern zur Laufzeit.

    Hab schon versucht mit

    m_ComboBox.AddString("Bla bla"),

    geht aber nicht, der Debugger gibt einen Fehler zur Laufzeit aus. die Member_variable habe ich, wie folgt derklariert:
    Kategorienfeld:Control,
    Variablentyp:CComboBox.

    Hat einer Rat für mich, möchte auch später die gefüllten Werte zur Auswahl benutzen, um weitere Aktionen auszuführen...

    Gruss,

    chullain



  • Existiert das Fenster schon?

    Zeig mal, wo du füllst mit ein paar Zeilen drumrum.



  • SAFEARRAY *users = avobjUsers.parray;
    
    //Check the Dimension of the Array
    if ( SafeArrayGetDim(users) != 1 )
    AfxMessageBox(E_INVALIDARG); 
    
    //Get the lower and upper bounds of the array
    SafeArrayGetLBound(users, 1, &lLBoundUser);
    SafeArrayGetUBound(users, 1, &lUBoundUser);
    
    //Access the elements of the array with Objects of Type "Principal"
    for ( long cCnt = lLBoundUser; cCnt <= lUBoundUser; cCnt++ )
    {
      //local variables
      VARIANT vVal;
      CString userString;
    
      //User Name
      SafeArrayGetElement( users, &cCnt, &vVal );
      ISaGsaRpObject objUser = vVal.pdispVal;
    
      m_IUserID.AddString(objUser.GetName());
    
    }
    

    Das ist der passende Quellcode dazu, sollte eigentlich funktionieren, der Debugger stoppt jedoch an der Position mit dem AddString und gibt die Meldung: "Debug Assertion Failed!" aus...dann stürzt mein Programm ab!

    Das Kombinationsfeld ist von Typ DropDown...

    Gruss,

    chullain



  • In welcher Funktion ist der Code? Wird vorher CDialog::OnInitDialog bzw. CFormView::OnInitialUpdate aufgerufen?

    Wenn du auf das AddString einen Breakpoint setzt, hat m_lUserID ein gültiges Fensterhandle?
    Wenn ja, zeig mal den Code, wo er steht wenn er abstürzt.



  • In welcher Funktion ist der Code?

    Der Code steht in seiner eigenen Funktion, ich hab sie jetzt "OnConnect" genannt, auf jeden Fall nicht in den beiden folgenden Funktionen von Dir

    Wird vorher CDialog::OnInitDialog bzw. CFormView::OnInitialUpdate aufgerufen? ,

    ...also die beiden Funktionen, die Du oben aufgeführt hast, finde ich nicht in meiner Dialogklasse...werden diese auf jeden Fall gebraucht?
    Das Dialogfenster zeigt er mir auf jeden Fall an, weil das Objekt von diesem Fenster aus einem anderen Dialogfenster/-klasse erzeugt wird.

    Wenn du auf das AddString einen Breakpoint setzt, hat m_lUserID ein gültiges Fensterhandle?

    Ich weiss jetzt nicht, was Du genau meinst mit dem Fensterhandle, aber ich versuch es genau wie möglich Dir Informationen zu geben...
    ...nachdem ich den Breakpoint gesetzt habe, bekomme ich folgende Informationen nebenbei angezeigt, wenn er an dieser Stelle ist...

    CUserDlg::OnConnect() line 84
    CUserDlg::CUserDlg(CWnd * 0x00000000 {CWnd hWnd=???}) line 32
    CUserInfoDlg::OnConnect() line 295 + 13 bytes
    _AfxDispatchCmdMsg(CCmdTarget * 0x0012fe50 {CUserInfoDlg hWnd=0x00090608}, unsigned int 1004, int 0, void (void)* 0x004012c6 CUserInfoDlg::OnConnect(void), void * 0x00000000, unsigned int 12, AFX_CMDHANDLERINFO * 0x00000000) line 88
    CCmdTarget::OnCmdMsg(unsigned int 1004, int 0, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 302 + 39 bytes
    CDialog::OnCmdMsg(unsigned int 1004, int 0, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 97 + 24 bytes
    CWnd::OnCommand(unsigned int 1004, long 3278586) line 2088
    CWnd::OnWndMsg(unsigned int 273, unsigned int 1004, long 3278586, long * 0x0012fa3c) line 1597 + 28 bytes
    CWnd::WindowProc(unsigned int 273, unsigned int 1004, long 3278586) line 1585 + 30 bytes
    AfxCallWndProc(CWnd * 0x0012fe50 {CUserInfoDlg hWnd=0x00090608}, HWND__ * 0x00090608, unsigned int 273, unsigned int 1004, long 3278586) line 215 + 26 bytes
    AfxWndProc(HWND__ * 0x00090608, unsigned int 273, unsigned int 1004, long 3278586) line 368
    AfxWndProcBase(HWND__ * 0x00090608, unsigned int 273, unsigned int 1004, long 3278586) line 220 + 21 bytes
    USER32! 77e727cd()
    USER32! 77e7334c()
    USER32! 77e8eea3()
    USER32! 77e8c5ea()
    USER32! 77e71416()

    Sorry, das war jetzt viel Text, ich hoffe Du kannst was damit anfangen...

    ...Die Fehlermeldung während der Laufzeit ist folgende:

    Debug Assertion Failed!

    Programm:c:\...\UserInfo.exe
    File:afxwin2.inl
    Line:735



  • CUserDlg::OnConnect() line 84
    CUserDlg::CUserDlg(CWnd * 0x00000000 {CWnd hWnd=???}) line 32
    CUserInfoDlg::OnConnect() line 295 + 13 bytes
    

    Sorry, das war jetzt viel Text, ich hoffe Du kannst was damit anfangen...

    Also, eines macht mich stutzig:

    CUserDlg::CUserDlg(CWnd * 0x00000000 {CWnd hWnd=???}) line 32
    

    Du befindest dich im Konstruktor des Dialoges. Zu dem Zeitpunkt existieren die Fenster noch nicht.
    Erstell bitte eine Nachrichtenbehandlungsroute im Dialog für WM_INITDIALOG und füge dort den Aufruf für OnConnect ein. Nach dem Aufruf der Basisklasse.

    ...Die Fehlermeldung während der Laufzeit ist folgende:

    Debug Assertion Failed!

    Programm:c:\...\UserInfo.exe
    File:afxwin2.inl
    Line:735

    [/quote]
    Das ist keine Fehlermeldung sondern eine Hilfe für dich. Drück mal Wiederholen. Dann solltest du eine Begründung für das Problem finden - eine Zeile mit ASSERT.

    So, ich hab Feierabend und muss los, kannst also erst morgen wieder mit antworten rechnen.



  • Danke schon mal, ich guck mir das mal an!



  • So, nun habe ich wieder etwas mehr Ruhe als gestern. 🙂

    Du hast die Membervariable mit dem Klassenassistenten erstellt und so der Combobox zugeordnet? (Der erste Beitrag klingt etwas anders...)

    Und noch zur Erklärung:
    Alle Aktionen, für die das Control existieren muss, müssen NACH CDialog::OnInitDialog stattfinden. Dafür überschreibst du die Funktion in deinem Dialog und ruft die Basisklasse auf. (In Views gilt das analog dazu.)

    AddString, EnableWindow und sowas sind solche Aktionen. Mit fällt momentan nichts ein, wo das bei Controlsvariablen nicht der Fall ist.

    Der Konstruktor ist für diese Aktionen also der falsche Platz. ⚠



  • Vielen Dank!

    Ich hab es gestern so gemacht und es hat funktioniert...bin halt noch nicht so fit auf dem Gebiet...hab erst mit der C++-Programmierung angefangen...
    🙂
    Gruss,

    chullain



  • Sags nächstes Mal dazu, Anfängerfehler hat man selbst mal gemacht. 😃
    Dann geht das Finden schneller. 😉



  • Hallo,

    ich habe ein sehr änliches Problem wie "chullain".
    Komme aber leider mit der Erklärung von
    "estartu" für die Windowsnachricht nicht ganz klar.
    Kann mir jemand das etwas genauer erkären?

    Gruss,

    Umleag



  • Hast du OnInitDialog denn schon gefunden/erstellt?
    Es würde sicherlich helfen, wenn du
    1. zeigst, was du versuchst
    2. sagst, wo genau dein Problem ist (Absturz, Fehlermeldung?)
    🙂



  • Hallo,

    und schon einmal danke für die schnelle Antwort.
    Hier erst einmal mein C++ Code:

    BOOL CMainDialog::OnAdd() 
    {
    	// Variablen Deklarationen
    	int nIndex = pDoc->m_oaClearance.GetUpperBound();
    	CClearance* pPointer = NULL;
    	CString strClearanceCombo;
    
    	// Listeneinträge in ComboBox füllen
    	for (int i=0; i<=nIndex; i++)
    	{
    		pPointer = (CClearance*)pDoc->m_oaClearance.GetAt(i);
    		strClearanceCombo.Format("%d",pPointer->m_nClearance);
    		m_AddDlg.ClearanceCombo.AddString(strClearanceCombo);
    	} 
    
    	// Dialog anzeigen
    	m_AddDlg.DoModal();
    
    	CString strHelp;
    
    	for (i=0; i<=nIndex; i++)
    	{
    		pPointer = (CClearance*)pDoc->m_oaClearance.GetAt(i);
    
    		strHelp.Format("%d",pPointer->m_nClearance);
    		if ( m_AddDlg.m_strClearanceCombo == strHelp)
    		{
    			pDoc->m_pWorkPosition = pPointer;
    			return TRUE;
    		}
    	}
    	return FALSE;
    }
    

    Wenn ich das Problem richtig vestanden habe muß ich vor dem Aufruf von m_AddDlg erst einmal InitDialog ausführen, dazu habe ich eine WM_INITDIALOG Nachricht in die aufzurufende Klasse eingefügt leider ohne großen Erfolg. Ich fürhcte ich das irgendwie falsch verstanden.

    Das Programm stürzt während der Laufzeit mit volgender Meldung ab:

    Debug Assertion Failed!
    Programm:c:\...\UserInfo.exe File:afxwin2.inl
    Line:735

    Ich bin leider ein blutiger Anfänger ich hoffe Du kannst mir da etwas helfen.

    Gruß

    Umleag

    PS: Habe mich angemeldet und knnte mich jetzt nicht richtig einloggen
    😞



  • Also, du darfst so eine Combobox nicht von außen füllen (jedenfalls nicht bei modalen Dialogen).

    m_AddDlg.ClearanceCombo.AddString
    

    sowas geht nicht!

    Gib dem Dialog doch die Liste (bzw. das Doc) und lass ihn die in SEINER OnInitDialog füllen.
    Also diese Schleife (mit allem was nötig ist) umsiedeln:

    // Variablen Deklarationen
        int nIndex = pDoc->m_oaClearance.GetUpperBound();
        CClearance* pPointer = NULL;
        CString strClearanceCombo;
    
        // Listeneinträge in ComboBox füllen
        for (int i=0; i<=nIndex; i++)
        {
            pPointer = (CClearance*)pDoc->m_oaClearance.GetAt(i);
            strClearanceCombo.Format("%d",pPointer->m_nClearance);
            m_AddDlg.ClearanceCombo.AddString(strClearanceCombo);
        }
    

    Das Doc kannst du dir auch vom Dialog aus holen (siehe mein Artikel (Klassen einer SDI) im Magazin). 🙂
    Aber einfacher ist sicherlich eine public Variable vom Typ CDeinDoc* (bitte anpassen) und der gibst du vor DoModal pDoc.

    Okay?

    Wegen der Anmeldung guck mal nach einer Freischaltmail oder frag Marcus. 🙂



  • Hallo,

    ich hab den Dialog wie du mir beschrieben hast umgebaut, leider stürzt das
    Programm immernoch ab.

    Hier zunähst einmal der neue Code:

    Hier die aufrufende Funktion:

    BOOL CMainDialog::OnAdd() 
    {
    	// Variablen Deklarationen
    	CAddDialog AddDlg;
    	CString strHelp;
    	int nIndex = pDoc->m_oaClearance.GetUpperBound();
    	CClearance* pPointer = NULL;
    
    	// Dialog initalisieren
    	AddDlg.OnInitDialog(pDoc);
    
    	// Dialog aufrufen
    	AddDlg.DoModal();
    
    	for (int i=0; i<=nIndex; i++)
    	{
    		pPointer = (CClearance*)pDoc->m_oaClearance.GetAt(i);
    
    		strHelp.Format("%d",pPointer->m_nClearance);
    		if ( AddDlg.m_strClearanceCombo == strHelp)
    		{
    			pDoc->m_pWorkPosition = pPointer;
    			return TRUE;
    		}
    	}
    	return FALSE;
    }
    

    Die OnInitDialog Funktion inerhalb meines Dialogfedes

    // Füllt das Kombinationsfeld
    BOOL CAddDialog::OnInitDialog(CImpulseVoltageDoc* pDoc) 
    {
    	CDialog::OnInitDialog();
    
    	// Variablen Deklarationen
        int nIndex = pDoc->m_oaClearance.GetUpperBound();
        CClearance* pPointer = NULL;
        CString strClearanceCombo;
    
        // Listeneinträge in ComboBox füllen
        for (int i=0; i<=nIndex; i++)
        {
            pPointer = (CClearance*)pDoc->m_oaClearance.GetAt(i);
            strClearanceCombo.Format("%d",pPointer->m_nClearance);
            ClearanceCombo.AddString(strClearanceCombo);
        }
    
    	return TRUE;  // return TRUE unless you set the focus to a control
    	              // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurückgeben
    }
    

    Ich habe versucht der Ursche auf die schliche zu kommen konnte aber den
    Grund nicht finden: 😞

    Übrigens vielen dank für die schnelle und herzhafte Antwort und sorry das ich
    so langsam bin.

    Gruß

    Umleag

    PS: Immerhin konnte ich das Problem mit meiner Registrierung lösen 🙂
    immerhin etwas,; Peinlich 😕



  • Hmm, der Ansatz ist ja gar nicht schlecht - nur leider hat sich Microsoft das anders gedacht. 😉

    Also: Die OnInitDialog des Dialoges musst du mit dem Klassenassistenten (hast du VC6?) erzeugen und so lassen (!), die hat keinen Parameter und wird automatisch aufgerufen. Du darfst sie glaubich nichtmal selbst aufrufen.

    Also kannst du die Liste nicht von außen füllen, auch nicht per Funktionsaufruf.
    Aber, du kannst das Doc bekanntgeben.
    In der AddDialog.h

    public:
    CImpulseVoltageDoc* m_pDoc;
    

    In der AddDialog.cpp

    // im Konstruktor m_pDoc = NULL; (wichtig!)
    
    // Füllt das Kombinationsfeld
    BOOL CAddDialog::OnInitDialog(/*Parameter bitte hier und im Header löschen!*/) 
    {
        CDialog::OnInitDialog();
    
        // Variablen Deklarationen
        int nIndex = m_pDoc->m_oaClearance.GetUpperBound();
        CClearance* pPointer = NULL;
        CString strClearanceCombo;
    
        // Listeneinträge in ComboBox füllen
        for (int i=0; i<=nIndex; i++)
        {
            pPointer = (CClearance*)m_pDoc->m_oaClearance.GetAt(i);
            strClearanceCombo.Format("%d",pPointer->m_nClearance);
            ClearanceCombo.AddString(strClearanceCombo);
        }
    
        return TRUE;  // return TRUE unless you set the focus to a control
                      // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurückgeben
    }
    

    Und den Aufruf musst du so abändern:

    BOOL CMainDialog::OnAdd() 
    {
        // Variablen Deklarationen
        CAddDialog AddDlg;
        CString strHelp;
        int nIndex = pDoc->m_oaClearance.GetUpperBound();
        CClearance* pPointer = NULL;
    
        // Dialog initalisieren
        AddDlg.m_pDoc = pDoc;
    
        // Dialog aufrufen
        AddDlg.DoModal();
    
        for (int i=0; i<=nIndex; i++)
        {
            pPointer = (CClearance*)pDoc->m_oaClearance.GetAt(i);
    
            strHelp.Format("%d",pPointer->m_nClearance);
            if ( AddDlg.m_strClearanceCombo == strHelp)
            {
                pDoc->m_pWorkPosition = pPointer;
                return TRUE;
            }
        }
        return FALSE;
    }
    

    Ich hoffe, ich habe nichts vergessen. 🙂

    So, jetzt noch die Erklärung, wieso das mit dem Zusatzparameter nicht klappt:
    Microsoft hat dir in der MFC so einiges vorgefertigt. u.a. den Mechanismus, dass OnInitDialog (durch die Nachricht WM_INITDIALOG) zu dem Zeitpunkt aufgerufen wird, wo du dann alle Controls initialisieren kannst.
    Allerdings MUSS die Funktion so aussehen, wie die sich das ausgedacht haben.

    Daher musst du einem Dialog auf andere Art und Weise die Daten geben, die du anzeigen lassen willst.
    Eine wesentlich elegantere Methode wäre, den Konstruktor das Doc als Parameter mitzugeben. Dann muss die Variable auch nicht public sein (was man ja auch nicht machen soll).
    Aber erstmal muss es so laufen, dann kann man es verfeinern. 😉

    Wenn du mit dem Antworten langsam bist, kanns dir maximal passieren, dass ich im Feierabend bin. :p



  • Hallo,

    vielen Dank für den Tipp, das hat jetzt auch endlich geklappt :). Du hast mir
    wirklich sehr geholfen, an diesem Problem bin ich schon seit zwei Tagen festgehangen!

    Gruß

    Umleag

    PS: Wenn du etwas Zeit hast würde mich die feinere Variante über den Kostruktor auch sehr interessieren 😋. Ich habe leider noch nicht viel Erfahrungen mit den MFC und C++, nur mein Schulwissen 😞 .



  • Dann zeig doch mal den Konstruktor des Dialoges.
    Und dann bau ihm mal den Zeiger auf das Doc als Parameter ein.

    Ist eigentlich ganz einfach. 🙂



  • Hallo,

    ersteinmal mein Kostruktor:

    CAddDialog::CAddDialog(CWnd* pParent /*=NULL*/)
    : CDialog(CAddDialog::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CAddDialog)
    	m_strClearanceCombo = _T("");
    	//}}AFX_DATA_INIT
    }
    

    und nebenbei noch eine Frage (ohje nur Fragen 😕 ). Ich habe die Dialogklasse Vorwärtsdeklarieren müssen,
    da ich sonst eine menge Fehlermeldungen vom Kompiler erhalten habe. Muß ich das an dieser Stelle machen? Gibts da eine andere möglichkeit sowas zu machen?
    Oder ist vielleicht meine #include Anweisung falsch gesetzt(was ich vermute)?

    Hier noch der Kopf meiner AddDialog.h:

    if !defined(AFX_ADDDIALOG_H__C1C356DE_C13B_4196_AFAC_02796E4CFCB8__INCLUDED_)
    #define AFX_ADDDIALOG_H__C1C356DE_C13B_4196_AFAC_02796E4CFCB8__INCLUDED_
    
    #include "Impulse Voltage.h"
    #include "Impulse VoltageDoc.h"
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // AddDialog.h : Header-Datei
    //
    
    class CImpulseVoltageDoc; //Vorwärtsdeklaration
    
    /////////////////////////////////////////////////////////////////////////////
    // Dialogfeld CAddDialog 
    
    class CAddDialog : public CDialog
    {
    // Konstruktion
    public:
    	CAddDialog(CWnd* pParent = NULL);   // Standardkonstruktor
    
    // Dialogfelddaten
    	//{{AFX_DATA(CAddDialog)
    	enum { IDD = IDD_ADDDIALOG };
    	CComboBox	ClearanceCombo;
    	CString	m_strClearanceCombo;
    	//}}AFX_DATA
    

    Gruß
    Umleag



  • Also, erstmal zum Konstruktor:

    CAddDialog::CAddDialog(CImpulseVoltageDoc* pDoc, CWnd* pParent /*=NULL*/)
    : CDialog(CAddDialog::IDD, pParent)
    , m_pDoc(pDoc)
    {
        //{{AFX_DATA_INIT(CAddDialog)
        m_strClearanceCombo = _T("");
        //}}AFX_DATA_INIT
    // es geht auch hier ein
    // m_pDoc = pDoc;
    // such dir eines aus :)
    }
    

    Vergiß nicht, das auch im Header zu ändern.
    Nun compilier mal und dann versuch mal die Fehler mit etwas Überlegen zu beheben. 🙂
    Ist nur eine Zeile in dem Code von gestern Abend.
    Und sag noch, welche Zeile du nun weglassen kannst.

    Wegen der Includerei:
    Die Forwarddeklaration kann hier schon nötig sein, weil es sonst einen Ringinclude geben dürfte.
    Lass es ruhig so, wenn ein normales Include nur Fehler gibt.


Anmelden zum Antworten