Dwie kolumny w ComboBox – wyświetlanie jednej kolumny a odwołanie się do drugiej

0

Cześć,

muszę zmodyfikować część kodu w C++ Builder 6.
Zetknąłem się z takim problemem. W wyniku zapytania SQL mam dwie kolumny np:

ID Values
1 one
2 two
3 three

chcę je wrzucić do ComboBox-a (dalej cbx1) i tutaj jest pierwszy problem bo wiem jak wrzucić pojedynczą kolumnę ale nie wiem jak podwójną. Powiedzmy że w cbx1 chcę wyświetlić wartości one, two, three ale jak jakaś wartość zostanie wybrana to dalej operować na wartościach ID czyli 1,2 lub 3.

google nie wiele pomógł tym bardziej że nie jestem za bardzo anglojęzyczny :)

0

Nie pamiętam jak to jest dokładnie w BCB6, Ale postaram Ci się doradzić. Po pierwsze zwykły ComboBox nie umie w standardzie listować w dwóch kolumnach. Jeśli Ci na tym zależy to albo napisz własne rysowanie kontrolki (żmudne rozwiązanie) albo kup/poszukaj darmowego na torry.net jakiegoś zewnętrznego komponentu (szybkie rozwiązanie).

Jednak chciałbym Cię odwieźć od takiego rozwiązania, po co user ma widzieć jakieś ID? TComboBox może przechowywać wskaźnik na TObject i dostęp do niego masz za pomocą cbx1->Items->Objects[i] Wystarczy korzystać podczas dodawania do komponentu itemów z metody cbx1->AddItem(). Tylko uwaga wrzucając pozycję musimy rzutować w kierunku int -> TObject* a pobierając odwrotnie.

A teraz jak to wszystko ogarnąć. Dodawanie wartości:

  cbx1->Items->Clear();
  cbx1->AddItem("Jeden",(TObject*)12);
  cbx1->AddItem("Dwa",(TObject*)1);
  cbx1->AddItem("Trzy",(TObject*)100);
  cbx1->ItemIndex = 0;

Oraz odczyt ID powiązanego z danym itemem:

  int ID;
  ID = (int)(cbx1->Items->Objects[cbx1->ItemIndex]);
  ShowMessage(ID);

Ewentualnie jeśli nie chcesz szukać nowego komponentu, a chcesz w prosty sposób pokazać ID'ki rekordów w bazie formatuj napis dodawany do ComboBoxa:

  cbx1->Items->Clear();
  cbx1->Items->Add("12 - Jeden");
  cbx1->Items->Add("1 - Dwa");
  cbx1->Items->Add("100 - Trzy");
  cbx1->ItemIndex = 0;

I potem sobie ręcznie wycinaj, parsuj itp wybrany tekst.

PS. użyłem z lenistwa rzutowania w stylu C. Żeby być bardziej eleganckim warto użyć odpowiedniego rzutowania w stylu C++

0

Dzięki ! Super !

Wszystko działa jak chciałem :)

0

Pewnie zwyczajny tabulator takie coś załatwi.

0

@mr.YaHooo mam jeszcze jeden zgryz. Wszystko zadziałało na danych wklepanych z palucha czyli np.

cbx1->AddItem("Jeden",(TObject*)12);

ale jak już chciałbym wrzucić dane z zapytania to nie może mi przejść konwersji

cbx1->AddItem(DataSet1->DataSet->Fields->Field[0]->AsString,(TObject*)zmienna_typu_string);

jak zrobię coś takiego to otrzymuję komunikat

Cannot cast from 'AnsiString' to 'TObject'

ale tak już działa

cbx1->AddItem(DataSet1->DataSet->Fields->Field[0]->AsString,(TObject*) "jakaś wartość" );

nie rozumiem dlaczego tak jest że jak wpiszę coś z palucha "jakaś wartość" o typie string to działa a jak wrzucę tam zmienną typu string to się wywala.

próbowałem także z intem ale też były błędy konwersji

0

@wil: nie, nie zadziałają tabulatory.

