Wert aus Combo in OnSelchangeCombo1() verwenden



  • Polofreak schrieb:

    hm OK aber irgendwie muss ich immernoch +2 machen weil er sonst nicht auf dem richtigen Datensatz ist.

    Zeig mal den Code bitte.



  • WOW Respekt! Aber für was mache ich dann die ganze Scheiße mit SetItemdata, das würde ja bedeuten sobald ich einen raus nehme stimmt ja gar nichts mehr, dann entspricht das ja gar nicht mehr meiner DB! Naja gut egal dann lösch ich entweder nichts raus oder ich mach danach halt immer ein Load auf das COmbo. Vielen Dank Isbeau und Estartu_de



  • Hm wenn du jetzt noch den Fehler findest küss ich dir die Füsse

    void CDokumentenVerwaltungView::loadPCD()
    {
    	CDBVariant varValue;
    
    	UpdateData(TRUE);
    
    	short nFields = m_pSet->GetODBCFieldCount();
    
    	for( short index = 0; index < nFields; index++ )
    		{
    			m_pSet->MoveFirst();
    			while (!m_pSet->IsEOF())
    			{
    				m_pSet->GetFieldValue( index, varValue );
    				 //Merken, an welche Position es geschrieben wird (wegen evtl. Sortieren oder so) 
    				int nIdx = m_PCD_CMB.AddString(*(varValue.m_pstring));
                    m_PCD_CMB.SetItemData(nIdx,m_pSet->m_ID); 
    
    				m_pSet->MoveNext();
    			}
    			if (m_pSet->IsEOF())
    			{
    				m_pSet->MoveFirst();
    				break;
    			}
    		}
    
    	UpdateData(FALSE);
    
    }
    
    void CDokumentenVerwaltungView::OnSelchangeCombo1() 
    {
    	int Test= m_PCD_CMB.GetCurSel(); 
    	if (Test != -1) // es muss was gewählt sein 
    	{ 
    	    int nID = m_PCD_CMB.GetItemData(Test); 
    	} 
    	m_pSet->SetAbsolutePosition( Test+2 );
    	selectedPCD = m_pSet->m_PCD_NR;
    	selectedAnweisungsindex =m_pSet->m_Anweisungsindex;
    	m_Selected = m_pSet->m_PCD_NR;
    	isSelected =TRUE;
    	UpdateData(FALSE);
    }
    

    aber mach dir nicht zu viel mühe, ich mein für das was ich bisher damit mach reicht es eigentlich auch. Wenn du den Fehler aber findest wäre ich dir dennoch super riesig Dankbar!



  • *seufz* Wenn ich ne neue Variable mache, wo das rein kommt, was du suchst - dann benutz sie doch auch...

    void CDokumentenVerwaltungView::OnSelchangeCombo1()
    {
        int Test= m_PCD_CMB.GetCurSel();
        if (Test != -1) // es muss was gewählt sein
        {
            int nID = m_PCD_CMB.GetItemData(Test);
            m_pSet->SetAbsolutePosition(nID);
            selectedPCD = m_pSet->m_PCD_NR;
            selectedAnweisungsindex =m_pSet->m_Anweisungsindex;
            m_Selected = m_pSet->m_PCD_NR;
            isSelected =TRUE;
            UpdateData(FALSE);
        }
    }
    

    Okay, jetzt auch die versprochene Erklärung:
    Ein Eintrag einer Combobox besteht nicht nur aus der Zeichenkette, die du sehen kannst.
    Du kannst auch einen Zeiger (Get-/SetItemDataPtr) oder eine Zahl (Get-/SetItemData) an einen Eintrag anhängen. (Ob beides gleichzeitig geht, habe ich noch nicht probiert.)

    Mit AddString hängst du ja einen neuen Eintrag in die Combobox. Wenn die jetzt aber sortiert wird oder du was löschst, dann weißt du ja den Index nicht (haste ja gemerkt).

    Wenn du nun aber deine ID aus der Datenbank mit anhängst, hast du etwas absolutes, den auch egal ist, in welcher Reihenfolge die Zeichenketten stehen. Das passt immer!

    Ich habe dafür eine eigene Comboboxklasse (du erinnerst dich an die Codeschnipsel von neulich?) die machen dir den Kram mit der ID etwas leichter.

    Nun solltest du aber noch eines beherzigen:
    In deinem Recordset ist NICHT unbedingt gewärleistet, dass der Datensatz mit der ID 3 auch an dritter Stelle steht. Spätestens wenn einer gelöscht wurde oder du die Sortierung änderst, klappt das nicht mehr.
    Bau also am besten eine Suchfunktion mit "Positionierung" des Cursors (also dass er auf dem gefundenen Datensatz steht, wenn er fertig ist) ein.

    Ich hab die hier in meiner Recordsetbasisklasse:

    // ------------------------------------------------------------------------------------------------
    // Gibt true zurück, wenn ein Datensatz mit der gegebenen ID gefunden wurde.
    // Lässt sich also zur "Vorhandenheitsprüfung" und zur Cursor Positionierung nutzen.
    // ------------------------------------------------------------------------------------------------
    bool CBasisSet::Suche(long f_lID)
    {
    	bool fReturn = false;
    
    	// Stimmt die Kombination?
    	if (m_lID == f_lID) 
    	{
    		// Die ID merken
    		fReturn = true;
    	}
    	else
    	{
    		// Einmal über alle Datensätze laufen
    		if (IsBOF())
    		{
    		}
    		else
    		{
    			// Vorne anfangen
    			MoveFirst();
    			while((!IsEOF()) && (!fReturn))
    			{
    				// Stimmt die Kombination?
    				if (m_lID == f_lID) 
    				{
    					// Die ID merken
    					fReturn = true;
    				}
    				if (!fReturn)
    				{
    					MoveNext();
    				}
    			}
    		}
    	}
    
    	return fReturn;
    }
    

    Okay? 🙂



  • Erst mal vielen lieben dank für deine ausfürliche Beschreibung, mir ist so einiges klar geworden. Ich hab auch schon ne Suchfunktion, die ein wenig anders aussieht wie deine aber in meinen Augen schon so ziemlich das gleiche macht.

    void CDokumentenVerwaltungView::suchen(CString Anfrage)
    {
    	bool Suchergebnis=FALSE;
    	CDBVariant varValue;
    
    	UpdateData(TRUE);
    
    	short nFields = m_pSet->GetODBCFieldCount();
    
    	for( short index = 0; index < nFields; index++ )
    		{
    			m_pSet->MoveFirst();
    			while (!m_pSet->IsEOF())
    			{
    				m_pSet->GetFieldValue( index, varValue );
    				if (m_pSet->m_PCD_NR == Anfrage)
    				{
    					Suchergebnis = TRUE;
    					selectedPCD = m_pSet->m_PCD_NR;
    					selectedAnweisungsindex =m_pSet->m_Anweisungsindex;
    					isSelected =TRUE;
    					break;
    				}
    				m_pSet->MoveNext();
    			}
    			if (m_pSet->IsEOF())
    			{
    				m_pSet->MoveFirst();
    				break;
    			}
    		}
    
    		if (!Suchergebnis)
    		 MessageBox("Die angeforderte Nummer ist nich vorhanden !","ERROR",MB_ICONERROR); 
    
    	UpdateData(FALSE);
    }
    

    aber was hat das andere mit meiner Suchfunktion zu tun, naja bzw. wie beeinflusst das meine Comboboxfüllung?? wo oder wie muss ich die aufrufen?
    P.S.: jetzt geht es echt super!! (hab aber auch noch nichts gelöscht



  • Ja, die macht das selbe, nur eben mit einer Zeichenkette und einem kleinen Nachteil:
    Stell dir vor, du hast eben etwas gefunden, das ist der letzte Datensatz.
    Nun suchst du das gleich nochmal.
    So, wie du das machst, fängt der blind wieder vorne an und rennt bis ganz hinten.

    Ich habe das erst vor ein paar Tagen eingebaut, mit der Zusatzprüfung - das spart ENORM viel Zeit. 😮

    Die Suche nach der ID brauchst du, weil das SetAbsolutePosition ja nicht stimmen muss. (s.o.)
    Also statt

    m_pSet->SetAbsolutePosition(nID);
    

    besser

    m_pSet->Suche(nID);
    

    🙂

    Noch ein kleiner Hinweis in Sachen Klassendesign:
    Pack das suchen besser in die Recordsetklasse. Sonst musst du das, wenn du es an einer anderen Stelle (in einem anderen View) brauchst, nochmal tippen bzw. kopieren. Sowas ist unschön, wartungshemmend und sehr fehleranfällig. ⚠
    (Oder hast du da Sachen drin, die unbedingt im View passieren müssen und nicht ausgelagert werden können?)



  • A L S O!!
    Ich habe jetzt meine Suche angepasst, dass ich auch nach ner ID suchen kann. Problem war nämlich ich hab ja immer nur eine Spalte mit dem Suchwert verglichen denn ích hab mehrere Spalten, wo z.B. 2 drin vor kommt. naja egal das geht ja auch alles ABER. Ich hab mal Spasseshalber einen Datensatz raus gelöscht und ans Ende mit ner neuen ID eingefügt, und ich hab genau das von dir angesprochene Problem, und das ohne dass ich moveabsoluteposition mach, sondern suchen (ID). Woran liegt das denn schon wieder ??



  • Zeig den Quellcode bitte.

    Einmal vom suchen(id) und einmal, wie du es aufrufst. 🙂



  • öhm ich hab mir mal angeschaut was du sehen willst, und mir ist schon klar wo der fehler sitzt. Also:

    void CDokumentenVerwaltungView::suchen(CString Anfrage, CString typ)
    {
    	bool Suchergebnis=FALSE;
    	CDBVariant varValue;
    
    	UpdateData(TRUE);
    
    	short nFields = m_pSet->GetODBCFieldCount();
    
    	for( short index = 0; index < nFields; index++ )
    		{
    			m_pSet->MoveFirst();
    			while (!m_pSet->IsEOF())
    			{
    				m_pSet->GetFieldValue( index, varValue );
    
    				if (typ=="ID")
    				{
    					int i = atoi(Anfrage);
    					if (m_pSet->m_ID == i)
    					{
    						Suchergebnis = TRUE;
    						break;
    					}
    				}
    				m_pSet->MoveNext();
    			}
    			if (m_pSet->IsEOF())
    			{
    				m_pSet->MoveFirst();
    				break;
    			}
    		}
    
    		if (!Suchergebnis)
    		 MessageBox("Die angeforderte Nummer ist nich vorhanden !","ERROR",MB_ICONERROR); 
    
    	UpdateData(FALSE);
    
    }
    

    und dann noch

    int nID =0;
    	nID = m_PCD_CMB.GetCurSel(); 
    	if (nID != -1) // es muss was gewählt sein 
    	{ 
    	    nID = m_PCD_CMB.GetItemData(nID); 
    	} 
    	suchen(nID,"ID");//Die Funktion erwartet ja aber einen String, muss ich das casten?
    //also wenn ich "7" schreibe macht er mir tatsächlich das Feld mit dem Index 7 auf
    

    🙄 🙄 🙄 kann ich nur über mich selbst mit den Augen rollen, da fehlt mir immer wieder grundlegendes



  • Wieso machst du das so "komisch"?
    Also, warum gibst du den Feldnamen mit - wo es doch eh keine andere Möglichkeit zu geben scheint (oder soll das noch kommen?).

    Naja, ein Vorschlag meinerseits wäre: Du überlädst die Funktion. 🙂
    Kurze Grundlage: Es kann pro Klasse mehrere Funktionen mit dem selben Namen geben, die Parameter müssen sich aber unterscheiden. (Der Rückgabetyp ist leider kein Unterschied.)
    Du kannst also ein
    suchen(int id)
    und ein
    suchen(CString Anfrage)
    haben.

    Und entweder kümmerst du dich da drinne um die Umwandlung in CString - oder du sucht da, dann kannst du dir auch das atoi sparen.

    Okay? 🙂

    PS:

    CString strZahl;
    strZahl.Format("%d");
    


  • hm mehr oder weniger Okay ich hab die ganzen anderen If abfragen raus genommen weil die ja in dem Moment nicht interessieren, ich hab sonst schon noch mehr drin. Aber das mit dem Überladen, naja dann hab ich ja aber nachher 6 suchen Funktionen. So hab ich nur eine und hau da halt den suchtyp mit rein (macht man das aus Programmesthetischen Gründen nicht?) naja ich schau mal morgen früh nochmal denn für heute mache ich feierabend, es hat ja doch kein wert mehr heute.
    Vielen Dank Estartu_de



  • Dann schönen Feierabend - morgen früh ist auch der Kopf wieder frei. 🙂

    Das mit dem Überladen würde das Konvertieren sparen.
    Ich gucke mal, in welchem Buch ne Erklärung dazu war...



  • bist echt ein schatz dir auch nen schönen Feierabend und bis morgen



  • Guten Morgen!

    Also, ich habe in zwei meiner Bücher was gefunden.
    Die C++-Programmiersprache | ISBN: 3827320585
    Kapitel 7.4 erklärt das sehr ausführlich. Das Buch gibt es hin und wieder als Special Edition und dann ist es recht billig, schau dich mal um, das ist DAS Standardwerk für C++.
    OOP mit C++ | ISBN: 3898423328
    Das Buch hat nur doppelseitige Kapitel, ist also als Nachschlagewerk genial. Ich fasse das Kapitel mal kurz zusammen:

    Oft braucht man mehrere Funktionen, die mit verschiedenen Parametern das "Gleiche" tun, z.B. das Minimum von Zahlen zurückgeben. Da gibt es ja ganze Zahlen und Kommazahlen.
    In C++ kann man (und manchmal sollte man auch) verschiedenen Funktionen den gleichen Namen geben:

    int min(int x, int y);
    double min(double x double y);
    

    Die Funktionen werden anhand ihrer "Signatur" unterschieden. Das sind die Typen und die Anzahl der Parameter.
    Der Rückgabetyp einer Funktion gehört nicht zur Signatur.

    So, das war jetzt die ultrakurze Version. Nun musst du fragen. 🙂



  • Das mit dem Kopf frei hat voll und ganz hingehauen, ich hab mir das heute morgen nochmal angeschauen, deine Ratschläge beherzigt, und schon geht es sowas von einwandfrei, und ich habe bemerkt dass ich so auch die Stringsuche gar nicht brauche! Ich hatte ursprünglich anstelle der Combo ein Edit Feld, und drum musste ich auf Strings suchen, jetzt kann ich aber gleich auf die IDs suchen und wenn ich das schön durchziehe, gibt es in meiner Anwendung keinen Drund nach Strings zu suchen (naja bisher zumindest). Wie fange ich jetzt aber am besten ne Falscheingabe des Combos ein? Es kann doch jetzt jemand nen Scheiß in die Combo tippen (statt auswählen) und dann bekomm ich das ja gar nicht mit.

    Kann ich das irgendwie machen wie bei der Klassenauswahl im Klassenassi, dass sobald ich ne 2 eingib er gleich die ganzen Werte wo vorn ne 1 steht überspringt und zum ersten Wert der an erster Stelle ne zwei hat springt??
    Wie kann ich elegant ne Standard auswahl machen? (OnInit den Index eintragen??)



  • Polofreak schrieb:

    Wie fange ich jetzt aber am besten ne Falscheingabe des Combos ein? Es kann doch jetzt jemand nen Scheiß in die Combo tippen (statt auswählen) und dann bekomm ich das ja gar nicht mit.

    Kann ich das irgendwie machen wie bei der Klassenauswahl im Klassenassi, dass sobald ich ne 2 eingib er gleich die ganzen Werte wo vorn ne 1 steht überspringt und zum ersten Wert der an erster Stelle ne zwei hat springt??

    Das kannst du mit ein paar einfachen Mausklicks erschlagen:
    Im Resourceeditor ie Eigenschaften der Combobox aufmachen, Tab Formate anklicken und in der oberen Combobox "Dropdown-Listenfeld" auswählen.
    Fertig. 😃
    Leider kann man das nicht als Standard festlegen, ich nutze NUR diesen Typ.

    Polofreak schrieb:

    Wie kann ich elegant ne Standard auswahl machen? (OnInit den Index eintragen??)

    Fast. Mach ein SetCurSel in OnInitDialog. 🙂



  • Genau das wollte ich! Klasse vielen Dank Estartu_de hast mir mal wieder richtig auf die Beine geholfen, doch laufen versuch ich jetzt selbst!
    😃 🙂 😃 🙂


Anmelden zum Antworten