@forritarik nie da się rzutować AnsiStringa na wskaźnik ponieważ to nie jest typ prosty, a obiekt. Ja zmieniałem int na wskaźnik, który można przyjąć, że też jest jest liczbą (dokładniej mówiąc numerem komórki pamięci w której znajduje się zmienna). Dlatego konwersja taka udaje się. Natomiast w przypadku obiektu jakim jest AnstString taka konwersja nie jest możliwa ponieważ nawet rozmiary się nie zgadzają.

Druga wersja (kompilująca się) polega na tym, że stałe znakowe w C to po prostu tablice znaków. A w C tablica jest utożsamiana ze wskaźnikiem na pierwszy element. Dla łatwiejszego zobrazowania można to napisać tak):

  char* temp = "jakaś wartość";
  cbx1->AddItem("txt",(TObject*)temp);

Zatem mamy tu po prostu rzutowanie ze wskaźnika na tablicę znaków na wskaźnik na TObject, a taka konwersja jest łatwa do wykonania. Podczas przekazywania napisu "jakas wartosc" jest tworzona tymczasowa zmienna wskazująca na znajdujący się gdzieś napis "jakas wartosc". Analogicznie jak w przypadku przekazywania np int'a do funkcji.

0

Tabulatory działają w listbox, zatem musisz wyciągnąć handle do listbox z tego combo, no i tam ustalić tabulację.
A potem dodajesz zwyczajnie stringi w stylu: "kolumna1\t kolumna2\t kolumna3".

Ewentualnie 'ownerdraw' może to załatwić bezproblemowo, co jest też łatwiutkie: wystarczy narysować trochę tekstu: ExtTextOut...

0

@wil Ok to pokaż jak użyć \t bo u mnie nie działa
screenshot-20180703203803.png

Co do ręcznego rysowania ok, ale po co się męczyć potem z dzieleniem stringa na części, zamianę jednej części na int. Droga na około i bez sensu skoro sam Delphi'owy TComcoBox udostępnia adekwatny mechanizm w postaci listy wskaźników na obiekty.

0

https://docs.microsoft.com/en-us/windows/desktop/controls/list-box-styles

najwyraźniej dla listbox należy użyć flagi: LBS_USETABSTOPS

0

No to było tak napisać na początku, a nie pisać półsłówkami... Poza tym i tak jak wcześniej napisałem rozwiązanie średnie ponieważ bez sensu jest trzymanie tego w napisie, a potem rozbijanie cele wyłuskania żądanych danych ponieważ elementy graficzne nie służą przetrzymywaniu danych.

0

Sam tworzysz cuda na patyku, więc ci podaję jak to działa.
Do list z kolumnami służy ListView, a nie prosty Listbox, czy combo.

Generalnie możesz sobie narysować co chcesz, ale to wymaga trochę programowania... samo klikanie nie wystarczy, niestety.

0
wil napisał(a):

Sam tworzysz cuda na patyku, więc ci podaję jak to działa.

Ja tylko korzystam z funkcjonalności jaką udostępnia VCL, więc nie za bardzo rozumiem jakie cuda na patyku masz na myśli? Lepsze to niż trzymanie na formatce tablicy intów z ID'kami rekordów, ponieważ to są cuda na patyku :)

Do list z kolumnami służy ListView, a nie prosty Listbox, czy combo.

Nie do końca. Czasem potrzeba wybrać coś z ComboBox'a zwłaszcza, że dość często mamy mało miejsca na ekranie.

Generalnie możesz sobie narysować co chcesz, ale to wymaga trochę programowania... samo klikanie nie wystarczy, niestety.

Ja to wiem. Ale to o co pyta założyciel wątku da się niemal wyklikać. Co więcej jakbyś uważnie przeczytał moje posty zauważyłbyś, że odradziłem stosowanie dwóch kolumn i użycie listy obiektów która jest powiązana z listą stringów.

1

Pogrzebałem w dokumentacji i znalazłem coś takiego: TCustomComboBoxEx.

Jak to namierzyłem:

  1. dokumentacja dla TComboBox.
  2. Skok do klasy bazowej TCustomComboBox.
  3. Tam jest taki tekst

Note: To create a combo box class that uses the extended combo box features such as images associated with entries, do not use TCustomComboBox. Instead, use the TCustomComboBoxEx class instead.

Dlatego radzę na to popatrzeć.

1 użytkowników online, w tym zalogowanych: 0, gości: 1